------------------------------------------------------------------------
-- A modality with simultaneous support for affine and linear types
------------------------------------------------------------------------

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

module Graded.Modality.Instances.Linear-or-affine where

import Tools.Algebra
open import Tools.Bool using (T)
open import Tools.Function
open import Tools.Level
open import Tools.Nullary
open import Tools.Product
open import Tools.PropositionalEquality as PE
import Tools.Reasoning.PartialOrder
import Tools.Reasoning.PropositionalEquality
open import Tools.Sum
open import Tools.Unit

import Graded.Modality
open import Graded.FullReduction.Assumptions
import Graded.Modality.Properties.Addition as Addition
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
open import Graded.Modality.Variant lzero
import Graded.Restrictions

import Definition.Typed.Restrictions

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

-- Zero, one, at most one, or unlimited.

data Linear-or-affine : Set where
  𝟘 πŸ™ β‰€πŸ™ ≀ω : Linear-or-affine

open Graded.Modality               Linear-or-affine
open Definition.Typed.Restrictions Linear-or-affine
open Tools.Algebra                 Linear-or-affine

private variable
  p q r   : Linear-or-affine
  variant : Modality-variant
  trs     : Type-restrictions

------------------------------------------------------------------------
-- Basic operations

-- Meet.

infixr 40 _∧_

_∧_ : Linear-or-affine β†’ Linear-or-affine β†’ Linear-or-affine
𝟘  ∧ 𝟘  = 𝟘
πŸ™  ∧ πŸ™  = πŸ™
≀ω ∧ _  = ≀ω
_  ∧ ≀ω = ≀ω
_  ∧ _  = β‰€πŸ™

-- Addition.

infixr 40 _+_

_+_ : Linear-or-affine β†’ Linear-or-affine β†’ Linear-or-affine
𝟘 + q = q
p + 𝟘 = p
_ + _ = ≀ω

-- Multiplication.

infixr 45 _Β·_

_Β·_ : Linear-or-affine β†’ Linear-or-affine β†’ Linear-or-affine
𝟘  · _  = 𝟘
_  · 𝟘  = 𝟘
πŸ™  Β· q  = q
p  Β· πŸ™  = p
β‰€πŸ™ Β· β‰€πŸ™ = β‰€πŸ™
_  Β· _  = ≀ω

------------------------------------------------------------------------
-- Some properties

-- The inferred ordering relation.

infix 10 _≀_

_≀_ : Linear-or-affine β†’ Linear-or-affine β†’ Set
p ≀ q = p ≑ p ∧ q

-- The quantity ≀ω is smaller than all others.

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

-- 𝟘 is maximal.

𝟘-maximal : 𝟘 ≀ p β†’ p ≑ 𝟘
𝟘-maximal {p = 𝟘} refl = refl

-- πŸ™ is maximal.

πŸ™-maximal : πŸ™ ≀ p β†’ p ≑ πŸ™
πŸ™-maximal {p = πŸ™} refl = refl

-- The value ≀ω is a left zero for _+_.

+-zeroΛ‘ : LeftZero ≀ω _+_
+-zeroˑ 𝟘  = refl
+-zeroΛ‘ πŸ™  = refl
+-zeroΛ‘ β‰€πŸ™ = refl
+-zeroΛ‘ ≀ω = refl

-- The value ≀ω is a right zero for _+_.

+-zeroΚ³ : RightZero ≀ω _+_
+-zeroʳ 𝟘  = refl
+-zeroΚ³ πŸ™  = refl
+-zeroΚ³ β‰€πŸ™ = refl
+-zeroΚ³ ≀ω = refl

-- The value ≀ω is a zero for _+_.

+-zero : Zero ≀ω _+_
+-zero = +-zeroΛ‘ , +-zeroΚ³

-- 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 = πŸ™}  {q = ≀ω} _   _   = refl
β‰’πŸ˜+β‰’πŸ˜ {p = β‰€πŸ™} {q = 𝟘}  _   πŸ˜β‰’πŸ˜ = βŠ₯-elim (πŸ˜β‰’πŸ˜ refl)
β‰’πŸ˜+β‰’πŸ˜ {p = β‰€πŸ™} {q = πŸ™}  _   _   = refl
β‰’πŸ˜+β‰’πŸ˜ {p = β‰€πŸ™} {q = β‰€πŸ™} _   _   = refl
β‰’πŸ˜+β‰’πŸ˜ {p = β‰€πŸ™} {q = ≀ω} _   _   = refl
β‰’πŸ˜+β‰’πŸ˜ {p = ≀ω} {q = 𝟘}  _   πŸ˜β‰’πŸ˜ = βŠ₯-elim (πŸ˜β‰’πŸ˜ refl)
β‰’πŸ˜+β‰’πŸ˜ {p = ≀ω} {q = πŸ™}  _   _   = refl
β‰’πŸ˜+β‰’πŸ˜ {p = ≀ω} {q = β‰€πŸ™} _   _   = refl
β‰’πŸ˜+β‰’πŸ˜ {p = ≀ω} {q = ≀ω} _   _   = refl

-- Multiplication is idempotent.

Β·-idempotent : Idempotent _Β·_
·-idempotent 𝟘  = refl
Β·-idempotent πŸ™  = refl
Β·-idempotent β‰€πŸ™ = refl
Β·-idempotent ≀ω = refl

-- Multiplication is commutative.

Β·-comm : Commutative _Β·_
Β·-comm = Ξ» where
  𝟘 𝟘   β†’ refl
  𝟘 πŸ™   β†’ refl
  𝟘 β‰€πŸ™  β†’ refl
  𝟘 ≀ω  β†’ refl
  πŸ™ 𝟘   β†’ refl
  πŸ™ πŸ™   β†’ refl
  πŸ™ β‰€πŸ™  β†’ refl
  πŸ™ ≀ω  β†’ 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
β‰€Ο‰Β·β‰’πŸ˜ {p = ≀ω} _   = refl

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

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

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

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

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

-- The "linear or affine types" semiring with meet

linear-or-affine-semiring-with-meet : Semiring-with-meet
linear-or-affine-semiring-with-meet  = record
  { _+_          = _+_
  ; _Β·_          = _Β·_
  ; _∧_          = _∧_
  ; 𝟘            = 𝟘
  ; πŸ™            = πŸ™
  ; +-Β·-Semiring = record
    { isSemiringWithoutAnnihilatingZero = record
      { +-isCommutativeMonoid = record
        { isMonoid = record
          { isSemigroup = record
            { isMagma = record
              { isEquivalence = PE.isEquivalence
              ; βˆ™-cong        = congβ‚‚ _+_
              }
            ; assoc = +-assoc
            }
          ; identity =
                (Ξ» _ β†’ refl)
              , comm+idΛ‘β‡’idΚ³ +-comm (Ξ» _ β†’ refl)
          }
        ; comm = +-comm
        }
      ; *-isMonoid = record
        { isSemigroup = record
          { isMagma = record
            { isEquivalence = PE.isEquivalence
            ; βˆ™-cong        = congβ‚‚ _Β·_
            }
          ; assoc = Β·-assoc
          }
        ; 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 = ∧-assoc
        }
      ; idem = Ξ» where
          𝟘  β†’ refl
          πŸ™  β†’ refl
          β‰€πŸ™ β†’ refl
          ≀ω β†’ refl
      }
    ; comm = ∧-comm
    }
  ; ·-distrib-∧ =
        ·-distribˑ-∧
      , comm+distrΛ‘β‡’distrΚ³ Β·-comm Β·-distribΛ‘-∧
  ; +-distrib-∧ =
        +-distribˑ-∧
      , comm+distrΛ‘β‡’distrΚ³ +-comm +-distribΛ‘-∧
  }
  where
  +-assoc : Associative _+_
  +-assoc = Ξ» where
    𝟘  _  _  β†’ refl
    πŸ™  𝟘  _  β†’ refl
    πŸ™  πŸ™  𝟘  β†’ refl
    πŸ™  πŸ™  πŸ™  β†’ refl
    πŸ™  πŸ™  β‰€πŸ™ β†’ refl
    πŸ™  πŸ™  ≀ω β†’ refl
    πŸ™  β‰€πŸ™ 𝟘  β†’ refl
    πŸ™  β‰€πŸ™ πŸ™  β†’ refl
    πŸ™  β‰€πŸ™ β‰€πŸ™ β†’ refl
    πŸ™  β‰€πŸ™ ≀ω β†’ refl
    πŸ™  ≀ω 𝟘  β†’ refl
    πŸ™  ≀ω πŸ™  β†’ refl
    πŸ™  ≀ω β‰€πŸ™ β†’ refl
    πŸ™  ≀ω ≀ω β†’ refl
    β‰€πŸ™ 𝟘  _  β†’ refl
    β‰€πŸ™ πŸ™  𝟘  β†’ refl
    β‰€πŸ™ πŸ™  πŸ™  β†’ refl
    β‰€πŸ™ πŸ™  β‰€πŸ™ β†’ refl
    β‰€πŸ™ πŸ™  ≀ω β†’ refl
    β‰€πŸ™ β‰€πŸ™ 𝟘  β†’ refl
    β‰€πŸ™ β‰€πŸ™ πŸ™  β†’ refl
    β‰€πŸ™ β‰€πŸ™ β‰€πŸ™ β†’ refl
    β‰€πŸ™ β‰€πŸ™ ≀ω β†’ refl
    β‰€πŸ™ ≀ω 𝟘  β†’ refl
    β‰€πŸ™ ≀ω πŸ™  β†’ refl
    β‰€πŸ™ ≀ω β‰€πŸ™ β†’ refl
    β‰€πŸ™ ≀ω ≀ω β†’ refl
    ≀ω 𝟘  _  β†’ refl
    ≀ω πŸ™  𝟘  β†’ refl
    ≀ω πŸ™  πŸ™  β†’ refl
    ≀ω πŸ™  β‰€πŸ™ β†’ refl
    ≀ω πŸ™  ≀ω β†’ refl
    ≀ω β‰€πŸ™ 𝟘  β†’ refl
    ≀ω β‰€πŸ™ πŸ™  β†’ refl
    ≀ω β‰€πŸ™ β‰€πŸ™ β†’ refl
    ≀ω β‰€πŸ™ ≀ω β†’ refl
    ≀ω ≀ω 𝟘  β†’ refl
    ≀ω ≀ω πŸ™  β†’ refl
    ≀ω ≀ω β‰€πŸ™ β†’ refl
    ≀ω ≀ω ≀ω β†’ refl

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

  Β·-assoc : Associative _Β·_
  Β·-assoc = Ξ» where
    𝟘  _  _  β†’ refl
    πŸ™  𝟘  _  β†’ refl
    πŸ™  πŸ™  𝟘  β†’ refl
    πŸ™  πŸ™  πŸ™  β†’ refl
    πŸ™  πŸ™  β‰€πŸ™ β†’ refl
    πŸ™  πŸ™  ≀ω β†’ refl
    πŸ™  β‰€πŸ™ 𝟘  β†’ refl
    πŸ™  β‰€πŸ™ πŸ™  β†’ refl
    πŸ™  β‰€πŸ™ β‰€πŸ™ β†’ refl
    πŸ™  β‰€πŸ™ ≀ω β†’ refl
    πŸ™  ≀ω 𝟘  β†’ refl
    πŸ™  ≀ω πŸ™  β†’ refl
    πŸ™  ≀ω β‰€πŸ™ β†’ refl
    πŸ™  ≀ω ≀ω β†’ refl
    β‰€πŸ™ 𝟘  _  β†’ refl
    β‰€πŸ™ πŸ™  𝟘  β†’ refl
    β‰€πŸ™ πŸ™  πŸ™  β†’ refl
    β‰€πŸ™ πŸ™  β‰€πŸ™ β†’ refl
    β‰€πŸ™ πŸ™  ≀ω β†’ refl
    β‰€πŸ™ β‰€πŸ™ 𝟘  β†’ refl
    β‰€πŸ™ β‰€πŸ™ πŸ™  β†’ refl
    β‰€πŸ™ β‰€πŸ™ β‰€πŸ™ β†’ refl
    β‰€πŸ™ β‰€πŸ™ ≀ω β†’ refl
    β‰€πŸ™ ≀ω 𝟘  β†’ refl
    β‰€πŸ™ ≀ω πŸ™  β†’ refl
    β‰€πŸ™ ≀ω β‰€πŸ™ β†’ refl
    β‰€πŸ™ ≀ω ≀ω β†’ refl
    ≀ω 𝟘  _  β†’ refl
    ≀ω πŸ™  𝟘  β†’ refl
    ≀ω πŸ™  πŸ™  β†’ refl
    ≀ω πŸ™  β‰€πŸ™ β†’ refl
    ≀ω πŸ™  ≀ω β†’ refl
    ≀ω β‰€πŸ™ 𝟘  β†’ refl
    ≀ω β‰€πŸ™ πŸ™  β†’ refl
    ≀ω β‰€πŸ™ β‰€πŸ™ β†’ refl
    ≀ω β‰€πŸ™ ≀ω β†’ refl
    ≀ω ≀ω 𝟘  β†’ refl
    ≀ω ≀ω πŸ™  β†’ refl
    ≀ω ≀ω β‰€πŸ™ β†’ refl
    ≀ω ≀ω ≀ω β†’ refl

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

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

  ∧-assoc : Associative _∧_
  ∧-assoc = λ where
    𝟘  𝟘  𝟘  β†’ refl
    𝟘  𝟘  πŸ™  β†’ refl
    𝟘  𝟘  β‰€πŸ™ β†’ refl
    𝟘  𝟘  ≀ω β†’ refl
    𝟘  πŸ™  𝟘  β†’ refl
    𝟘  πŸ™  πŸ™  β†’ refl
    𝟘  πŸ™  β‰€πŸ™ β†’ refl
    𝟘  πŸ™  ≀ω β†’ refl
    𝟘  β‰€πŸ™ 𝟘  β†’ refl
    𝟘  β‰€πŸ™ πŸ™  β†’ refl
    𝟘  β‰€πŸ™ β‰€πŸ™ β†’ refl
    𝟘  β‰€πŸ™ ≀ω β†’ refl
    𝟘  ≀ω 𝟘  β†’ refl
    𝟘  ≀ω πŸ™  β†’ refl
    𝟘  ≀ω β‰€πŸ™ β†’ refl
    𝟘  ≀ω ≀ω β†’ refl
    πŸ™  𝟘  𝟘  β†’ refl
    πŸ™  𝟘  πŸ™  β†’ refl
    πŸ™  𝟘  β‰€πŸ™ β†’ refl
    πŸ™  𝟘  ≀ω β†’ refl
    πŸ™  πŸ™  𝟘  β†’ refl
    πŸ™  πŸ™  πŸ™  β†’ refl
    πŸ™  πŸ™  β‰€πŸ™ β†’ refl
    πŸ™  πŸ™  ≀ω β†’ refl
    πŸ™  β‰€πŸ™ 𝟘  β†’ refl
    πŸ™  β‰€πŸ™ πŸ™  β†’ refl
    πŸ™  β‰€πŸ™ β‰€πŸ™ β†’ refl
    πŸ™  β‰€πŸ™ ≀ω β†’ refl
    πŸ™  ≀ω 𝟘  β†’ refl
    πŸ™  ≀ω πŸ™  β†’ refl
    πŸ™  ≀ω β‰€πŸ™ β†’ refl
    πŸ™  ≀ω ≀ω β†’ refl
    β‰€πŸ™ 𝟘  𝟘  β†’ refl
    β‰€πŸ™ 𝟘  πŸ™  β†’ refl
    β‰€πŸ™ 𝟘  β‰€πŸ™ β†’ refl
    β‰€πŸ™ 𝟘  ≀ω β†’ refl
    β‰€πŸ™ πŸ™  𝟘  β†’ refl
    β‰€πŸ™ πŸ™  πŸ™  β†’ refl
    β‰€πŸ™ πŸ™  β‰€πŸ™ β†’ refl
    β‰€πŸ™ πŸ™  ≀ω β†’ refl
    β‰€πŸ™ β‰€πŸ™ 𝟘  β†’ refl
    β‰€πŸ™ β‰€πŸ™ πŸ™  β†’ refl
    β‰€πŸ™ β‰€πŸ™ β‰€πŸ™ β†’ refl
    β‰€πŸ™ β‰€πŸ™ ≀ω β†’ refl
    β‰€πŸ™ ≀ω 𝟘  β†’ refl
    β‰€πŸ™ ≀ω πŸ™  β†’ refl
    β‰€πŸ™ ≀ω β‰€πŸ™ β†’ refl
    β‰€πŸ™ ≀ω ≀ω β†’ refl
    ≀ω 𝟘  𝟘  β†’ refl
    ≀ω 𝟘  πŸ™  β†’ refl
    ≀ω 𝟘  β‰€πŸ™ β†’ refl
    ≀ω 𝟘  ≀ω β†’ refl
    ≀ω πŸ™  𝟘  β†’ refl
    ≀ω πŸ™  πŸ™  β†’ refl
    ≀ω πŸ™  β‰€πŸ™ β†’ refl
    ≀ω πŸ™  ≀ω β†’ refl
    ≀ω β‰€πŸ™ 𝟘  β†’ refl
    ≀ω β‰€πŸ™ πŸ™  β†’ refl
    ≀ω β‰€πŸ™ β‰€πŸ™ β†’ refl
    ≀ω β‰€πŸ™ ≀ω β†’ refl
    ≀ω ≀ω 𝟘  β†’ refl
    ≀ω ≀ω πŸ™  β†’ refl
    ≀ω ≀ω β‰€πŸ™ β†’ refl
    ≀ω ≀ω ≀ω β†’ refl

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

  ·-distribˑ-∧ : _·_ DistributesOverˑ _∧_
  ·-distribˑ-∧ = λ where
    𝟘  𝟘  𝟘  β†’ refl
    𝟘  𝟘  πŸ™  β†’ refl
    𝟘  𝟘  β‰€πŸ™ β†’ refl
    𝟘  𝟘  ≀ω β†’ refl
    𝟘  πŸ™  𝟘  β†’ refl
    𝟘  πŸ™  πŸ™  β†’ refl
    𝟘  πŸ™  β‰€πŸ™ β†’ refl
    𝟘  πŸ™  ≀ω β†’ refl
    𝟘  β‰€πŸ™ 𝟘  β†’ refl
    𝟘  β‰€πŸ™ πŸ™  β†’ refl
    𝟘  β‰€πŸ™ β‰€πŸ™ β†’ refl
    𝟘  β‰€πŸ™ ≀ω β†’ refl
    𝟘  ≀ω 𝟘  β†’ refl
    𝟘  ≀ω πŸ™  β†’ refl
    𝟘  ≀ω β‰€πŸ™ β†’ refl
    𝟘  ≀ω ≀ω β†’ refl
    πŸ™  𝟘  𝟘  β†’ refl
    πŸ™  𝟘  πŸ™  β†’ refl
    πŸ™  𝟘  β‰€πŸ™ β†’ refl
    πŸ™  𝟘  ≀ω β†’ refl
    πŸ™  πŸ™  𝟘  β†’ refl
    πŸ™  πŸ™  πŸ™  β†’ refl
    πŸ™  πŸ™  β‰€πŸ™ β†’ refl
    πŸ™  πŸ™  ≀ω β†’ refl
    πŸ™  β‰€πŸ™ 𝟘  β†’ refl
    πŸ™  β‰€πŸ™ πŸ™  β†’ refl
    πŸ™  β‰€πŸ™ β‰€πŸ™ β†’ refl
    πŸ™  β‰€πŸ™ ≀ω β†’ refl
    πŸ™  ≀ω 𝟘  β†’ refl
    πŸ™  ≀ω πŸ™  β†’ refl
    πŸ™  ≀ω β‰€πŸ™ β†’ refl
    πŸ™  ≀ω ≀ω β†’ refl
    β‰€πŸ™ 𝟘  𝟘  β†’ refl
    β‰€πŸ™ 𝟘  πŸ™  β†’ refl
    β‰€πŸ™ 𝟘  β‰€πŸ™ β†’ refl
    β‰€πŸ™ 𝟘  ≀ω β†’ refl
    β‰€πŸ™ πŸ™  𝟘  β†’ refl
    β‰€πŸ™ πŸ™  πŸ™  β†’ refl
    β‰€πŸ™ πŸ™  β‰€πŸ™ β†’ refl
    β‰€πŸ™ πŸ™  ≀ω β†’ refl
    β‰€πŸ™ β‰€πŸ™ 𝟘  β†’ refl
    β‰€πŸ™ β‰€πŸ™ πŸ™  β†’ refl
    β‰€πŸ™ β‰€πŸ™ β‰€πŸ™ β†’ refl
    β‰€πŸ™ β‰€πŸ™ ≀ω β†’ refl
    β‰€πŸ™ ≀ω 𝟘  β†’ refl
    β‰€πŸ™ ≀ω πŸ™  β†’ refl
    β‰€πŸ™ ≀ω β‰€πŸ™ β†’ refl
    β‰€πŸ™ ≀ω ≀ω β†’ refl
    ≀ω 𝟘  𝟘  β†’ refl
    ≀ω 𝟘  πŸ™  β†’ refl
    ≀ω 𝟘  β‰€πŸ™ β†’ refl
    ≀ω 𝟘  ≀ω β†’ refl
    ≀ω πŸ™  𝟘  β†’ refl
    ≀ω πŸ™  πŸ™  β†’ refl
    ≀ω πŸ™  β‰€πŸ™ β†’ refl
    ≀ω πŸ™  ≀ω β†’ refl
    ≀ω β‰€πŸ™ 𝟘  β†’ refl
    ≀ω β‰€πŸ™ πŸ™  β†’ refl
    ≀ω β‰€πŸ™ β‰€πŸ™ β†’ refl
    ≀ω β‰€πŸ™ ≀ω β†’ refl
    ≀ω ≀ω 𝟘  β†’ refl
    ≀ω ≀ω πŸ™  β†’ refl
    ≀ω ≀ω β‰€πŸ™ β†’ refl
    ≀ω ≀ω ≀ω β†’ refl

  +-distribˑ-∧ : _+_ DistributesOverˑ _∧_
  +-distribˑ-∧ = λ where
    𝟘  𝟘  𝟘  β†’ refl
    𝟘  𝟘  πŸ™  β†’ refl
    𝟘  𝟘  β‰€πŸ™ β†’ refl
    𝟘  𝟘  ≀ω β†’ refl
    𝟘  πŸ™  𝟘  β†’ refl
    𝟘  πŸ™  πŸ™  β†’ refl
    𝟘  πŸ™  β‰€πŸ™ β†’ refl
    𝟘  πŸ™  ≀ω β†’ refl
    𝟘  β‰€πŸ™ 𝟘  β†’ refl
    𝟘  β‰€πŸ™ πŸ™  β†’ refl
    𝟘  β‰€πŸ™ β‰€πŸ™ β†’ refl
    𝟘  β‰€πŸ™ ≀ω β†’ refl
    𝟘  ≀ω 𝟘  β†’ refl
    𝟘  ≀ω πŸ™  β†’ refl
    𝟘  ≀ω β‰€πŸ™ β†’ refl
    𝟘  ≀ω ≀ω β†’ refl
    πŸ™  𝟘  𝟘  β†’ refl
    πŸ™  𝟘  πŸ™  β†’ refl
    πŸ™  𝟘  β‰€πŸ™ β†’ refl
    πŸ™  𝟘  ≀ω β†’ refl
    πŸ™  πŸ™  𝟘  β†’ refl
    πŸ™  πŸ™  πŸ™  β†’ refl
    πŸ™  πŸ™  β‰€πŸ™ β†’ refl
    πŸ™  πŸ™  ≀ω β†’ refl
    πŸ™  β‰€πŸ™ 𝟘  β†’ refl
    πŸ™  β‰€πŸ™ πŸ™  β†’ refl
    πŸ™  β‰€πŸ™ β‰€πŸ™ β†’ refl
    πŸ™  β‰€πŸ™ ≀ω β†’ refl
    πŸ™  ≀ω 𝟘  β†’ refl
    πŸ™  ≀ω πŸ™  β†’ refl
    πŸ™  ≀ω β‰€πŸ™ β†’ refl
    πŸ™  ≀ω ≀ω β†’ refl
    β‰€πŸ™ 𝟘  𝟘  β†’ refl
    β‰€πŸ™ 𝟘  πŸ™  β†’ refl
    β‰€πŸ™ 𝟘  β‰€πŸ™ β†’ refl
    β‰€πŸ™ 𝟘  ≀ω β†’ refl
    β‰€πŸ™ πŸ™  𝟘  β†’ refl
    β‰€πŸ™ πŸ™  πŸ™  β†’ refl
    β‰€πŸ™ πŸ™  β‰€πŸ™ β†’ refl
    β‰€πŸ™ πŸ™  ≀ω β†’ refl
    β‰€πŸ™ β‰€πŸ™ 𝟘  β†’ refl
    β‰€πŸ™ β‰€πŸ™ πŸ™  β†’ refl
    β‰€πŸ™ β‰€πŸ™ β‰€πŸ™ β†’ refl
    β‰€πŸ™ β‰€πŸ™ ≀ω β†’ refl
    β‰€πŸ™ ≀ω 𝟘  β†’ refl
    β‰€πŸ™ ≀ω πŸ™  β†’ refl
    β‰€πŸ™ ≀ω β‰€πŸ™ β†’ refl
    β‰€πŸ™ ≀ω ≀ω β†’ refl
    ≀ω 𝟘  𝟘  β†’ refl
    ≀ω 𝟘  πŸ™  β†’ refl
    ≀ω 𝟘  β‰€πŸ™ β†’ refl
    ≀ω 𝟘  ≀ω β†’ refl
    ≀ω πŸ™  𝟘  β†’ refl
    ≀ω πŸ™  πŸ™  β†’ refl
    ≀ω πŸ™  β‰€πŸ™ β†’ refl
    ≀ω πŸ™  ≀ω β†’ refl
    ≀ω β‰€πŸ™ 𝟘  β†’ refl
    ≀ω β‰€πŸ™ πŸ™  β†’ refl
    ≀ω β‰€πŸ™ β‰€πŸ™ β†’ refl
    ≀ω β‰€πŸ™ ≀ω β†’ refl
    ≀ω ≀ω 𝟘  β†’ refl
    ≀ω ≀ω πŸ™  β†’ refl
    ≀ω ≀ω β‰€πŸ™ β†’ refl
    ≀ω ≀ω ≀ω β†’ refl

-- The semiring has a well behaved zero

linear-or-affine-has-well-behaved-zero : Has-well-behaved-zero linear-or-affine-semiring-with-meet
linear-or-affine-has-well-behaved-zero = record
  { πŸ™β‰’πŸ˜ = Ξ» ()
  ; is-𝟘? = λ where
      𝟘  β†’ yes refl
      πŸ™  β†’ no (Ξ» ())
      β‰€πŸ™ β†’ no (Ξ» ())
      ≀ω β†’ no (Ξ» ())
  ; zero-product = Ξ» where
      {p = 𝟘} _ β†’ inj₁ refl
      {q = 𝟘} _ β†’ injβ‚‚ refl
  ; +-positiveΛ‘ = Ξ» where
      {p = 𝟘} {q = 𝟘}  _  β†’ refl
      {p = 𝟘} {q = πŸ™}  _  β†’ refl
      {p = 𝟘} {q = β‰€πŸ™} ()
      {p = 𝟘} {q = ≀ω} ()
  ; ∧-positiveˑ = λ where
      {p = 𝟘} {q = 𝟘}  _  β†’ refl
      {p = 𝟘} {q = πŸ™}  _  β†’ refl
      {p = 𝟘} {q = β‰€πŸ™} ()
      {p = 𝟘} {q = ≀ω} ()
  }

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

-- Some requirements of a star operation.

Star-requirements :
  (Linear-or-affine β†’ Linear-or-affine β†’ Linear-or-affine β†’
   Linear-or-affine) β†’
  Set
Star-requirements _βŠ›_β–·_ =
  (βˆ€ {q r} β†’                     (≀ω βŠ› q  β–· r)  ≑ ≀ω) Γ—
  (βˆ€ {p r} β†’                     (p  βŠ› ≀ω β–· r)  ≑ ≀ω) Γ—
  (βˆ€ {p q} β†’ Β¬ (p ≑ 𝟘 Γ— q ≑ 𝟘) β†’ (p  βŠ› q  β–· ≀ω) ≑ ≀ω) Γ—
  (βˆ€ {r} β†’                       (𝟘  βŠ› 𝟘  β–· r)  ≑ 𝟘)  Γ—
  (βˆ€ {p} β†’                       (p  βŠ› πŸ™  β–· πŸ™)  ≑ ≀ω) Γ—
  (βˆ€ {p} β†’                       (p  βŠ› πŸ™  β–· β‰€πŸ™) ≑ ≀ω) Γ—
  (βˆ€ {p} β†’                       (p  βŠ› β‰€πŸ™ β–· πŸ™)  ≑ ≀ω) Γ—
  (βˆ€ {p} β†’                       (p  βŠ› β‰€πŸ™ β–· β‰€πŸ™) ≑ ≀ω) Γ—
                                ((𝟘  βŠ› πŸ™  β–· 𝟘)  ≀ β‰€πŸ™) Γ—
                                ((𝟘  βŠ› β‰€πŸ™ β–· 𝟘)  ≀ β‰€πŸ™) Γ—
                                ((πŸ™  βŠ› 𝟘  β–· 𝟘)  ≀ β‰€πŸ™) Γ—
                                ((β‰€πŸ™ βŠ› 𝟘  β–· 𝟘)  ≀ β‰€πŸ™) Γ—
                                ((πŸ™  βŠ› 𝟘  β–· πŸ™)  ≀ πŸ™)  Γ—
                                ((πŸ™  βŠ› 𝟘  β–· β‰€πŸ™) ≀ β‰€πŸ™) Γ—
                                ((β‰€πŸ™ βŠ› 𝟘  β–· πŸ™)  ≀ β‰€πŸ™) Γ—
                                ((β‰€πŸ™ βŠ› 𝟘  β–· β‰€πŸ™) ≀ β‰€πŸ™) Γ—
                                ((πŸ™  βŠ› πŸ™  β–· 𝟘)  ≀ πŸ™)  Γ—
                                ((πŸ™  βŠ› β‰€πŸ™ β–· 𝟘)  ≀ β‰€πŸ™) Γ—
                                ((β‰€πŸ™ βŠ› πŸ™  β–· 𝟘)  ≀ β‰€πŸ™) Γ—
                                ((β‰€πŸ™ βŠ› β‰€πŸ™ β–· 𝟘)  ≀ β‰€πŸ™)

-- A star operation for a ModalityWithoutβŠ› for Linear-or-affine for
-- which the zero is 𝟘, the one is πŸ™, addition is _+_, multiplication
-- is _·_, and the meet operation is _∧_ has to satisfy the
-- Star-requirements 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 ≑ _∧_ β†’
  (_βŠ›_β–·_ :
   Linear-or-affine β†’ Linear-or-affine β†’ Linear-or-affine β†’
   Linear-or-affine) β†’
  (βˆ€ 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 refl refl refl refl refl star βŠ›-ineq₁ βŠ›-ineqβ‚‚ Β·-sub-distribΚ³-βŠ› =
    (Ξ» {_ _} β†’ Ο‰βŠ›β–·)
  , (Ξ» {_ _} β†’ βŠ›Ο‰β–·)
  , (Ξ» {_ _} β†’ βŠ›β–·Ο‰ _ _)
  , (Ξ» {r = r} β†’ ≀-antisym
       (begin
          𝟘 βŠ› 𝟘 β–· r  β‰€βŸ¨ βŠ›-ineqβ‚‚ _ _ _ ⟩
          𝟘          ∎)
       (begin
          𝟘              β‰‘Λ˜βŸ¨ Β·-zeroΚ³ (𝟘 βŠ› 𝟘 β–· r) ⟩
          𝟘 βŠ› 𝟘 β–· r Β· 𝟘  β‰€βŸ¨ Β·-sub-distribΚ³-βŠ› _ _ _ _ ⟩
          𝟘 βŠ› 𝟘 β–· r      ∎))
  , (Ξ» {p = p} β†’ ≀-antisym
       (begin
          p βŠ› πŸ™ β–· πŸ™          β‰€βŸ¨ βŠ›-ineq₁ _ _ _ ⟩
          πŸ™ + πŸ™ Β· p βŠ› πŸ™ β–· πŸ™  β‰ˆβŸ¨ β‰’πŸ˜+β‰’πŸ˜ {p = πŸ™} (Ξ» ()) (πŸ™Β·β‰’πŸ˜ βŠ›πŸ™β–·) ⟩
          ≀ω                 ∎)
       (≀ω≀ (p βŠ› πŸ™ β–· πŸ™)))
  , (Ξ» {p = p} β†’ ≀-antisym
       (begin
          p βŠ› πŸ™ β–· β‰€πŸ™           β‰€βŸ¨ βŠ›-ineq₁ _ _ _ ⟩
          πŸ™ + β‰€πŸ™ Β· p βŠ› πŸ™ β–· β‰€πŸ™  β‰ˆβŸ¨ β‰’πŸ˜+β‰’πŸ˜ {p = πŸ™} (Ξ» ()) (β‰€πŸ™Β·β‰’πŸ˜ βŠ›πŸ™β–·) ⟩
          ≀ω                   ∎)
       (≀ω≀ (p βŠ› πŸ™ β–· β‰€πŸ™)))
  , (Ξ» {p = p} β†’ ≀-antisym
       (begin
          p βŠ› β‰€πŸ™ β–· πŸ™           β‰€βŸ¨ βŠ›-ineq₁ _ _ _ ⟩
          β‰€πŸ™ + πŸ™ Β· p βŠ› β‰€πŸ™ β–· πŸ™  β‰ˆβŸ¨ β‰’πŸ˜+β‰’πŸ˜ {p = β‰€πŸ™} (Ξ» ()) (πŸ™Β·β‰’πŸ˜ βŠ›β‰€πŸ™β–·) ⟩
          ≀ω                   ∎)
       (≀ω≀ (p βŠ› β‰€πŸ™ β–· πŸ™)))
  , (Ξ» {p = p} β†’ ≀-antisym
       (begin
          p βŠ› β‰€πŸ™ β–· β‰€πŸ™            β‰€βŸ¨ βŠ›-ineq₁ _ _ _ ⟩
          β‰€πŸ™ + β‰€πŸ™ Β· p βŠ› β‰€πŸ™ β–· β‰€πŸ™  β‰ˆβŸ¨ β‰’πŸ˜+β‰’πŸ˜ {p = β‰€πŸ™} (Ξ» ()) (β‰€πŸ™Β·β‰’πŸ˜ βŠ›β‰€πŸ™β–·) ⟩
          ≀ω                     ∎)
       (≀ω≀ (p βŠ› β‰€πŸ™ β–· β‰€πŸ™)))
  , ∧-greatest-lower-bound
      (βŠ›-ineqβ‚‚ _ _ _)
      (begin
         𝟘 βŠ› πŸ™ β–· 𝟘          β‰€βŸ¨ βŠ›-ineq₁ _ _ _ ⟩
         πŸ™ + 𝟘 Β· 𝟘 βŠ› πŸ™ β–· 𝟘  β‰‘βŸ¨βŸ©
         πŸ™                  ∎)
  , (begin
       𝟘 βŠ› β‰€πŸ™ β–· 𝟘           β‰€βŸ¨ βŠ›-ineq₁ _ _ _ ⟩
       β‰€πŸ™ + 𝟘 Β· 𝟘 βŠ› β‰€πŸ™ β–· 𝟘  β‰‘βŸ¨βŸ©
       β‰€πŸ™                   ∎)
  , ∧-greatest-lower-bound
      (begin
         πŸ™ βŠ› 𝟘 β–· 𝟘          β‰€βŸ¨ βŠ›-ineq₁ _ _ _ ⟩
         𝟘 + 𝟘 Β· πŸ™ βŠ› 𝟘 β–· 𝟘  β‰‘βŸ¨βŸ©
         𝟘                  ∎)
      (βŠ›-ineqβ‚‚ _ _ _)
  , βŠ›-ineqβ‚‚ _ _ _
  , βŠ›-ineqβ‚‚ _ _ _
  , (begin
       πŸ™ βŠ› 𝟘 β–· β‰€πŸ™       β‰€βŸ¨ βŠ›-ineq₁ _ _ _ ⟩
       β‰€πŸ™ Β· πŸ™ βŠ› 𝟘 β–· β‰€πŸ™  β‰€βŸ¨ Β·-monotoneΚ³ {r = β‰€πŸ™} (βŠ›-ineqβ‚‚ _ _ _) ⟩
       β‰€πŸ™ Β· πŸ™           β‰‘βŸ¨βŸ©
       β‰€πŸ™               ∎)
  , βŠ›-ineqβ‚‚ _ _ _
  , βŠ›-ineqβ‚‚ _ _ _
  , βŠ›-ineqβ‚‚ _ _ _
  , (begin
       πŸ™ βŠ› β‰€πŸ™ β–· 𝟘           β‰€βŸ¨ βŠ›-ineq₁ _ _ _ ⟩
       β‰€πŸ™ + 𝟘 Β· πŸ™ βŠ› β‰€πŸ™ β–· 𝟘  β‰‘βŸ¨βŸ©
       β‰€πŸ™                   ∎)
  , βŠ›-ineqβ‚‚ _ _ _
  , βŠ›-ineqβ‚‚ _ _ _
  where
  open Semiring-with-meet M using (Β·-zeroΚ³)
  open PartialOrder M
  open Meet M
  open Multiplication M
  open Tools.Reasoning.PartialOrder ≀-poset

  infix 50 _βŠ›_β–·_

  _βŠ›_β–·_ :
    Linear-or-affine β†’ Linear-or-affine β†’ Linear-or-affine β†’
    Linear-or-affine
  _βŠ›_β–·_ = 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  β‰‘βŸ¨ +-zeroΛ‘ (r Β· _) ⟩
       ≀ω                   ∎)
    (≀ω≀ (p βŠ› ≀ω β–· r))

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

  β‰€πŸ™βŠ›β–· : β‰€πŸ™ βŠ› 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 βŠ› β‰€πŸ™ β–· 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 βŠ› πŸ™ β–· ≀ω))
  βŠ›β–·Ο‰ p β‰€πŸ™ _ = ≀-antisym
    (begin
       p βŠ› β‰€πŸ™ β–· ≀ω            β‰€βŸ¨ βŠ›-ineq₁ _ _ _ ⟩
       β‰€πŸ™ + ≀ω Β· p βŠ› β‰€πŸ™ β–· ≀ω  β‰‘βŸ¨ cong (β‰€πŸ™ +_) (β‰€Ο‰Β·β‰’πŸ˜ βŠ›β‰€πŸ™β–·) ⟩
       β‰€πŸ™ + ≀ω                β‰‘βŸ¨βŸ©
       ≀ω                     ∎)
    (≀ω≀ (p βŠ› πŸ™ β–· ≀ω))
  βŠ›β–·Ο‰ πŸ™ 𝟘 _ = ≀-antisym
    (begin
       πŸ™ βŠ› 𝟘 β–· ≀ω       β‰€βŸ¨ βŠ›-ineq₁ _ _ _ ⟩
       ≀ω Β· πŸ™ βŠ› 𝟘 β–· ≀ω  β‰ˆβŸ¨ β‰€Ο‰Β·β‰’πŸ˜ πŸ™βŠ›β–· ⟩
       ≀ω               ∎)
    (≀ω≀ (πŸ™ βŠ› 𝟘 β–· ≀ω))
  βŠ›β–·Ο‰ β‰€πŸ™ 𝟘 _ = ≀-antisym
    (begin
       β‰€πŸ™ βŠ› 𝟘 β–· ≀ω       β‰€βŸ¨ βŠ›-ineq₁ _ _ _ ⟩
       ≀ω Β· β‰€πŸ™ βŠ› 𝟘 β–· ≀ω  β‰ˆβŸ¨ β‰€Ο‰Β·β‰’πŸ˜ β‰€πŸ™βŠ›β–· ⟩
       ≀ω                ∎)
    (≀ω≀ (β‰€πŸ™ βŠ› 𝟘 β–· ≀ω))

-- Every natrec-star operator for linear-or-affine-semiring-with-meet
-- has to satisfy the Star-requirements.

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

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

infix 50 _βŠ›_β–·_

_βŠ›_β–·_ :
  Linear-or-affine β†’ Linear-or-affine β†’ Linear-or-affine β†’
  Linear-or-affine
p βŠ› q β–· 𝟘  = p ∧ q
p βŠ› q β–· πŸ™  = p + ≀ω Β· q
p βŠ› q β–· β‰€πŸ™ = p ∧ ≀ω Β· q
p βŠ› q β–· ≀ω = ≀ω Β· (p ∧ q)

-- A simplification lemma for the star operation.

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

-- A simplification lemma for the star operation.

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

-- A simplification lemma for the star operation.

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

-- A simplification lemma for the star operation.

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

-- A simplification lemma for the star operation.

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

-- A simplification lemma for the star operation.

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

-- A simplification lemma for the star operation.

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

-- A simplification lemma for the star operation.

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

-- The natrec-star operator returns results that are at least as large
-- as those of any other natrec-star operator for
-- linear-or-affine-semiring-with-meet.

βŠ›-greatest :
  (has-star : Has-star linear-or-affine-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
    ≀ω q r β†’ begin
      ≀ω βŠ› q β–·β€² r  β‰ˆβŸ¨ β‰€Ο‰βŠ›β–·β€² ⟩
      ≀ω           β‰ˆΛ˜βŸ¨ β‰€Ο‰βŠ›β–· r ⟩
      ≀ω βŠ› q β–· r   ∎
    p ≀ω r β†’ begin
      p βŠ› ≀ω β–·β€² r  β‰ˆβŸ¨ βŠ›β‰€Ο‰β–·β€² ⟩
      ≀ω           β‰ˆΛ˜βŸ¨ βŠ›β‰€Ο‰β–· r ⟩
      p βŠ› ≀ω β–· r   ∎
    𝟘 𝟘 r β†’ begin
      𝟘 βŠ› 𝟘 β–·β€² r  β‰ˆβŸ¨ πŸ˜βŠ›πŸ˜β–·β€² ⟩
      𝟘           β‰ˆΛ˜βŸ¨ πŸ˜βŠ›πŸ˜β–· r ⟩
      𝟘 βŠ› 𝟘 β–· r   ∎
    𝟘 πŸ™ ≀ω β†’ begin
      𝟘 βŠ› πŸ™ β–·β€² ≀ω  β‰ˆβŸ¨ βŠ›β–·β€²β‰€Ο‰ (Ξ» { (_ , ()) }) ⟩
      ≀ω           β‰ˆΛ˜βŸ¨ βŠ›β–·β‰€Ο‰ 𝟘 πŸ™ (Ξ» { (_ , ()) }) ⟩
      𝟘 βŠ› πŸ™ β–· ≀ω   ∎
    𝟘 β‰€πŸ™ ≀ω β†’ begin
      𝟘 βŠ› β‰€πŸ™ β–·β€² ≀ω  β‰ˆβŸ¨ βŠ›β–·β€²β‰€Ο‰ (Ξ» { (_ , ()) }) ⟩
      ≀ω            β‰ˆΛ˜βŸ¨ βŠ›β–·β‰€Ο‰ 𝟘 πŸ™ (Ξ» { (_ , ()) }) ⟩
      𝟘 βŠ› β‰€πŸ™ β–· ≀ω   ∎
    πŸ™ q ≀ω β†’ begin
      πŸ™ βŠ› q β–·β€² ≀ω  β‰ˆβŸ¨ βŠ›β–·β€²β‰€Ο‰ (Ξ» { (() , _) }) ⟩
      ≀ω           β‰ˆΛ˜βŸ¨ βŠ›β–·β‰€Ο‰ πŸ™ q (Ξ» { (() , _) }) ⟩
      πŸ™ βŠ› q β–· ≀ω   ∎
    β‰€πŸ™ q ≀ω β†’ begin
      β‰€πŸ™ βŠ› q β–·β€² ≀ω  β‰ˆβŸ¨ βŠ›β–·β€²β‰€Ο‰ (Ξ» { (() , _) }) ⟩
      ≀ω            β‰ˆΛ˜βŸ¨ βŠ›β–·β‰€Ο‰ β‰€πŸ™ q (Ξ» { (() , _) }) ⟩
      β‰€πŸ™ βŠ› q β–· ≀ω   ∎
    p πŸ™ πŸ™ β†’ begin
      p βŠ› πŸ™ β–·β€² πŸ™  β‰ˆβŸ¨ βŠ›πŸ™β–·β€²πŸ™ ⟩
      ≀ω          β‰ˆΛ˜βŸ¨ βŠ›πŸ™β–·πŸ™ p ⟩
      p βŠ› πŸ™ β–· πŸ™   ∎
    p β‰€πŸ™ πŸ™ β†’ begin
      p βŠ› β‰€πŸ™ β–·β€² πŸ™  β‰ˆβŸ¨ βŠ›β‰€πŸ™β–·β€²πŸ™ ⟩
      ≀ω           β‰ˆΛ˜βŸ¨ βŠ›β‰€πŸ™β–·πŸ™ p ⟩
      p βŠ› β‰€πŸ™ β–· πŸ™   ∎
    p πŸ™ β‰€πŸ™ β†’ begin
      p βŠ› πŸ™ β–·β€² β‰€πŸ™  β‰ˆβŸ¨ βŠ›πŸ™β–·β€²β‰€πŸ™ ⟩
      ≀ω           β‰ˆΛ˜βŸ¨ βŠ›πŸ™β–·β‰€πŸ™ p ⟩
      p βŠ› πŸ™ β–· β‰€πŸ™   ∎
    p β‰€πŸ™ β‰€πŸ™ β†’ begin
      p βŠ› β‰€πŸ™ β–·β€² β‰€πŸ™  β‰ˆβŸ¨ βŠ›β‰€πŸ™β–·β€²β‰€πŸ™ ⟩
      ≀ω            β‰ˆΛ˜βŸ¨ βŠ›β‰€πŸ™β–·β‰€πŸ™ p ⟩
      p βŠ› β‰€πŸ™ β–· β‰€πŸ™   ∎
    𝟘 πŸ™ 𝟘 β†’ begin
      𝟘 βŠ› πŸ™ β–·β€² 𝟘  β‰€βŸ¨ πŸ˜βŠ›πŸ™β–·β€²πŸ˜ ⟩
      β‰€πŸ™          ∎
    𝟘 β‰€πŸ™ 𝟘 β†’ begin
      𝟘 βŠ› β‰€πŸ™ β–·β€² 𝟘  β‰€βŸ¨ πŸ˜βŠ›β‰€πŸ™β–·β€²πŸ˜ ⟩
      β‰€πŸ™           ∎
    πŸ™ 𝟘 𝟘 β†’ begin
      πŸ™ βŠ› 𝟘 β–·β€² 𝟘  β‰€βŸ¨ πŸ™βŠ›πŸ˜β–·β€²πŸ˜ ⟩
      β‰€πŸ™          ∎
    β‰€πŸ™ 𝟘 𝟘 β†’ begin
      β‰€πŸ™ βŠ› 𝟘 β–·β€² 𝟘  β‰€βŸ¨ β‰€πŸ™βŠ›πŸ˜β–·β€²πŸ˜ ⟩
      β‰€πŸ™           ∎
    πŸ™ 𝟘 πŸ™ β†’ begin
      πŸ™ βŠ› 𝟘 β–·β€² πŸ™  β‰€βŸ¨ πŸ™βŠ›πŸ˜β–·β€²πŸ™ ⟩
      πŸ™           ∎
    πŸ™ 𝟘 β‰€πŸ™ β†’ begin
      πŸ™ βŠ› 𝟘 β–·β€² β‰€πŸ™  β‰€βŸ¨ πŸ™βŠ›πŸ˜β–·β€²β‰€πŸ™ ⟩
      β‰€πŸ™           ∎
    β‰€πŸ™ 𝟘 πŸ™ β†’ begin
      β‰€πŸ™ βŠ› 𝟘 β–·β€² πŸ™  β‰€βŸ¨ β‰€πŸ™βŠ›πŸ˜β–·β€²πŸ™ ⟩
      β‰€πŸ™           ∎
    β‰€πŸ™ 𝟘 β‰€πŸ™ β†’ begin
      β‰€πŸ™ βŠ› 𝟘 β–·β€² β‰€πŸ™  β‰€βŸ¨ β‰€πŸ™βŠ›πŸ˜β–·β€²β‰€πŸ™ ⟩
      β‰€πŸ™            ∎
    πŸ™ πŸ™ 𝟘 β†’ begin
      πŸ™ βŠ› πŸ™ β–·β€² 𝟘  β‰€βŸ¨ πŸ™βŠ›πŸ™β–·β€²πŸ˜ ⟩
      πŸ™           ∎
    πŸ™ β‰€πŸ™ 𝟘 β†’ begin
      πŸ™ βŠ› β‰€πŸ™ β–·β€² 𝟘  β‰€βŸ¨ πŸ™βŠ›β‰€πŸ™β–·β€²πŸ˜ ⟩
      β‰€πŸ™           ∎
    β‰€πŸ™ πŸ™ 𝟘 β†’ begin
      β‰€πŸ™ βŠ› πŸ™ β–·β€² 𝟘  β‰€βŸ¨ β‰€πŸ™βŠ›πŸ™β–·β€²πŸ˜ ⟩
      β‰€πŸ™           ∎
    β‰€πŸ™ β‰€πŸ™ 𝟘 β†’ begin
      β‰€πŸ™ βŠ› β‰€πŸ™ β–·β€² 𝟘  β‰€βŸ¨ β‰€πŸ™βŠ›β‰€πŸ™β–·β€²πŸ˜ ⟩
      β‰€πŸ™            ∎
  where
  open Has-star has-star renaming (_βŠ›_β–·_ to _βŠ›_β–·β€²_)
  open PartialOrder linear-or-affine-semiring-with-meet
  open Tools.Reasoning.PartialOrder ≀-poset

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

linear-or-affine-has-star :
  Has-star linear-or-affine-semiring-with-meet
linear-or-affine-has-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 = linear-or-affine-semiring-with-meet

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

  βŠ›-ineq₁ : βˆ€ p q r β†’ p βŠ› q β–· r ≀ q + r Β· p βŠ› q β–· r
  βŠ›-ineq₁ = Ξ» where
    𝟘  𝟘  𝟘  β†’ refl
    𝟘  𝟘  πŸ™  β†’ refl
    𝟘  𝟘  β‰€πŸ™ β†’ refl
    𝟘  𝟘  ≀ω β†’ refl
    𝟘  πŸ™  𝟘  β†’ refl
    𝟘  πŸ™  πŸ™  β†’ refl
    𝟘  πŸ™  β‰€πŸ™ β†’ refl
    𝟘  πŸ™  ≀ω β†’ refl
    𝟘  β‰€πŸ™ 𝟘  β†’ refl
    𝟘  β‰€πŸ™ πŸ™  β†’ refl
    𝟘  β‰€πŸ™ β‰€πŸ™ β†’ refl
    𝟘  β‰€πŸ™ ≀ω β†’ refl
    𝟘  ≀ω 𝟘  β†’ refl
    𝟘  ≀ω πŸ™  β†’ refl
    𝟘  ≀ω β‰€πŸ™ β†’ refl
    𝟘  ≀ω ≀ω β†’ refl
    πŸ™  𝟘  𝟘  β†’ refl
    πŸ™  𝟘  πŸ™  β†’ refl
    πŸ™  𝟘  β‰€πŸ™ β†’ refl
    πŸ™  𝟘  ≀ω β†’ refl
    πŸ™  πŸ™  𝟘  β†’ refl
    πŸ™  πŸ™  πŸ™  β†’ refl
    πŸ™  πŸ™  β‰€πŸ™ β†’ refl
    πŸ™  πŸ™  ≀ω β†’ refl
    πŸ™  β‰€πŸ™ 𝟘  β†’ refl
    πŸ™  β‰€πŸ™ πŸ™  β†’ refl
    πŸ™  β‰€πŸ™ β‰€πŸ™ β†’ refl
    πŸ™  β‰€πŸ™ ≀ω β†’ refl
    πŸ™  ≀ω 𝟘  β†’ refl
    πŸ™  ≀ω πŸ™  β†’ refl
    πŸ™  ≀ω β‰€πŸ™ β†’ refl
    πŸ™  ≀ω ≀ω β†’ refl
    β‰€πŸ™ 𝟘  𝟘  β†’ refl
    β‰€πŸ™ 𝟘  πŸ™  β†’ refl
    β‰€πŸ™ 𝟘  β‰€πŸ™ β†’ refl
    β‰€πŸ™ 𝟘  ≀ω β†’ refl
    β‰€πŸ™ πŸ™  𝟘  β†’ refl
    β‰€πŸ™ πŸ™  πŸ™  β†’ refl
    β‰€πŸ™ πŸ™  β‰€πŸ™ β†’ refl
    β‰€πŸ™ πŸ™  ≀ω β†’ refl
    β‰€πŸ™ β‰€πŸ™ 𝟘  β†’ refl
    β‰€πŸ™ β‰€πŸ™ πŸ™  β†’ refl
    β‰€πŸ™ β‰€πŸ™ β‰€πŸ™ β†’ refl
    β‰€πŸ™ β‰€πŸ™ ≀ω β†’ refl
    β‰€πŸ™ ≀ω 𝟘  β†’ refl
    β‰€πŸ™ ≀ω πŸ™  β†’ refl
    β‰€πŸ™ ≀ω β‰€πŸ™ β†’ refl
    β‰€πŸ™ ≀ω ≀ω β†’ refl
    ≀ω 𝟘  𝟘  β†’ refl
    ≀ω 𝟘  πŸ™  β†’ refl
    ≀ω 𝟘  β‰€πŸ™ β†’ refl
    ≀ω 𝟘  ≀ω β†’ refl
    ≀ω πŸ™  𝟘  β†’ refl
    ≀ω πŸ™  πŸ™  β†’ refl
    ≀ω πŸ™  β‰€πŸ™ β†’ refl
    ≀ω πŸ™  ≀ω β†’ refl
    ≀ω β‰€πŸ™ 𝟘  β†’ refl
    ≀ω β‰€πŸ™ πŸ™  β†’ refl
    ≀ω β‰€πŸ™ β‰€πŸ™ β†’ refl
    ≀ω β‰€πŸ™ ≀ω β†’ refl
    ≀ω ≀ω 𝟘  β†’ refl
    ≀ω ≀ω πŸ™  β†’ refl
    ≀ω ≀ω β‰€πŸ™ β†’ refl
    ≀ω ≀ω ≀ω β†’ refl

  βŠ›-ineqβ‚‚ : βˆ€ p q r β†’ (p βŠ› q β–· r) ≀ p
  βŠ›-ineqβ‚‚ = Ξ» where
    𝟘  𝟘  𝟘  β†’ refl
    𝟘  𝟘  πŸ™  β†’ refl
    𝟘  𝟘  β‰€πŸ™ β†’ refl
    𝟘  𝟘  ≀ω β†’ refl
    𝟘  πŸ™  𝟘  β†’ refl
    𝟘  πŸ™  πŸ™  β†’ refl
    𝟘  πŸ™  β‰€πŸ™ β†’ refl
    𝟘  πŸ™  ≀ω β†’ refl
    𝟘  β‰€πŸ™ 𝟘  β†’ refl
    𝟘  β‰€πŸ™ πŸ™  β†’ refl
    𝟘  β‰€πŸ™ β‰€πŸ™ β†’ refl
    𝟘  β‰€πŸ™ ≀ω β†’ refl
    𝟘  ≀ω 𝟘  β†’ refl
    𝟘  ≀ω πŸ™  β†’ refl
    𝟘  ≀ω β‰€πŸ™ β†’ refl
    𝟘  ≀ω ≀ω β†’ refl
    πŸ™  𝟘  𝟘  β†’ refl
    πŸ™  𝟘  πŸ™  β†’ refl
    πŸ™  𝟘  β‰€πŸ™ β†’ refl
    πŸ™  𝟘  ≀ω β†’ refl
    πŸ™  πŸ™  𝟘  β†’ refl
    πŸ™  πŸ™  πŸ™  β†’ refl
    πŸ™  πŸ™  β‰€πŸ™ β†’ refl
    πŸ™  πŸ™  ≀ω β†’ refl
    πŸ™  β‰€πŸ™ 𝟘  β†’ refl
    πŸ™  β‰€πŸ™ πŸ™  β†’ refl
    πŸ™  β‰€πŸ™ β‰€πŸ™ β†’ refl
    πŸ™  β‰€πŸ™ ≀ω β†’ refl
    πŸ™  ≀ω 𝟘  β†’ refl
    πŸ™  ≀ω πŸ™  β†’ refl
    πŸ™  ≀ω β‰€πŸ™ β†’ refl
    πŸ™  ≀ω ≀ω β†’ refl
    β‰€πŸ™ 𝟘  𝟘  β†’ refl
    β‰€πŸ™ 𝟘  πŸ™  β†’ refl
    β‰€πŸ™ 𝟘  β‰€πŸ™ β†’ refl
    β‰€πŸ™ 𝟘  ≀ω β†’ refl
    β‰€πŸ™ πŸ™  𝟘  β†’ refl
    β‰€πŸ™ πŸ™  πŸ™  β†’ refl
    β‰€πŸ™ πŸ™  β‰€πŸ™ β†’ refl
    β‰€πŸ™ πŸ™  ≀ω β†’ refl
    β‰€πŸ™ β‰€πŸ™ 𝟘  β†’ refl
    β‰€πŸ™ β‰€πŸ™ πŸ™  β†’ refl
    β‰€πŸ™ β‰€πŸ™ β‰€πŸ™ β†’ refl
    β‰€πŸ™ β‰€πŸ™ ≀ω β†’ refl
    β‰€πŸ™ ≀ω 𝟘  β†’ refl
    β‰€πŸ™ ≀ω πŸ™  β†’ refl
    β‰€πŸ™ ≀ω β‰€πŸ™ β†’ refl
    β‰€πŸ™ ≀ω ≀ω β†’ refl
    ≀ω 𝟘  𝟘  β†’ refl
    ≀ω 𝟘  πŸ™  β†’ refl
    ≀ω 𝟘  β‰€πŸ™ β†’ refl
    ≀ω 𝟘  ≀ω β†’ refl
    ≀ω πŸ™  𝟘  β†’ refl
    ≀ω πŸ™  πŸ™  β†’ refl
    ≀ω πŸ™  β‰€πŸ™ β†’ refl
    ≀ω πŸ™  ≀ω β†’ refl
    ≀ω β‰€πŸ™ 𝟘  β†’ refl
    ≀ω β‰€πŸ™ πŸ™  β†’ refl
    ≀ω β‰€πŸ™ β‰€πŸ™ β†’ refl
    ≀ω β‰€πŸ™ ≀ω β†’ refl
    ≀ω ≀ω 𝟘  β†’ refl
    ≀ω ≀ω πŸ™  β†’ refl
    ≀ω ≀ω β‰€πŸ™ β†’ refl
    ≀ω ≀ω ≀ω β†’ refl

  +-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 ((p + _) +_) (Β·-distribΛ‘-+ ≀ω q _) ⟩
        (p + pβ€²) + ≀ω Β· (q + qβ€²)       ∎
      β‰€πŸ™ p q pβ€² qβ€² β†’ begin
        (p ∧ ≀ω Β· q) + (pβ€² ∧ ≀ω Β· qβ€²)  β‰€βŸ¨ +-sub-interchangeable-∧ p _ _ _ ⟩
        (p + pβ€²) ∧ (≀ω Β· q + ≀ω Β· qβ€²)  β‰ˆΛ˜βŸ¨ ∧-congΛ‘ (Β·-distribΛ‘-+ ≀ω q _) ⟩
        (p + pβ€²) ∧ ≀ω Β· (q + qβ€²)       ∎
      ≀ω p q pβ€² qβ€² β†’ begin
        ≀ω Β· (p ∧ q) + ≀ω Β· (pβ€² ∧ qβ€²)  β‰ˆΛ˜βŸ¨ Β·-distribΛ‘-+ ≀ω (p ∧ _) _ ⟩
        ≀ω Β· ((p ∧ q) + (pβ€² ∧ qβ€²))     β‰€βŸ¨ Β·-monotoneΚ³ {r = ≀ω} (+-sub-interchangeable-∧ p _ _ _) ⟩
        ≀ω Β· ((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 (p Β· _ +_) (Β·-assoc ≀ω 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 ∧ 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 (p +_) (Β·-distribΛ‘-∧ ≀ω q _) ⟩
        p + (≀ω Β· q ∧ ≀ω Β· qβ€²)        β‰‘βŸ¨ +-distribΛ‘-∧ p _ _ ⟩
        (p + ≀ω Β· q) ∧ (p + ≀ω Β· qβ€²)  ∎
      β‰€πŸ™ p q qβ€² β†’
        p ∧ ≀ω Β· (q ∧ qβ€²)             β‰‘βŸ¨ ∧-congΛ‘ (Β·-distribΛ‘-∧ ≀ω q _) ⟩
        p ∧ (≀ω Β· q ∧ ≀ω Β· qβ€²)        β‰‘βŸ¨ lemma 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
      𝟘 _ p _  β†’ lemma _ p _
      πŸ™ q p pβ€² β†’
        (p ∧ pβ€²) + ≀ω Β· q             β‰‘βŸ¨ +-distribΚ³-∧ _ p _ ⟩
        (p + ≀ω Β· q) ∧ (pβ€² + ≀ω Β· q)  ∎
      β‰€πŸ™ q p pβ€² β†’
        (p ∧ pβ€²) ∧ ≀ω Β· q             β‰‘βŸ¨ lemma _ _ _ ⟩
        (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 modality

-- A "linear or affine types" modality. If there is no dedicated
-- natrec-star operator, then 𝟘ᡐ must not be allowed.

linear-or-affine :
  (variant : Modality-variant) β†’
  let open Modality-variant variant in
  (Β¬ βŠ›-available β†’ Β¬ T 𝟘ᡐ-allowed) β†’
  Modality
linear-or-affine variant ok = record
  { variant            = variant
  ; semiring-with-meet = linear-or-affine-semiring-with-meet
  ; 𝟘-well-behaved     = Ξ» _ β†’ linear-or-affine-has-well-behaved-zero
  ; has-star           = Ξ» _ β†’ linear-or-affine-has-star
  ; +-decreasingΛ‘      = Ξ» 𝟘ᡐ-ok no-star β†’ βŠ₯-elim (ok no-star 𝟘ᡐ-ok)
  }

------------------------------------------------------------------------
-- Instances of Full-reduction-assumptions

-- An instance of Type-restrictions is suitable for the full reduction
-- theorem if
-- * Unit-allowed does not hold,
-- * Ξ£β‚š-allowed 𝟘 p does not hold,
-- * Ξ£β‚š-allowedΒ β‰€πŸ™Β p does not hold, and
-- * Ξ£β‚š-allowed ≀ω p does not hold.

Suitable-for-full-reduction :
  Type-restrictions β†’ Set
Suitable-for-full-reduction rs =
  Β¬ Unit-allowed Γ—
  (βˆ€ p β†’ Β¬ Ξ£β‚š-allowed 𝟘 p) Γ—
  (βˆ€ p β†’ Β¬ Ξ£β‚š-allowed β‰€πŸ™ p) Γ—
  (βˆ€ p β†’ Β¬ Ξ£β‚š-allowed ≀ω p)
  where
  open Type-restrictions rs

-- Given an instance of Type-restrictions one can create a "suitable"
-- instance.

suitable-for-full-reduction :
  Type-restrictions β†’ βˆƒ Suitable-for-full-reduction
suitable-for-full-reduction rs =
    record rs
      { Unit-allowed = βŠ₯
      ; Ξ Ξ£-allowed   = Ξ» b p q β†’
          Ξ Ξ£-allowed b p q Γ— p β‰’ 𝟘 Γ— p β‰’ β‰€πŸ™ Γ— p β‰’ ≀ω
      }
  , idαΆ 
  , (Ξ» _ β†’ (_$ refl) βˆ˜β†’ proj₁ βˆ˜β†’ projβ‚‚)
  , (Ξ» _ β†’ (_$ refl) βˆ˜β†’ proj₁ βˆ˜β†’ projβ‚‚ βˆ˜β†’ projβ‚‚)
  , (Ξ» _ β†’ (_$ refl) βˆ˜β†’ projβ‚‚ βˆ˜β†’ projβ‚‚ βˆ˜β†’ projβ‚‚)
  where
  open Type-restrictions rs

-- The full reduction assumptions hold for any instance of
-- linear-or-affine and any "suitable" Type-restrictions.

full-reduction-assumptions :
  let open Modality-variant variant in
  {variant-ok : Β¬ βŠ›-available β†’ Β¬ T 𝟘ᡐ-allowed} β†’
  Suitable-for-full-reduction trs β†’
  Full-reduction-assumptions (linear-or-affine variant variant-ok) trs
full-reduction-assumptions (Β¬Unit , ¬𝟘 , Β¬β‰€πŸ™ , ¬≀ω) = record
  { πŸ™β‰€πŸ˜    = βŠ₯-elim βˆ˜β†’ Β¬Unit
  ; β‰‘πŸ™βŠŽπŸ™β‰€πŸ˜ = Ξ» where
      {p = 𝟘}  ok β†’ βŠ₯-elim (¬𝟘 _ ok)
      {p = β‰€πŸ™} ok β†’ βŠ₯-elim (Β¬β‰€πŸ™ _ ok)
      {p = ≀ω} ok β†’ βŠ₯-elim (¬≀ω _ ok)
      {p = πŸ™}  _  β†’ inj₁ refl
  }