{-# OPTIONS --safe #-}
module Cubical.Data.Quiver.Reachability where
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Equiv
open import Cubical.Foundations.Function
open import Cubical.Foundations.Isomorphism
open import Cubical.Foundations.Structure
open import Cubical.Functions.Embedding
open import Cubical.Data.Empty as ⊥ hiding (elim ; rec)
open import Cubical.Data.FinData as FD
open import Cubical.Data.FinData.FinSet
import Cubical.Data.SumFin as SumFin
open import Cubical.Data.FinSet
open import Cubical.Data.FinSet.Cardinality
open import Cubical.Data.FinSet.Constructors
open import Cubical.Data.Nat hiding (elim)
open import Cubical.Data.Nat.Order
open import Cubical.Data.Sum
open import Cubical.Data.Quiver.Base
import Cubical.Data.Equality as Eq
open import Cubical.HITs.PropositionalTruncation as PT hiding (elim ; rec ; map)
open import Cubical.Relation.Nullary.Base
open import Cubical.Relation.Nullary.Properties
open import Cubical.Relation.Nullary.DecidablePropositions
private
variable
ℓ ℓ' : Level
n : ℕ
module Reachability {ℓ} {ℓ'}
(ob : FinSet ℓ)
(Q : QuiverOver ⟨ ob ⟩ ℓ')
(isFinSetMor : isFinSet (Q .QuiverOver.mor ))
where
open QuiverOver Q
data Walk (end : ⟨ ob ⟩) : ⟨ ob ⟩ → ℕ → Type (ℓ-max ℓ ℓ') where
nil : Walk end end 0
cons : ∀ n (e : mor) → Walk end (cod e) n → Walk end (dom e) (suc n)
Walk' : (end start : ⟨ ob ⟩) → Type (ℓ-max ℓ ℓ')
Walk' end start = Σ[ n ∈ ℕ ] Walk end start n
trivialWalk→sameEndpoints :
(end start : ⟨ ob ⟩) →
Walk end start 0 →
end ≡ start
trivialWalk→sameEndpoints end start nil = refl
module _
(isFinOrdMor : isFinOrd mor) where
isFinOrdWalk :
∀ (n : ℕ) →
(end start : ⟨ ob ⟩) →
isFinOrd (Walk end start n)
isFinOrdWalk zero end start =
decRec
(λ end≡start →
1 ,
isoToEquiv (
iso
(λ _ → inl _)
(λ { (inl tt) → subst (λ z → Walk end z zero) end≡start nil })
(λ { (inl tt) → refl})
λ { nil →
cong (λ u → subst (λ z → Walk end z zero) u nil)
(isFinSet→isSet (str ob) end end end≡start refl) ∙
substRefl {B = λ z → Walk end z zero}
Walk.nil }))
(λ ¬q≡q' →
0 ,
uninhabEquiv
(λ walk → ¬q≡q' (trivialWalk→sameEndpoints _ _ walk)) (λ x → x)
)
(isFinSet→Discrete (str ob) end start)
isFinOrdWalk (suc n) end start =
EquivPresIsFinOrd
{A = Σ[ e ∈ mor ] Σ[ src≡start ∈ dom e Eq.≡ start ] Walk end (cod e) n}
(isoToEquiv
(iso
(λ { (e , Eq.refl , walk) → cons n e walk })
(λ { (cons .n e walk) → e , Eq.refl , walk })
(λ { (cons .n e walk) → refl } )
λ { (e , Eq.refl , walk) → refl
}
))
(isFinOrdΣ mor isFinOrdMor
(λ e → _)
(λ e → isFinOrdΣ (dom e Eq.≡ start)
(decRec
(λ src≡start →
isContr→isFinOrd ((Eq.pathToEq src≡start) ,
(λ { Eq.refl →
cong (Eq.pathToEq)
(isFinSet→isSet (str ob) (dom e) (dom e) src≡start refl) ∙
Eq.eqToPath Eq.pathToEq-reflPath })))
(λ ¬src≡start → 0 , uninhabEquiv (λ eq → ¬src≡start (Eq.eqToPath eq)) λ x → x)
(isFinSet→Discrete (str ob) (dom e) start))
_
λ { Eq.refl → isFinOrdWalk n end (cod e)}))
isFinSetWalk :
(end start : ⟨ ob ⟩) →
(n : ℕ) →
isFinSet (Walk end start n)
isFinSetWalk end start n = isFinOrd→isFinSet (isFinOrdWalk _ _ _)
isSetWalk :
(end start : ⟨ ob ⟩) →
(n : ℕ) →
isSet (Walk end start n)
isSetWalk end start n = isFinSet→isSet (isFinSetWalk _ _ _)
first-edge :
{end start : ⟨ ob ⟩} →
(walk : Walk end start (suc n)) →
mor
first-edge (cons _ e walk) = e
tail :
{end start : ⟨ ob ⟩} →
(walk : Walk end start (suc n)) →
Walk end (cod (first-edge walk)) n
tail (cons _ e walk) = walk
snocWalk :
{start : ⟨ ob ⟩} →
(e : mor) →
Walk (dom e) start n →
Walk (cod e) start (suc n)
snocWalk e nil = cons 0 e nil
snocWalk e (cons n e' walk) = cons (suc n) e' (snocWalk e walk)
vertices :
{end start : ⟨ ob ⟩} →
Walk end start n →
Fin (suc n) → ⟨ ob ⟩
vertices {start = start} walk zero = start
vertices (cons n e walk) (suc m) = vertices walk m
hasUniqueVertices : ∀ {end start : ⟨ ob ⟩} → Walk end start n → Type ℓ
hasUniqueVertices walk = isEmbedding (vertices walk)
hasUniqueVertices→boundedLength :
{end start : ⟨ ob ⟩} →
(walk : Walk end start n) →
hasUniqueVertices walk →
n < card ob
hasUniqueVertices→boundedLength walk unique =
card↪Inequality' (_ , isFinSetFinData) ob (vertices walk) unique
uniqueVerticesWalk : ∀ (end start : ⟨ ob ⟩) → Type (ℓ-max ℓ ℓ')
uniqueVerticesWalk end start =
Σ[ n ∈ ℕ ]
Σ[ walk ∈ Walk end start n ] hasUniqueVertices walk
tailUniqueVertices :
{end start : ⟨ ob ⟩} →
(walk : Walk end start (suc n)) →
hasUniqueVertices walk →
hasUniqueVertices (tail walk)
tailUniqueVertices (cons _ e walk) uniq =
isEmbedding-∘ uniq (injEmbedding isSetFin injSucFin)
dec-hasUniqueVertices :
∀ {end start : ⟨ ob ⟩} → (walk : Walk end start n) →
Dec (hasUniqueVertices walk)
dec-hasUniqueVertices nil =
yes (injEmbedding (isFinSet→isSet (str ob))
(λ { {zero} {zero} → λ _ → refl }))
dec-hasUniqueVertices (cons n e walk) =
decRec
(λ (k , p) → no (λ x →
FD.znots (x zero (suc k) .equiv-proof (sym p) .fst .fst)))
(λ ¬repeatFirst →
decRec
(λ uniqWalk → yes
(λ j k →
injEmbedding
(isFinSet→isSet (str ob))
(λ {
{zero} {zero} → λ _ → refl
; {zero} {suc b} →
λ dom≡vert →
⊥.rec (¬repeatFirst (b , (sym dom≡vert)))
; {suc a} {zero} →
λ dom≡vert → ⊥.rec (¬repeatFirst (a , dom≡vert))
; {suc a} {suc b} → λ verts≡ →
decRec
(λ a≡b → cong suc a≡b)
(λ ¬a≡b →
⊥.rec
(¬a≡b (uniqWalk a b .equiv-proof verts≡ .fst .fst)))
(discreteFin a b)
})
j
k)
)
(λ ¬uniqWalk → no (λ x → ¬uniqWalk (tailUniqueVertices _ x)))
(dec-hasUniqueVertices walk)
)
(DecΣ (suc n) (λ k → vertices walk k ≡ dom e)
(λ k → isFinSet→Discrete (str ob) (vertices walk k) (dom e)))
drop : {end start : ⟨ ob ⟩} →
(walk : Walk end start n) →
(k : Fin (suc n)) →
Σ[ m ∈ ℕ ] Walk end (vertices walk k) m
drop walk zero = _ , walk
drop (cons n e walk) (suc k) = drop walk k
dropPreservesUnique :
{end start : ⟨ ob ⟩} →
(uniqWalk : uniqueVerticesWalk end start) →
(k : Fin (suc (uniqWalk .fst))) →
hasUniqueVertices (drop (uniqWalk .snd .fst) k .snd)
dropPreservesUnique uniqWalk zero = uniqWalk .snd .snd
dropPreservesUnique (n , cons n-1 e walk , uniq) (suc k) =
dropPreservesUnique
(n-1 ,
(walk , tailUniqueVertices (cons n-1 e walk) uniq)) k
UniqueWalk : ∀ (end start : ⟨ ob ⟩) → Type _
UniqueWalk end start =
Σ[ n ∈ Fin (card ob) ]
Σ[ walk ∈ Walk end start (toℕ n) ] hasUniqueVertices walk
makeUnique :
{end start : ⟨ ob ⟩} →
(walk : Walk end start n) →
uniqueVerticesWalk end start
makeUnique nil =
0 ,
nil ,
injEmbedding
(isFinSet→isSet (str ob))
(λ _ → isContr→isProp isContrFin1 _ _)
makeUnique {end = end}(cons n e walk) =
let new-vert = dom e in
let new-edge = e in
let n' , walk' , uniq = makeUnique walk in
decRec
(λ (m , p) →
let n'' , walk'' = drop walk' m in
let uniq' = dropPreservesUnique (n' , (walk' , uniq)) m in
n'' ,
subst (λ z → Σ[ w ∈ Walk end z n'' ] hasUniqueVertices w) p (walk'' , uniq'))
(λ ¬ΣnewVert →
suc n' ,
(cons n' new-edge walk' ,
injEmbedding
(isFinSet→isSet (str ob))
λ { {zero} {zero} p → refl
; {zero} {suc j} p → ⊥.rec (¬ΣnewVert (j , (sym p)))
; {suc i} {zero} p → ⊥.rec (¬ΣnewVert (i , p))
; {suc i} {suc j} p → congS suc $ isEmbedding→Inj uniq i j p
}
)
)
(DecΣ
(suc n')
(λ k → vertices walk' k ≡ new-vert)
(λ k → isFinSet→Discrete (str ob) (vertices walk' k) new-vert))
Walk→UniqueWalk :
{end start : ⟨ ob ⟩} →
(walk : Walk end start n) →
UniqueWalk end start
Walk→UniqueWalk {end = end}{start = start} walk =
let m , walk' , uniq = makeUnique walk in
let bound = hasUniqueVertices→boundedLength walk' uniq in
let to-and-fro = sym (toFromId' (card ob) m bound) in
fromℕ' (card ob) m bound ,
subst
(λ n' → Σ[ walk ∈ Walk end start n' ] hasUniqueVertices walk)
to-and-fro (walk' , uniq)
Reachable PathReachable : ⟨ ob ⟩ → ⟨ ob ⟩ → Type _
Reachable end start =
PT.∥ Σ[ n ∈ ℕ ] Walk end start n ∥₁
PathReachable end start =
PT.∥ UniqueWalk end start ∥₁
PathReachable≃Reachable :
(end start : ⟨ ob ⟩) → PathReachable end start ≃ Reachable end start
PathReachable≃Reachable end start =
propBiimpl→Equiv isPropPropTrunc isPropPropTrunc
(PT.map (λ gp → (toℕ (gp .fst)) , (gp .snd .fst)))
(PT.map (λ (n , gw) → Walk→UniqueWalk gw))
isFinSetHasUniqueVertices :
{end start : ⟨ ob ⟩} →
(gw : Walk end start n) → isFinSet (hasUniqueVertices gw)
isFinSetHasUniqueVertices gw =
isFinSetIsEmbedding (_ , isFinSetFinData) ob (vertices gw)
module _
(isFinOrdMor : isFinOrd mor)
(end start : ⟨ ob ⟩)
where
isFinOrdUniqueWalk : isFinOrd (UniqueWalk end start)
isFinOrdUniqueWalk =
isFinOrdΣ
(Fin (ob .snd .fst))
((card ob) , SumFin.FinData≃SumFin)
(λ n → Σ-syntax (Walk end start (toℕ n)) hasUniqueVertices)
(λ m → isFinOrdΣ
(Walk end start (toℕ m))
(isFinOrdWalk isFinOrdMor (toℕ m) end start)
hasUniqueVertices
(λ walk → DecProp→isFinOrd ((_ , isPropIsEmbedding) , dec-hasUniqueVertices walk)))
isFinSetUniqueWalk : isFinSet (UniqueWalk end start)
isFinSetUniqueWalk =
isFinOrd→isFinSet isFinOrdUniqueWalk
DecPathReachable : Dec (PathReachable end start)
DecPathReachable = isFinSet→Dec∥∥ isFinSetUniqueWalk
DecReachable : Dec (Reachable end start)
DecReachable =
EquivPresDec
(PathReachable≃Reachable end start)
DecPathReachable
Reachable-is-reflexive : (u : ⟨ ob ⟩) → Reachable u u
Reachable-is-reflexive u = ∣ 0 , nil ∣₁