Link-cut tree
Link Cut Tree
DefinitionPath tree on a vertex list#✓fully proved
For a vertex \(r\) and a list of vertices \(c_1, \dots, c_k\), the spine is the rooted tree \(r \to c_1 \to \cdots \to c_k\): its root is \(r\), each vertex has the next one in the list as its only child, and the last vertex (\(c_k\), or \(r\) when \(k = 0\)) is a leaf.
public def spine : V → List V → Tree V
| r, [] => .node r []
| r, c :: cs => .node r [spine c cs]
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
Uses 1 · Used by 1
DefinitionForest from a vertex list#✓fully proved
The forest built from the empty list is empty; the forest built from a list \(r, c_1, \dots, c_k\) consists of the single spine \(r \to c_1 \to \cdots \to c_k\), the rooted tree in which each vertex has the next one as its only child.
public def ofVertexList : List V → List (Tree V)
| [] => []
| r :: rs => [spine r rs]
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
public def spine : V → List V → Tree V
| r, [] => .node r []
| r, c :: cs => .node r [spine c cs]
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:205
Uses 2
DefinitionTree of a forest containing a vertex#✓fully proved
For a vertex \(x\) and a forest given as a list of trees, the first tree whose vertices contain \(x\), or nothing when no tree contains \(x\).
public def findTree (x : V) : List (Tree V) → Option (Tree V)
| [] => none
| t :: ts => if x ∈ Tree.vertices t then some t else findTree x ts
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
def vertices (t : Tree V) : List V :=
verticesAux t []
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:108
Uses 2 · Used by 20
DefinitionRemoving the trees that contain a vertex#✓fully proved
Given a vertex \(x\) and a forest, given as a list of rooted ordered trees, removing the trees containing \(x\) deletes from the list every tree that has \(x\) among its vertices and keeps the remaining trees in their original order.
public def removeTree (x : V) : List (Tree V) → List (Tree V)
| [] => []
| t :: ts => if x ∈ Tree.vertices t then removeTree x ts else t :: removeTree x ts
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
def vertices (t : Tree V) : List V :=
verticesAux t []
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:108
Uses 2 · Used by 14
TheoremRemoving the tree containing a vertex splits the forest's vertices#✓fully proved
Let \(f\) be a forest of rooted ordered trees whose concatenated vertex lists have no duplicates, let \(x\) be a vertex, and let \(t\) be the first tree of \(f\) containing \(x\). Then the concatenated vertex list of the forest obtained from \(f\) by removing every tree containing \(x\), followed by the vertex list of \(t\), is a permutation of the concatenated vertex list of \(f\).
public theorem perm_flatMap_removeTree {x : V} :
∀ {f : List (Tree V)} {t : Tree V},
(f.flatMap Tree.vertices).Nodup → findTree x f = some t →
((removeTree x f).flatMap Tree.vertices ++ Tree.vertices t).Perm
(f.flatMap Tree.vertices)
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
def vertices (t : Tree V) : List V :=
verticesAux t []
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:108
public def findTree (x : V) : List (Tree V) → Option (Tree V)
| [] => none
| t :: ts => if x ∈ Tree.vertices t then some t else findTree x ts
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:247
public def removeTree (x : V) : List (Tree V) → List (Tree V)
| [] => []
| t :: ts => if x ∈ Tree.vertices t then removeTree x ts else t :: removeTree x ts
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:293
Uses 4 · Used by 3
DefinitionSubtree rooted at a vertex#✓fully proved
For a vertex \(x\) and a tree \(T\), the subtree of \(T\) rooted at the first occurrence of \(x\) in preorder, or nothing when \(x\) does not occur in \(T\).
public def findSubtree (x : V) : Tree V → Option (Tree V)
| .node r cs => if r = x then some (.node r cs) else findSubtreeList x cs
where
findSubtreeList (x : V) : List (Tree V) → Option (Tree V)
| [] => none
| c :: cs =>
match findSubtree x c with
| some s => some s
| none => findSubtreeList x cs
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
Uses 1 · Used by 8
DefinitionAdjacency in a rooted tree#✓fully proved
Two vertices \(a\) and \(b\) are adjacent in a rooted tree \(t\) when they are joined by a parent-child edge of \(t\) in either direction: some node of \(t\) labelled \(a\) has a child labelled \(b\), or some node of \(t\) labelled \(b\) has a child labelled \(a\).
This is the undirected edge relation that the structural operations of the link-cut tree are specified against.
public def Adjacent (a b : V) : Tree V → Prop
| .node r cs =>
(r = a ∧ ∃ c ∈ cs, c.root = b) ∨ (r = b ∧ ∃ c ∈ cs, c.root = a) ∨
AdjacentList a b cs
where
/-- Adjacency inside one of a list of subtrees. -/
AdjacentList (a b : V) : List (Tree V) → Prop
| [] => False
| c :: cs => Adjacent a b c ∨ AdjacentList a b cs
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
Uses 2 · Used by 15
TheoremThe first endpoint of a tree edge is a vertex#✓fully proved
If \(a\) and \(b\) are adjacent in a tree \(t\), that is, joined by a parent-child edge in either direction, then \(a\) is a vertex of \(t\).
public theorem Adjacent.mem_left {a b : V} :
∀ {t : Tree V}, Adjacent a b t → a ∈ Tree.vertices t
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
public def Adjacent (a b : V) : Tree V → Prop
| .node r cs =>
(r = a ∧ ∃ c ∈ cs, c.root = b) ∨ (r = b ∧ ∃ c ∈ cs, c.root = a) ∨
AdjacentList a b cs
where
/-- Adjacency inside one of a list of subtrees. -/
AdjacentList (a b : V) : List (Tree V) → Prop
| [] => False
| c :: cs => Adjacent a b c ∨ AdjacentList a b cs
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:606
def vertices (t : Tree V) : List V :=
verticesAux t []
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:108
Uses 6 · Used by 5
TheoremAdjacency in a tree is symmetric#✓fully proved
For every rooted ordered tree \(T\) and vertices \(a\) and \(b\), if \(a\) and \(b\) are adjacent in \(T\) (joined by a parent-child edge in either direction), then \(b\) and \(a\) are adjacent in \(T\).
public theorem Adjacent.symm {a b : V} :
∀ {t : Tree V}, Adjacent a b t → Adjacent b a t
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
public def Adjacent (a b : V) : Tree V → Prop
| .node r cs =>
(r = a ∧ ∃ c ∈ cs, c.root = b) ∨ (r = b ∧ ∃ c ∈ cs, c.root = a) ∨
AdjacentList a b cs
where
/-- Adjacency inside one of a list of subtrees. -/
AdjacentList (a b : V) : List (Tree V) → Prop
| [] => False
| c :: cs => Adjacent a b c ∨ AdjacentList a b cs
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:606
Uses 4 · Used by 2
TheoremThe second endpoint of a tree edge is a vertex#✓fully proved
If \(a\) and \(b\) are adjacent in a tree \(t\), that is, joined by a parent-child edge in either direction, then \(b\) is a vertex of \(t\).
public theorem Adjacent.mem_right {a b : V} {t : Tree V}
(h : Adjacent a b t) : b ∈ Tree.vertices t
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
public def Adjacent (a b : V) : Tree V → Prop
| .node r cs =>
(r = a ∧ ∃ c ∈ cs, c.root = b) ∨ (r = b ∧ ∃ c ∈ cs, c.root = a) ∨
AdjacentList a b cs
where
/-- Adjacency inside one of a list of subtrees. -/
AdjacentList (a b : V) : List (Tree V) → Prop
| [] => False
| c :: cs => Adjacent a b c ∨ AdjacentList a b cs
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:606
def vertices (t : Tree V) : List V :=
verticesAux t []
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:108
Uses 5 · Used by 4
DefinitionAdjacency test#✓fully proved
For vertices \(a\), \(b\) and a rooted tree \(t\) with root \(r\) and child subtrees \(c_1, \dots, c_k\), the adjacency test of \(a\) and \(b\) in \(t\) returns true exactly when \(r = a\) and some \(c_i\) has root \(b\), or \(r = b\) and some \(c_i\) has root \(a\), or the adjacency test of \(a\) and \(b\) returns true in some \(c_i\).
It returns true exactly when \(a\) and \(b\) are adjacent in \(t\), and it is the guard checked by the edge cut before it cuts.
public def adjacentB (a b : V) : Tree V → Bool
| .node r cs =>
(decide (r = a) && cs.any (fun c => decide (c.root = b))) ||
(decide (r = b) && cs.any (fun c => decide (c.root = a))) ||
adjacentBList a b cs
where
/-- Adjacency test over a list of subtrees. -/
adjacentBList (a b : V) : List (Tree V) → Bool
| [] => false
| c :: cs => adjacentB a b c || adjacentBList a b cs
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
Uses 2 · Used by 4
DefinitionGrafting a tree below a vertex#✓fully proved
For a vertex \(y\) and trees \(N\) and \(T\), grafting \(N\) at \(y\) in \(T\) attaches \(N\) as a new last child of the first node of \(T\) labelled \(y\) in preorder, keeping every existing node and edge; it returns nothing when \(y\) does not occur in \(T\). This is the tree surgery behind linking two trees: it adds exactly the edge from \(y\) to the root of \(N\).
public def graftAt (y : V) (newChild : Tree V) : Tree V → Option (Tree V)
| .node r cs =>
if r = y then some (.node r (cs ++ [newChild]))
else (graftAtList y newChild cs).map (.node r)
where
graftAtList (y : V) (newChild : Tree V) :
List (Tree V) → Option (List (Tree V))
| [] => none
| c :: cs =>
match graftAt y newChild c with
| some c' => some (c' :: cs)
| none => (graftAtList y newChild cs).map (c :: ·)
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
Uses 1 · Used by 16
TheoremVertices after grafting#✓fully proved
Let \(t\) and \(C\) be trees and \(y\) a vertex. If grafting \(C\) at \(y\) in \(t\), that is, attaching \(C\) as a new last child of a node labelled \(y\), produces the tree \(t'\), then for every \(v\), \(v\) is a vertex of \(t'\) if and only if \(v\) is a vertex of \(t\) or a vertex of \(C\).
public theorem mem_vertices_graftAt {y v : V} {newChild : Tree V} :
∀ {t t' : Tree V}, graftAt y newChild t = some t' →
(v ∈ Tree.vertices t' ↔ v ∈ Tree.vertices t ∨ v ∈ Tree.vertices newChild)
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
public def graftAt (y : V) (newChild : Tree V) : Tree V → Option (Tree V)
| .node r cs =>
if r = y then some (.node r (cs ++ [newChild]))
else (graftAtList y newChild cs).map (.node r)
where
graftAtList (y : V) (newChild : Tree V) :
List (Tree V) → Option (List (Tree V))
| [] => none
| c :: cs =>
match graftAt y newChild c with
| some c' => some (c' :: cs)
| none => (graftAtList y newChild cs).map (c :: ·)
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:856
def vertices (t : Tree V) : List V :=
verticesAux t []
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:108
Uses 5 · Used by 6
TheoremGrafting keeps the root#✓fully proved
Let \(T\) and \(N\) be rooted ordered trees and \(y\) a vertex. If grafting \(N\) into \(T\) at \(y\) is defined and yields the tree \(T'\), then the root of \(T'\) equals the root of \(T\).
public theorem root_graftAt {y : V} {newChild : Tree V} :
∀ {t t' : Tree V}, graftAt y newChild t = some t' → t'.root = t.root
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
public def graftAt (y : V) (newChild : Tree V) : Tree V → Option (Tree V)
| .node r cs =>
if r = y then some (.node r (cs ++ [newChild]))
else (graftAtList y newChild cs).map (.node r)
where
graftAtList (y : V) (newChild : Tree V) :
List (Tree V) → Option (List (Tree V))
| [] => none
| c :: cs =>
match graftAt y newChild c with
| some c' => some (c' :: cs)
| none => (graftAtList y newChild cs).map (c :: ·)
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:856
Uses 4 · Used by 7
TheoremEdges after grafting#✓fully proved
Let \(t\) and \(u\) be rooted trees and \(y\) a vertex, and suppose that grafting \(u\) as a new child under \(y\) in \(t\) succeeds and yields the tree \(t'\). Then for all vertices \(a\) and \(b\), the vertices \(a\) and \(b\) are adjacent in \(t'\) if and only if they are adjacent in \(t\), or adjacent in \(u\), or \(a = y\) and \(b\) is the root of \(u\), or \(a\) is the root of \(u\) and \(b = y\).
public theorem adjacent_graftAt {y a b : V} {newChild : Tree V} :
∀ {t t' : Tree V}, graftAt y newChild t = some t' →
(Adjacent a b t' ↔ Adjacent a b t ∨ Adjacent a b newChild ∨
(a = y ∧ b = newChild.root) ∨ (a = newChild.root ∧ b = y))
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
public def graftAt (y : V) (newChild : Tree V) : Tree V → Option (Tree V)
| .node r cs =>
if r = y then some (.node r (cs ++ [newChild]))
else (graftAtList y newChild cs).map (.node r)
where
graftAtList (y : V) (newChild : Tree V) :
List (Tree V) → Option (List (Tree V))
| [] => none
| c :: cs =>
match graftAt y newChild c with
| some c' => some (c' :: cs)
| none => (graftAtList y newChild cs).map (c :: ·)
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:856
public def Adjacent (a b : V) : Tree V → Prop
| .node r cs =>
(r = a ∧ ∃ c ∈ cs, c.root = b) ∨ (r = b ∧ ∃ c ∈ cs, c.root = a) ∨
AdjacentList a b cs
where
/-- Adjacency inside one of a list of subtrees. -/
AdjacentList (a b : V) : List (Tree V) → Prop
| [] => False
| c :: cs => Adjacent a b c ∨ AdjacentList a b cs
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:606
Uses 6 · Used by 1
TheoremGrafting adds the new subtree's vertices#✓fully proved
Let \(t\) and \(s\) be rooted ordered trees and \(y\) a vertex. If grafting \(s\) as a new child at \(y\) in \(t\) succeeds and yields the tree \(t'\), then the vertex list of \(t'\) is a permutation of the vertex list of \(t\) followed by the vertex list of \(s\).
public theorem perm_vertices_graftAt {y : V} {newChild : Tree V} :
∀ {t t' : Tree V}, graftAt y newChild t = some t' →
(Tree.vertices t').Perm (Tree.vertices t ++ Tree.vertices newChild)
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
public def graftAt (y : V) (newChild : Tree V) : Tree V → Option (Tree V)
| .node r cs =>
if r = y then some (.node r (cs ++ [newChild]))
else (graftAtList y newChild cs).map (.node r)
where
graftAtList (y : V) (newChild : Tree V) :
List (Tree V) → Option (List (Tree V))
| [] => none
| c :: cs =>
match graftAt y newChild c with
| some c' => some (c' :: cs)
| none => (graftAtList y newChild cs).map (c :: ·)
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:856
def vertices (t : Tree V) : List V :=
verticesAux t []
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:108
Uses 5 · Used by 2
DefinitionRerooting a tree at a vertex#✓fully proved
For a vertex \(x\) and a rooted ordered tree \(T\) with root \(r\), rerooting \(T\) at \(x\) is defined recursively. If \(r = x\), the result is \(T\) itself. Otherwise let \(C\) be the first child subtree of \(r\) that contains \(x\), let \(p\) be the root of \(C\), and let \(C'\) be \(C\) rerooted at \(x\). The result is \(C'\) with the tree formed by \(r\) and its remaining children (in their original order) attached as a new last child of the first node of \(C'\), in preorder, labelled \(p\). If no child subtree of \(r\) contains \(x\), rerooting is undefined; thus rerooting is defined exactly when \(x\) is a vertex of \(T\).
When the vertices of \(T\) are distinct, this reverses the edges on the path from \(r\) to \(x\) and keeps every other edge, so the undirected tree is unchanged and only the root moves to \(x\). This is the tree surgery behind making \(x\) the root in a link-cut tree.
Cslib.Algorithms.Lean.LinkCutTree.rerootAt · 19 lines
public def rerootAt (x : V) : Tree V → Option (Tree V)
| .node r cs =>
if r = x then some (.node r cs)
else
match rerootAtList x cs with
| some (c', rest, p) => graftAt p (.node r rest) c'
| none => none
where
/-- Reroot the first child subtree containing `x`; returns the rerooted
child, the remaining sibling subtrees in order, and the root of the
original child (the next vertex on the root-to-`x` path, under which the
caller reattaches the remainder). -/
rerootAtList (x : V) : List (Tree V) → Option (Tree V × List (Tree V) × V)
| [] => none
| c :: cs =>
match rerootAt x c with
| some c' => some (c', cs, c.root)
| none =>
(rerootAtList x cs).map (fun (c', rest, p) => (c', c :: rest, p))
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
public def graftAt (y : V) (newChild : Tree V) : Tree V → Option (Tree V)
| .node r cs =>
if r = y then some (.node r (cs ++ [newChild]))
else (graftAtList y newChild cs).map (.node r)
where
graftAtList (y : V) (newChild : Tree V) :
List (Tree V) → Option (List (Tree V))
| [] => none
| c :: cs =>
match graftAt y newChild c with
| some c' => some (c' :: cs)
| none => (graftAtList y newChild cs).map (c :: ·)
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:856
Uses 3 · Used by 13
TheoremRerooting fails at an absent vertex#✓fully proved
For every rooted ordered tree \(T\) and every vertex \(x\) that is not a vertex of \(T\), rerooting \(T\) at \(x\) is undefined (it returns no tree).
public theorem rerootAt_eq_none_of_not_mem {x : V} :
∀ {t : Tree V}, x ∉ Tree.vertices t → rerootAt x t = none
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
def vertices (t : Tree V) : List V :=
verticesAux t []
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:108
public def rerootAt (x : V) : Tree V → Option (Tree V)
| .node r cs =>
if r = x then some (.node r cs)
else
match rerootAtList x cs with
| some (c', rest, p) => graftAt p (.node r rest) c'
| none => none
where
/-- Reroot the first child subtree containing `x`; returns the rerooted
child, the remaining sibling subtrees in order, and the root of the
original child (the next vertex on the root-to-`x` path, under which the
caller reattaches the remainder). -/
⋯
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:1355
Uses 7 · Used by 6
TheoremRerooting preserves the vertex set#✓fully proved
Let \(t\) be a rooted tree and \(x\) a vertex. If rerooting \(t\) at \(x\) yields the tree \(t'\), then a vertex lies in \(t'\) if and only if it lies in \(t\).
public theorem mem_vertices_rerootAt {x v : V} :
∀ {t t' : Tree V}, rerootAt x t = some t' →
(v ∈ Tree.vertices t' ↔ v ∈ Tree.vertices t)
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
public def rerootAt (x : V) : Tree V → Option (Tree V)
| .node r cs =>
if r = x then some (.node r cs)
else
match rerootAtList x cs with
| some (c', rest, p) => graftAt p (.node r rest) c'
| none => none
where
/-- Reroot the first child subtree containing `x`; returns the rerooted
child, the remaining sibling subtrees in order, and the root of the
original child (the next vertex on the root-to-`x` path, under which the
caller reattaches the remainder). -/
⋯
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:1355
def vertices (t : Tree V) : List V :=
verticesAux t []
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:108
Uses 10 · Used by 5
TheoremRerooting keeps every edge#✓fully proved
Let \(t\) be a rooted tree with no repeated vertex, and suppose that rerooting \(t\) at a vertex \(x\) yields the tree \(t'\). Then for all vertices \(a\) and \(b\), the vertices \(a\) and \(b\) are adjacent in \(t'\) if and only if they are adjacent in \(t\).
public theorem adjacent_rerootAt {x a b : V} :
∀ {t t' : Tree V}, (Tree.vertices t).Nodup → rerootAt x t = some t' →
(Adjacent a b t' ↔ Adjacent a b t)
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
def vertices (t : Tree V) : List V :=
verticesAux t []
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:108
public def rerootAt (x : V) : Tree V → Option (Tree V)
| .node r cs =>
if r = x then some (.node r cs)
else
match rerootAtList x cs with
| some (c', rest, p) => graftAt p (.node r rest) c'
| none => none
where
/-- Reroot the first child subtree containing `x`; returns the rerooted
child, the remaining sibling subtrees in order, and the root of the
original child (the next vertex on the root-to-`x` path, under which the
caller reattaches the remainder). -/
⋯
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:1355
public def Adjacent (a b : V) : Tree V → Prop
| .node r cs =>
(r = a ∧ ∃ c ∈ cs, c.root = b) ∨ (r = b ∧ ∃ c ∈ cs, c.root = a) ∨
AdjacentList a b cs
where
/-- Adjacency inside one of a list of subtrees. -/
AdjacentList (a b : V) : List (Tree V) → Prop
| [] => False
| c :: cs => Adjacent a b c ∨ AdjacentList a b cs
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:606
Uses 9 · Used by 2
TheoremRerooting preserves the vertices#✓fully proved
Let \(t\) be a rooted ordered tree and \(x\) a vertex. If rerooting \(t\) at \(x\) yields the tree \(t'\), then the vertex list of \(t'\) is a permutation of the vertex list of \(t\).
public theorem perm_vertices_rerootAt {x : V} :
∀ {t t' : Tree V}, rerootAt x t = some t' →
(Tree.vertices t').Perm (Tree.vertices t)
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
public def rerootAt (x : V) : Tree V → Option (Tree V)
| .node r cs =>
if r = x then some (.node r cs)
else
match rerootAtList x cs with
| some (c', rest, p) => graftAt p (.node r rest) c'
| none => none
where
/-- Reroot the first child subtree containing `x`; returns the rerooted
child, the remaining sibling subtrees in order, and the root of the
original child (the next vertex on the root-to-`x` path, under which the
caller reattaches the remainder). -/
⋯
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:1355
def vertices (t : Tree V) : List V :=
verticesAux t []
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:108
Uses 8 · Used by 4
DefinitionPruning the subtrees rooted at a vertex#✓fully proved
For a vertex \(x\) and a rooted ordered tree \(T\), pruning \(T\) at \(x\) removes every subtree of \(T\) whose root is labelled \(x\), keeping every other node and edge and the order of children. If the root of \(T\) is \(x\), nothing remains and pruning is undefined. Otherwise the result is the tree with the same root whose children are, in their original order, the pruned children of the root, with the children labelled \(x\) dropped.
This is the tree surgery behind the remainder side of the cut operation of a link-cut tree.
public def pruneAt (x : V) : Tree V → Option (Tree V)
| .node r cs => if r = x then none else some (.node r (pruneList x cs))
where
pruneList (x : V) : List (Tree V) → List (Tree V)
| [] => []
| c :: cs =>
match pruneAt x c with
| some c' => c' :: pruneList x cs
| none => pruneList x cs
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
Uses 1 · Used by 11
TheoremPruning at an absent vertex changes nothing#✓fully proved
Let \(t\) be a rooted ordered tree and \(x\) a vertex that does not occur in \(t\). Then pruning the subtrees rooted at \(x\) from \(t\) succeeds and returns \(t\) itself.
public theorem pruneAt_eq_self_of_not_mem {x : V} :
∀ {t : Tree V}, x ∉ Tree.vertices t → pruneAt x t = some t
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
def vertices (t : Tree V) : List V :=
verticesAux t []
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:108
public def pruneAt (x : V) : Tree V → Option (Tree V)
| .node r cs => if r = x then none else some (.node r (pruneList x cs))
where
pruneList (x : V) : List (Tree V) → List (Tree V)
| [] => []
| c :: cs =>
match pruneAt x c with
| some c' => c' :: pruneList x cs
| none => pruneList x cs
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:1809
Uses 5 · Used by 2
TheoremVertices of a pruned tree#✓fully proved
Let \(t\) be a rooted tree and \(x\) a vertex. If pruning \(t\) at \(x\) leaves the tree \(t'\), then every vertex of \(t'\) is a vertex of \(t\) and is different from \(x\).
public theorem mem_vertices_pruneAt {x v : V} :
∀ {t t' : Tree V}, pruneAt x t = some t' → v ∈ Tree.vertices t' →
v ∈ Tree.vertices t ∧ v ≠ x
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
public def pruneAt (x : V) : Tree V → Option (Tree V)
| .node r cs => if r = x then none else some (.node r (pruneList x cs))
where
pruneList (x : V) : List (Tree V) → List (Tree V)
| [] => []
| c :: cs =>
match pruneAt x c with
| some c' => c' :: pruneList x cs
| none => pruneList x cs
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:1809
def vertices (t : Tree V) : List V :=
verticesAux t []
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:108
Uses 5 · Used by 2
TheoremPruning keeps the vertices outside the detached subtree#✓fully proved
Let \(t\) be a rooted tree whose preorder vertex list has no repeated vertex, and let \(x\) be a vertex. Suppose the subtree search finds the subtree \(s\) of \(t\) rooted at \(x\), and pruning \(t\) at \(x\) leaves the tree \(t'\). Then every vertex of \(t\) that is not a vertex of \(s\) is a vertex of \(t'\).
public theorem mem_vertices_pruneAt_of_mem_not_mem {x v : V} :
∀ {t sub t' : Tree V}, (Tree.vertices t).Nodup →
findSubtree x t = some sub → pruneAt x t = some t' →
v ∈ Tree.vertices t → v ∉ Tree.vertices sub →
v ∈ Tree.vertices t'
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
def vertices (t : Tree V) : List V :=
verticesAux t []
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:108
public def findSubtree (x : V) : Tree V → Option (Tree V)
| .node r cs => if r = x then some (.node r cs) else findSubtreeList x cs
where
findSubtreeList (x : V) : List (Tree V) → Option (Tree V)
| [] => none
| c :: cs =>
match findSubtree x c with
| some s => some s
| none => findSubtreeList x cs
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:395
public def pruneAt (x : V) : Tree V → Option (Tree V)
| .node r cs => if r = x then none else some (.node r (pruneList x cs))
where
pruneList (x : V) : List (Tree V) → List (Tree V)
| [] => []
| c :: cs =>
match pruneAt x c with
| some c' => c' :: pruneList x cs
| none => pruneList x cs
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:1809
Uses 8 · Used by 1
TheoremPruning a subtree splits the vertex list#✓fully proved
Let \(t\) be a rooted ordered tree whose vertex list has no duplicates and let \(x\) be a vertex. If \(x\) occurs in \(t\), with \(s\) the subtree of \(t\) rooted at \(x\), and pruning at \(x\) leaves a tree \(t'\) (that is, \(x\) is not the root of \(t\)), then the vertex list of \(t\) is a permutation of the vertex list of \(t'\) followed by the vertex list of \(s\).
public theorem perm_vertices_pruneAt {x : V} :
∀ {t sub t' : Tree V}, (Tree.vertices t).Nodup →
findSubtree x t = some sub → pruneAt x t = some t' →
(Tree.vertices t).Perm (Tree.vertices t' ++ Tree.vertices sub)
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
def vertices (t : Tree V) : List V :=
verticesAux t []
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:108
public def findSubtree (x : V) : Tree V → Option (Tree V)
| .node r cs => if r = x then some (.node r cs) else findSubtreeList x cs
where
findSubtreeList (x : V) : List (Tree V) → Option (Tree V)
| [] => none
| c :: cs =>
match findSubtree x c with
| some s => some s
| none => findSubtreeList x cs
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:395
public def pruneAt (x : V) : Tree V → Option (Tree V)
| .node r cs => if r = x then none else some (.node r (pruneList x cs))
where
pruneList (x : V) : List (Tree V) → List (Tree V)
| [] => []
| c :: cs =>
match pruneAt x c with
| some c' => c' :: pruneList x cs
| none => pruneList x cs
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:1809
Uses 8 · Used by 2
TheoremPruning keeps the root#✓fully proved
Let \(T\) be a rooted ordered tree and \(x\) a vertex. If pruning \(T\) at \(x\) yields a tree \(T'\) (that is, the root of \(T\) is not \(x\)), then the root of \(T'\) equals the root of \(T\).
public theorem root_pruneAt {x : V} {t t' : Tree V}
(h : pruneAt x t = some t') : t'.root = t.root
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
public def pruneAt (x : V) : Tree V → Option (Tree V)
| .node r cs => if r = x then none else some (.node r (pruneList x cs))
where
pruneList (x : V) : List (Tree V) → List (Tree V)
| [] => []
| c :: cs =>
match pruneAt x c with
| some c' => c' :: pruneList x cs
| none => pruneList x cs
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:1809
Uses 3 · Used by 1
TheoremPruning keeps surviving edges#✓fully proved
Let \(t\) be a rooted tree with no repeated vertex and \(x\) a vertex, and suppose that removing every subtree rooted at \(x\) from \(t\) leaves the tree \(t'\) (that is, the root of \(t\) is not \(x\)). If \(a\) and \(b\) are adjacent in \(t\) and both are vertices of \(t'\), then \(a\) and \(b\) are adjacent in \(t'\).
Together with the fact that every vertex of \(t'\) is a vertex of \(t\) other than \(x\), this specifies pruning at the level of edges on the surviving vertices.
public theorem adjacent_pruneAt_of_mem_mem {a b x : V} :
∀ {t t' : Tree V}, (Tree.vertices t).Nodup →
pruneAt x t = some t' → Adjacent a b t →
a ∈ Tree.vertices t' → b ∈ Tree.vertices t' →
Adjacent a b t'
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
def vertices (t : Tree V) : List V :=
verticesAux t []
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:108
public def pruneAt (x : V) : Tree V → Option (Tree V)
| .node r cs => if r = x then none else some (.node r (pruneList x cs))
where
pruneList (x : V) : List (Tree V) → List (Tree V)
| [] => []
| c :: cs =>
match pruneAt x c with
| some c' => c' :: pruneList x cs
| none => pruneList x cs
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:1809
public def Adjacent (a b : V) : Tree V → Prop
| .node r cs =>
(r = a ∧ ∃ c ∈ cs, c.root = b) ∨ (r = b ∧ ∃ c ∈ cs, c.root = a) ∨
AdjacentList a b cs
where
/-- Adjacency inside one of a list of subtrees. -/
AdjacentList (a b : V) : List (Tree V) → Prop
| [] => False
| c :: cs => Adjacent a b c ∨ AdjacentList a b cs
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:606
Uses 11 · Used by 1
DefinitionRoot-to-vertex path#✓fully proved
For a vertex \(x\) and a rooted ordered tree \(T\), the root path of \(x\) is defined exactly when \(x\) is a vertex of \(T\). It is then the list of vertices on the path from the root of \(T\) down to \(x\), root first and ending with \(x\); if \(x\) occurs more than once, the path leads to its first occurrence in preorder.
This is the preferred path installed by the access operation of a link-cut tree.
public def rootPath (x : V) : Tree V → Option (List V)
| .node r cs =>
if r = x then some [r] else (rootPathList x cs).map (fun p => r :: p)
where
rootPathList (x : V) : List (Tree V) → Option (List V)
| [] => none
| c :: cs =>
match rootPath x c with
| some p => some p
| none => rootPathList x cs
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
Uses 1 · Used by 13
TheoremA root path ends at its target#✓fully proved
If \(p\) is the path from the root of a tree \(T\) down to a vertex \(x\) of \(T\), then \(p\) is nonempty and its last (deepest) vertex is \(x\).
public theorem getLast?_rootPath {x : V} {t : Tree V} {p : List V}
(h : rootPath x t = some p) : p.getLast? = some x
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
public def rootPath (x : V) : Tree V → Option (List V)
| .node r cs =>
if r = x then some [r] else (rootPathList x cs).map (fun p => r :: p)
where
rootPathList (x : V) : List (Tree V) → Option (List V)
| [] => none
| c :: cs =>
match rootPath x c with
| some p => some p
| none => rootPathList x cs
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:2324
Uses 3 · Used by 2
TheoremThe root path starts at the root#✓fully proved
Let \(t\) be a tree and \(x\) a vertex. If the root path of \(x\) in \(t\) (the path from the root of \(t\) down to \(x\)) is defined and equals \(p\), then \(p\) is nonempty and its first vertex is the root of \(t\).
public theorem head?_rootPath {x : V} {t : Tree V} {p : List V}
(h : rootPath x t = some p) : p.head? = some t.root
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
public def rootPath (x : V) : Tree V → Option (List V)
| .node r cs =>
if r = x then some [r] else (rootPathList x cs).map (fun p => r :: p)
where
rootPathList (x : V) : List (Tree V) → Option (List V)
| [] => none
| c :: cs =>
match rootPath x c with
| some p => some p
| none => rootPathList x cs
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:2324
TheoremRoot paths stay inside the tree#✓fully proved
If \(p\) is the path in a tree \(t\) from the root down to a vertex \(x\), then every vertex of \(p\) is a vertex of \(t\).
public theorem mem_rootPath {x v : V} {t : Tree V} {p : List V}
(h : rootPath x t = some p) (hv : v ∈ p) : v ∈ Tree.vertices t
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
public def rootPath (x : V) : Tree V → Option (List V)
| .node r cs =>
if r = x then some [r] else (rootPathList x cs).map (fun p => r :: p)
where
rootPathList (x : V) : List (Tree V) → Option (List V)
| [] => none
| c :: cs =>
match rootPath x c with
| some p => some p
| none => rootPathList x cs
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:2324
def vertices (t : Tree V) : List V :=
verticesAux t []
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:108
Uses 5 · Used by 1
TheoremRoot paths have distinct vertices#✓fully proved
If the preorder vertex list of a rooted tree \(t\) has no repeated vertex and \(p\) is the path from the root of \(t\) down to a vertex \(x\), then \(p\) has no repeated vertex.
public theorem nodup_rootPath {x : V} :
∀ {t : Tree V} {p : List V}, (Tree.vertices t).Nodup →
rootPath x t = some p → p.Nodup
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
def vertices (t : Tree V) : List V :=
verticesAux t []
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:108
public def rootPath (x : V) : Tree V → Option (List V)
| .node r cs =>
if r = x then some [r] else (rootPathList x cs).map (fun p => r :: p)
where
rootPathList (x : V) : List (Tree V) → Option (List V)
| [] => none
| c :: cs =>
match rootPath x c with
| some p => some p
| none => rootPathList x cs
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:2324
Uses 6 · Used by 2
TheoremConsecutive vertices of a root path are adjacent#✓fully proved
Let \(t\) be a tree and \(x\) a vertex. If the root path of \(x\) in \(t\) is defined and equals \(p = (p_0, \dots, p_k)\), then for every \(i < k\) the vertices \(p_i\) and \(p_{i+1}\) are adjacent in \(t\), that is, joined by a parent-child edge of \(t\) in one direction or the other.
public theorem isChain_adjacent_rootPath {x : V} :
∀ {t : Tree V} {p : List V}, rootPath x t = some p →
p.IsChain (fun a b => Adjacent a b t)
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
public def rootPath (x : V) : Tree V → Option (List V)
| .node r cs =>
if r = x then some [r] else (rootPathList x cs).map (fun p => r :: p)
where
rootPathList (x : V) : List (Tree V) → Option (List V)
| [] => none
| c :: cs =>
match rootPath x c with
| some p => some p
| none => rootPathList x cs
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:2324
public def Adjacent (a b : V) : Tree V → Prop
| .node r cs =>
(r = a ∧ ∃ c ∈ cs, c.root = b) ∨ (r = b ∧ ∃ c ∈ cs, c.root = a) ∨
AdjacentList a b cs
where
/-- Adjacency inside one of a list of subtrees. -/
AdjacentList (a b : V) : List (Tree V) → Prop
| [] => False
| c :: cs => Adjacent a b c ∨ AdjacentList a b cs
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:606
Uses 6
DefinitionParent-child relation in a rooted tree#✓fully proved
For vertices \(a\) and \(b\) and a rooted ordered tree \(t\), \(a\) is a parent of \(b\) in \(t\) when some node of \(t\) labelled \(a\) has a child subtree whose root is \(b\). Preferred edges of a link-cut tree are directed this way, from a node to its preferred child.
public def ParentChild (a b : V) : Tree V → Prop
| .node r cs => (r = a ∧ ∃ c ∈ cs, c.root = b) ∨ ParentChildList a b cs
where
/-- Directed parent-child adjacency inside one of a list of subtrees. -/
ParentChildList (a b : V) : List (Tree V) → Prop
| [] => False
| c :: cs => ParentChild a b c ∨ ParentChildList a b cs
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
Uses 2 · Used by 16
TheoremParent-child edges are edges#✓fully proved
For every rooted tree \(t\) and all vertices \(a\) and \(b\), if \(a\) is the parent of \(b\) somewhere in \(t\), then \(a\) and \(b\) are adjacent in \(t\).
public theorem ParentChild.adjacent {a b : V} :
∀ {t : Tree V}, ParentChild a b t → Adjacent a b t
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
public def ParentChild (a b : V) : Tree V → Prop
| .node r cs => (r = a ∧ ∃ c ∈ cs, c.root = b) ∨ ParentChildList a b cs
where
/-- Directed parent-child adjacency inside one of a list of subtrees. -/
ParentChildList (a b : V) : List (Tree V) → Prop
| [] => False
| c :: cs => ParentChild a b c ∨ ParentChildList a b cs
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:2515
public def Adjacent (a b : V) : Tree V → Prop
| .node r cs =>
(r = a ∧ ∃ c ∈ cs, c.root = b) ∨ (r = b ∧ ∃ c ∈ cs, c.root = a) ∨
AdjacentList a b cs
where
/-- Adjacency inside one of a list of subtrees. -/
AdjacentList (a b : V) : List (Tree V) → Prop
| [] => False
| c :: cs => Adjacent a b c ∨ AdjacentList a b cs
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:606
Uses 5 · Used by 2
TheoremThe parent endpoint of a tree edge is a vertex#✓fully proved
If \(a\) is the parent of \(b\) somewhere in a tree \(t\), then \(a\) is a vertex of \(t\).
public theorem ParentChild.mem_left {a b : V} {t : Tree V}
(h : ParentChild a b t) : a ∈ Tree.vertices t
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
public def ParentChild (a b : V) : Tree V → Prop
| .node r cs => (r = a ∧ ∃ c ∈ cs, c.root = b) ∨ ParentChildList a b cs
where
/-- Directed parent-child adjacency inside one of a list of subtrees. -/
ParentChildList (a b : V) : List (Tree V) → Prop
| [] => False
| c :: cs => ParentChild a b c ∨ ParentChildList a b cs
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:2515
def vertices (t : Tree V) : List V :=
verticesAux t []
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:108
TheoremThe child endpoint of a tree edge is a vertex#✓fully proved
If \(a\) is the parent of \(b\) somewhere in a tree \(t\), then \(b\) is a vertex of \(t\).
public theorem ParentChild.mem_right {a b : V} {t : Tree V}
(h : ParentChild a b t) : b ∈ Tree.vertices t
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
public def ParentChild (a b : V) : Tree V → Prop
| .node r cs => (r = a ∧ ∃ c ∈ cs, c.root = b) ∨ ParentChildList a b cs
where
/-- Directed parent-child adjacency inside one of a list of subtrees. -/
ParentChildList (a b : V) : List (Tree V) → Prop
| [] => False
| c :: cs => ParentChild a b c ∨ ParentChildList a b cs
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:2515
def vertices (t : Tree V) : List V :=
verticesAux t []
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:108
TheoremA root path follows parent-child edges downward#✓fully proved
Let \(t\) be a tree and \(x\) a vertex. If the root path of \(x\) in \(t\) is defined and equals \(p = (p_0, \dots, p_k)\), then for every \(i < k\) the vertex \(p_i\) is the parent of \(p_{i+1}\) somewhere in \(t\).
public theorem isChain_parentChild_rootPath {x : V} :
∀ {t : Tree V} {p : List V}, rootPath x t = some p →
p.IsChain (fun a b => ParentChild a b t)
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
public def rootPath (x : V) : Tree V → Option (List V)
| .node r cs =>
if r = x then some [r] else (rootPathList x cs).map (fun p => r :: p)
where
rootPathList (x : V) : List (Tree V) → Option (List V)
| [] => none
| c :: cs =>
match rootPath x c with
| some p => some p
| none => rootPathList x cs
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:2324
public def ParentChild (a b : V) : Tree V → Prop
| .node r cs => (r = a ∧ ∃ c ∈ cs, c.root = b) ∨ ParentChildList a b cs
where
/-- Directed parent-child adjacency inside one of a list of subtrees. -/
ParentChildList (a b : V) : List (Tree V) → Prop
| [] => False
| c :: cs => ParentChild a b c ∨ ParentChildList a b cs
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:2515
Uses 6 · Used by 1
DefinitionConsecutive edges of a vertex path#✓fully proved
For a list of vertices \(v_0, v_1, \dots, v_n\), its path edges are the ordered pairs \((v_0, v_1), (v_1, v_2), \dots, (v_{n-1}, v_n)\) of consecutive vertices, in this order; a list with at most one vertex has no path edges. For a path listed from the root downward each pair is (parent, child), and the preferred edges installed by an access to a vertex \(x\) are the path edges of the root-to-\(x\) path.
public def pathEdges : List V → List (V × V)
| [] => []
| [_] => []
| a :: b :: rest => (a, b) :: pathEdges (b :: rest)
Used by 7
DefinitionPreferred-path decomposition of a tree#✓fully proved
Given a list \(E\) of preferred edges, each a pair (parent, preferred child), the decomposition of a tree \(T\) is a pair (down, rest): down is the preferred path that starts at the root of \(T\) and follows edges of \(E\) downward, and rest is the list of all other preferred paths of \(T\). When a node has several children joined to it by edges of \(E\) (excluded in valid states, where each vertex has at most one preferred child), the first one in child order continues the path through that node and each of the others starts its own path in rest.
Cslib.Algorithms.Lean.LinkCutTree.decomp · 18 lines
public def decomp (edges : List (V × V)) : Tree V → List V × List (List V)
| .node r cs =>
match decompList edges r cs with
| (ext, rest) => (r :: ext, rest)
where
/-- Combine the decompositions of the children of `r`: returns the
downward continuation below `r` (the root path of the preferred child, or
`[]` when no child is preferred) and every other path below `r`. -/
decompList (edges : List (V × V)) (r : V) :
List (Tree V) → List V × List (List V)
| [] => ([], [])
| c :: cs =>
match decomp edges c, decompList edges r cs with
| (cdown, crest), (ext, rest) =>
if (r, c.root) ∈ edges then
(cdown, crest ++ if ext = [] then rest else ext :: rest)
else
(ext, (cdown :: crest) ++ rest)
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
Uses 2 · Used by 8
DefinitionPreferred paths of a tree#✓fully proved
Let \(t\) be a rooted ordered tree and let \(E\) be a list of preferred edges, each a pair (parent, child). The preferred paths of \(t\) under \(E\) are listed as follows: first the downward path of the preferred-path decomposition of \(t\) under \(E\), which starts at the root of \(t\) and follows preferred edges downward, and then all other paths of that decomposition, in the order the decomposition returns them.
public def treePaths (edges : List (V × V)) (t : Tree V) : List (List V) :=
(decomp edges t).1 :: (decomp edges t).2
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
public def decomp (edges : List (V × V)) : Tree V → List V × List (List V)
| .node r cs =>
match decompList edges r cs with
| (ext, rest) => (r :: ext, rest)
where
/-- Combine the decompositions of the children of `r`: returns the
downward continuation below `r` (the root path of the preferred child, or
`[]` when no child is preferred) and every other path below `r`. -/
decompList (edges : List (V × V)) (r : V) :
List (Tree V) → List V × List (List V)
| [] => ([], [])
| c :: cs =>
⋯
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:2743
Uses 2 · Used by 8
TheoremThe downward preferred path starts at the root#✓fully proved
For every list of preferred edges, the downward preferred path in the preferred-path decomposition of a tree is nonempty and its first vertex is the root of the tree.
public theorem decomp_fst_head? (edges : List (V × V)) (t : Tree V) :
(decomp edges t).1.head? = some t.root
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
public def decomp (edges : List (V × V)) : Tree V → List V × List (List V)
| .node r cs =>
match decompList edges r cs with
| (ext, rest) => (r :: ext, rest)
where
/-- Combine the decompositions of the children of `r`: returns the
downward continuation below `r` (the root path of the preferred child, or
`[]` when no child is preferred) and every other path below `r`. -/
decompList (edges : List (V × V)) (r : V) :
List (Tree V) → List V × List (List V)
| [] => ([], [])
| c :: cs =>
⋯
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:2743
Uses 3 · Used by 1
TheoremPreferred paths permute the vertex list#✓fully proved
For every list of preferred edges, the downward preferred path of a tree followed by the concatenation of the other paths of its preferred-path decomposition is a permutation of the vertex list of the tree.
public theorem decomp_perm (edges : List (V × V)) (t : Tree V) :
((decomp edges t).1 ++ (decomp edges t).2.flatMap id).Perm
(Tree.vertices t)
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
public def decomp (edges : List (V × V)) : Tree V → List V × List (List V)
| .node r cs =>
match decompList edges r cs with
| (ext, rest) => (r :: ext, rest)
where
/-- Combine the decompositions of the children of `r`: returns the
downward continuation below `r` (the root path of the preferred child, or
`[]` when no child is preferred) and every other path below `r`. -/
decompList (edges : List (V × V)) (r : V) :
List (Tree V) → List V × List (List V)
| [] => ([], [])
| c :: cs =>
⋯
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:2743
def vertices (t : Tree V) : List V :=
verticesAux t []
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:108
Uses 6 · Used by 1
TheoremThe preferred paths of a tree rearrange its vertex list#✓fully proved
For every list \(E\) of directed edges and every rooted ordered tree \(t\), the concatenation of the preferred paths of \(t\) under \(E\) is a permutation of the preorder vertex list of \(t\).
public theorem perm_treePaths_flatMap (edges : List (V × V)) (t : Tree V) :
((treePaths edges t).flatMap id).Perm (Tree.vertices t)
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
public def treePaths (edges : List (V × V)) (t : Tree V) : List (List V) :=
(decomp edges t).1 :: (decomp edges t).2
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:2764
def vertices (t : Tree V) : List V :=
verticesAux t []
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:108
Uses 5 · Used by 2
TheoremDecomposition paths are paths of the tree#✓fully proved
For every list of preferred edges, in the preferred-path decomposition of a tree \(T\), the downward preferred path and every other path are paths of \(T\): any two consecutive vertices are joined by a parent-child edge of \(T\), in either direction.
public theorem decomp_isChain (edges : List (V × V)) (t : Tree V) :
(decomp edges t).1.IsChain (fun a b => Adjacent a b t) ∧
∀ p ∈ (decomp edges t).2, p.IsChain (fun a b => Adjacent a b t)
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
public def decomp (edges : List (V × V)) : Tree V → List V × List (List V)
| .node r cs =>
match decompList edges r cs with
| (ext, rest) => (r :: ext, rest)
where
/-- Combine the decompositions of the children of `r`: returns the
downward continuation below `r` (the root path of the preferred child, or
`[]` when no child is preferred) and every other path below `r`. -/
decompList (edges : List (V × V)) (r : V) :
List (Tree V) → List V × List (List V)
| [] => ([], [])
| c :: cs =>
⋯
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:2743
public def Adjacent (a b : V) : Tree V → Prop
| .node r cs =>
(r = a ∧ ∃ c ∈ cs, c.root = b) ∨ (r = b ∧ ∃ c ∈ cs, c.root = a) ∨
AdjacentList a b cs
where
/-- Adjacency inside one of a list of subtrees. -/
AdjacentList (a b : V) : List (Tree V) → Prop
| [] => False
| c :: cs => Adjacent a b c ∨ AdjacentList a b cs
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:606
Uses 7 · Used by 1
TheoremPreferred paths of a tree follow tree edges#✓fully proved
Let \(t\) be a tree and \(E\) any list of pairs of vertices, read as preferred (parent, child) edges. For every path \(p = (p_0, \dots, p_k)\) in the preferred-path decomposition of \(t\) under \(E\) and every \(i < k\), the vertices \(p_i\) and \(p_{i+1}\) are adjacent in \(t\), that is, joined by a parent-child edge of \(t\) in one direction or the other.
public theorem isChain_of_mem_treePaths {edges : List (V × V)} {t : Tree V}
{p : List V} (hp : p ∈ treePaths edges t) :
p.IsChain (fun a b => Adjacent a b t)
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
public def treePaths (edges : List (V × V)) (t : Tree V) : List (List V) :=
(decomp edges t).1 :: (decomp edges t).2
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:2764
public def Adjacent (a b : V) : Tree V → Prop
| .node r cs =>
(r = a ∧ ∃ c ∈ cs, c.root = b) ∨ (r = b ∧ ∃ c ∈ cs, c.root = a) ∨
AdjacentList a b cs
where
/-- Adjacency inside one of a list of subtrees. -/
AdjacentList (a b : V) : List (Tree V) → Prop
| [] => False
| c :: cs => Adjacent a b c ∨ AdjacentList a b cs
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:606
Uses 5 · Used by 1
TheoremAccess edges make the root path the downward preferred path#✓fully proved
Let \(T\) be a tree whose vertex list is duplicate-free, let \(x\) be a vertex of \(T\) with root path \(p\) (the path from the root of \(T\) down to \(x\)), and let \(E\) be a list of directed edges such that every consecutive pair of \(p\), parent first, lies in \(E\), and every edge of \(E\) whose first vertex lies on \(p\) is such a consecutive pair. Then the downward preferred path of the preferred-path decomposition of \(T\) under \(E\) is \(p\).
public theorem decomp_fst_eq_rootPath {x : V} {E : List (V × V)} :
∀ {t : Tree V} {p : List V}, (Tree.vertices t).Nodup →
rootPath x t = some p →
(∀ e ∈ pathEdges p, e ∈ E) →
(∀ e ∈ E, e.1 ∈ p → e ∈ pathEdges p) →
(decomp E t).1 = p
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
def vertices (t : Tree V) : List V :=
verticesAux t []
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:108
public def rootPath (x : V) : Tree V → Option (List V)
| .node r cs =>
if r = x then some [r] else (rootPathList x cs).map (fun p => r :: p)
where
rootPathList (x : V) : List (Tree V) → Option (List V)
| [] => none
| c :: cs =>
match rootPath x c with
| some p => some p
| none => rootPathList x cs
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:2324
public def pathEdges : List V → List (V × V)
| [] => []
| [_] => []
| a :: b :: rest => (a, b) :: pathEdges (b :: rest)
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:2608
public def decomp (edges : List (V × V)) : Tree V → List V × List (List V)
| .node r cs =>
match decompList edges r cs with
| (ext, rest) => (r :: ext, rest)
where
/-- Combine the decompositions of the children of `r`: returns the
downward continuation below `r` (the root path of the preferred child, or
`[]` when no child is preferred) and every other path below `r`. -/
decompList (edges : List (V × V)) (r : V) :
List (Tree V) → List V × List (List V)
| [] => ([], [])
| c :: cs =>
⋯
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:2743
Uses 11 · Used by 1
StructureLink-cut tree state#✓fully proved
A state of a link-cut tree over a vertex type \(V\) consists of the represented forest, a list of rooted ordered trees with vertices in \(V\), and a list of preferred (solid) edges, each a pair \((u, v)\) of vertices meant as the edge from a node \(u\) to its preferred child \(v\) in the represented forest; the structure itself does not require these pairs to be edges of the forest. The preferred-path decomposition is derived from the preferred edges as the maximal solid chains in each represented tree. With no preferred edges, every edge is dashed and every vertex is its own singleton path.
public structure State (V : Type u) where
/-- The represented forest. -/
forest : List (Tree V)
/-- The preferred edges, as `(parent, child)` pairs. -/
preferred : List (V × V)
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
Uses 1 · Used by 34
State
DefinitionVertex of a link-cut tree state#✓fully proved
A vertex \(x\) belongs to a link-cut tree state \(s\) when \(x\) is a vertex of some tree of the represented forest of \(s\).
public def Mem (s : State V) (x : V) : Prop :=
∃ t ∈ s.forest, x ∈ Tree.vertices t
public structure State (V : Type u) where
/-- The represented forest. -/
forest : List (Tree V)
/-- The preferred edges, as `(parent, child)` pairs. -/
preferred : List (V × V)
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:3181
def vertices (t : Tree V) : List V :=
verticesAux t []
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:108
Uses 3 · Used by 7
DefinitionConnectivity in a link-cut tree state#✓fully proved
Two vertices \(x\) and \(y\) are connected in a link-cut tree state \(s\) when some tree of the represented forest of \(s\) has both \(x\) and \(y\) among its vertices.
Connectivity is the abstraction against which the link-cut tree operations are specified.
public def Connected (s : State V) (x y : V) : Prop :=
∃ t ∈ s.forest, x ∈ Tree.vertices t ∧ y ∈ Tree.vertices t
public structure State (V : Type u) where
/-- The represented forest. -/
forest : List (Tree V)
/-- The preferred edges, as `(parent, child)` pairs. -/
preferred : List (V × V)
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:3181
def vertices (t : Tree V) : List V :=
verticesAux t []
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:108
Uses 3 · Used by 5
TheoremConnectivity via Euler tours#✓fully proved
For a link-cut tree state \(s\) and vertices \(x\) and \(y\), \(x\) and \(y\) are connected in \(s\) if and only if some tree of the represented forest of \(s\) contains both \(x\) and \(y\) in its Euler tour.
public theorem connected_iff_tour {x y : V} :
s.Connected x y ↔ ∃ t ∈ s.forest, x ∈ Tree.tour t ∧ y ∈ Tree.tour t
def tour (t : Tree V) : List V :=
tourAux t []
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:174
Uses 6
DefinitionValid link-cut tree states#✓fully proved
A link-cut tree state \(s\) is valid when four conditions hold: the concatenation of the vertex lists of the trees of its represented forest has no duplicates (so the trees are vertex-disjoint); its list of preferred edges has no duplicates; every preferred edge \((a, b)\) is a parent-child edge of some tree of the represented forest, with \(a\) the parent of \(b\); and any two preferred edges with the same parent are equal, so each vertex has at most one preferred child.
The duplicate-free vertex condition also pins down the parent of each vertex, so the maximal chains of preferred edges in each tree are genuine disjoint paths.
public def Valid (s : State V) : Prop :=
(s.forest.flatMap Tree.vertices).Nodup ∧
s.preferred.Nodup ∧
(∀ e ∈ s.preferred, ∃ t ∈ s.forest, ParentChild e.1 e.2 t) ∧
(∀ e₁ ∈ s.preferred, ∀ e₂ ∈ s.preferred, e₁.1 = e₂.1 → e₁ = e₂)
public structure State (V : Type u) where
/-- The represented forest. -/
forest : List (Tree V)
/-- The preferred edges, as `(parent, child)` pairs. -/
preferred : List (V × V)
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:3181
def vertices (t : Tree V) : List V :=
verticesAux t []
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:108
public def ParentChild (a b : V) : Tree V → Prop
| .node r cs => (r = a ∧ ∃ c ∈ cs, c.root = b) ∨ ParentChildList a b cs
where
/-- Directed parent-child adjacency inside one of a list of subtrees. -/
ParentChildList (a b : V) : List (Tree V) → Prop
| [] => False
| c :: cs => ParentChild a b c ∨ ParentChildList a b cs
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:2515
Uses 4 · Used by 13
TheoremValidity of states with no preferred edges#✓fully proved
Let \(s\) be a link-cut tree state whose list of preferred edges is empty. If the concatenation of the vertex lists of the trees of the represented forest of \(s\) has no duplicates, then \(s\) is valid.
This is the situation after every structural operation, which resets all edges to dashed.
public theorem valid_of_preferred_nil (hpre : s.preferred = [])
(h : (s.forest.flatMap Tree.vertices).Nodup) : s.Valid
def vertices (t : Tree V) : List V :=
verticesAux t []
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:108
Uses 5 · Used by 4
DefinitionPreferred-path decomposition of a link-cut tree state#✓fully proved
For a link-cut tree state \(s\), its preferred paths are obtained by taking, for each represented tree of \(s\) in forest order, the preferred paths of that tree under the preferred edges of \(s\), and concatenating these lists. Within a tree these are its maximal chains of preferred edges when each vertex has at most one preferred child, each listed from its shallowest to its deepest vertex; a vertex incident to no preferred edge forms a singleton path.
The decomposition keeps the preferred paths of every subtree, not one distinguished path, so an access changes only the preferred edges leaving vertices of the accessed root path.
public def paths (s : State V) : List (List V) :=
s.forest.flatMap (treePaths s.preferred)
public structure State (V : Type u) where
/-- The represented forest. -/
forest : List (Tree V)
/-- The preferred edges, as `(parent, child)` pairs. -/
preferred : List (V × V)
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:3181
public def treePaths (edges : List (V × V)) (t : Tree V) : List (List V) :=
(decomp edges t).1 :: (decomp edges t).2
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:2764
Uses 3 · Used by 6
TheoremPreferred paths cover exactly the vertices of the forest#✓fully proved
For every link-cut tree state \(s\) and every vertex \(v\), \(v\) lies on some path of the preferred-path decomposition of \(s\) if and only if \(v\) is a vertex of some tree of the represented forest of \(s\). No validity hypothesis on \(s\) is needed.
public theorem mem_paths_flatMap {v : V} :
v ∈ (paths s).flatMap id ↔ v ∈ s.forest.flatMap Tree.vertices
public def paths (s : State V) : List (List V) :=
s.forest.flatMap (treePaths s.preferred)
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:3281
def vertices (t : Tree V) : List V :=
verticesAux t []
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:108
TheoremPreferred paths cover each vertex at most once#✓fully proved
In a valid link-cut tree state, the concatenation of all preferred paths of the decomposition has no repeated vertex: no vertex occurs twice on one path or on two different paths.
Together with the fact that every vertex of the represented forest lies on some preferred path, the preferred paths partition the vertex set.
public theorem nodup_paths_flatMap (hs : s.Valid) :
((paths s).flatMap id).Nodup
public def paths (s : State V) : List (List V) :=
s.forest.flatMap (treePaths s.preferred)
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:3281
Uses 8 · Used by 2
TheoremPreferred paths are pairwise vertex-disjoint#✓fully proved
In a valid link-cut tree state, any two preferred paths at different positions of the preferred-path decomposition have no vertex in common.
public theorem pairwise_disjoint_paths (hs : s.Valid) :
(paths s).Pairwise List.Disjoint
public def paths (s : State V) : List (List V) :=
s.forest.flatMap (treePaths s.preferred)
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:3281
Uses 4
TheoremPreferred paths have distinct vertices#✓fully proved
Every preferred path of a valid state has distinct vertices.
public theorem nodup_of_mem_paths {p : List V} (hs : s.Valid)
(hp : p ∈ paths s) : p.Nodup
public def paths (s : State V) : List (List V) :=
s.forest.flatMap (treePaths s.preferred)
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:3281
Uses 4
TheoremPreferred paths of a link-cut tree state follow represented edges#✓fully proved
Let \(s\) be a link-cut tree state. For every path \(p = (p_0, \dots, p_k)\) in the preferred-path decomposition of \(s\) and every \(i < k\), some represented tree of \(s\) has \(p_i\) and \(p_{i+1}\) adjacent, that is, joined by a parent-child edge in one direction or the other.
This holds for every state, with no validity hypothesis.
public theorem isChain_of_mem_paths {p : List V} (hp : p ∈ paths s) :
p.IsChain (fun a b => ∃ t ∈ s.forest, Adjacent a b t)
public def paths (s : State V) : List (List V) :=
s.forest.flatMap (treePaths s.preferred)
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:3281
public def Adjacent (a b : V) : Tree V → Prop
| .node r cs =>
(r = a ∧ ∃ c ∈ cs, c.root = b) ∨ (r = b ∧ ∃ c ∈ cs, c.root = a) ∨
AdjacentList a b cs
where
/-- Adjacency inside one of a list of subtrees. -/
AdjacentList (a b : V) : List (Tree V) → Prop
| [] => False
| c :: cs => Adjacent a b c ∨ AdjacentList a b cs
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:606
DefinitionAccess in a link-cut tree#✓fully proved
Let \(s\) be a link-cut tree state and \(x\) a vertex. If \(x\) is a vertex of some tree of the represented forest of \(s\), let \(T\) be the first such tree and let \(p\) be the path in \(T\) from its root down to \(x\). Accessing \(x\) keeps the represented forest and replaces the preferred edges by those preferred edges of \(s\) whose parent endpoint is not on \(p\), followed by the edges of \(p\), each directed from parent to child. If \(x\) is not a vertex of the represented forest, accessing \(x\) leaves \(s\) unchanged.
Thus every edge of the root-to-\(x\) path becomes preferred, the previously preferred child edges of the vertices on that path are dropped, and preferred edges hanging off the path survive: in the tree with root \(1\), whose children are \(2\) and \(3\), where \(4\) is a child of \(2\) and \(5\) a child of \(3\), accessing \(5\) after accessing \(4\) keeps the preferred path \([2, 4]\), since the edge from \(2\) to \(4\) has its parent endpoint off the path \(1, 3, 5\).
public def access (x : V) (s : State V) : State V :=
match findTree x s.forest with
| some t =>
match rootPath x t with
| some p =>
⟨s.forest,
(s.preferred.filter (fun e => e.1 ∉ p)) ++ pathEdges p⟩
| none => s
| none => s
public structure State (V : Type u) where
/-- The represented forest. -/
forest : List (Tree V)
/-- The preferred edges, as `(parent, child)` pairs. -/
preferred : List (V × V)
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:3181
public def findTree (x : V) : List (Tree V) → Option (Tree V)
| [] => none
| t :: ts => if x ∈ Tree.vertices t then some t else findTree x ts
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:247
public def rootPath (x : V) : Tree V → Option (List V)
| .node r cs =>
if r = x then some [r] else (rootPathList x cs).map (fun p => r :: p)
where
rootPathList (x : V) : List (Tree V) → Option (List V)
| [] => none
| c :: cs =>
match rootPath x c with
| some p => some p
| none => rootPathList x cs
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:2324
public def pathEdges : List V → List (V × V)
| [] => []
| [_] => []
| a :: b :: rest => (a, b) :: pathEdges (b :: rest)
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:2608
Uses 5 · Used by 5
TheoremAccess keeps off-path preferred edges#✓fully proved
Let \(s\) be a link-cut tree state, \(x\) a vertex, and \((u, w)\) a preferred edge of \(s\), directed from the parent \(u\) to the child \(w\). Suppose that, if some tree of the represented forest of \(s\) contains \(x\), then \(u\) does not lie on the path in the first such tree from its root down to the first occurrence of \(x\) in preorder. Then \((u, w)\) is still a preferred edge after accessing \(x\).
This is the edge-level fact behind the persistence of off-path preferred paths across accesses.
public theorem mem_preferred_access {x : V} {e : V × V}
(he : e ∈ s.preferred)
(h : ∀ t p, findTree x s.forest = some t → rootPath x t = some p →
e.1 ∉ p) :
e ∈ (access x s).preferred
public def findTree (x : V) : List (Tree V) → Option (Tree V)
| [] => none
| t :: ts => if x ∈ Tree.vertices t then some t else findTree x ts
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:247
public def rootPath (x : V) : Tree V → Option (List V)
| .node r cs =>
if r = x then some [r] else (rootPathList x cs).map (fun p => r :: p)
where
rootPathList (x : V) : List (Tree V) → Option (List V)
| [] => none
| c :: cs =>
match rootPath x c with
| some p => some p
| none => rootPathList x cs
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:2324
public def access (x : V) (s : State V) : State V :=
match findTree x s.forest with
| some t =>
match rootPath x t with
| some p =>
⟨s.forest,
(s.preferred.filter (fun e => e.1 ∉ p)) ++ pathEdges p⟩
| none => s
| none => s
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:3349
Uses 6
TheoremAccess makes the root path preferred#✓fully proved
Let \(s\) be a link-cut tree state and \(x\) a vertex, let \(t\) be the first tree of the represented forest of \(s\) that contains \(x\), and let \(p\) be the path in \(t\) from the root down to the first occurrence of \(x\) in preorder. Then every edge of \(p\), taken as the pair (parent, child) of consecutive vertices of \(p\), is a preferred edge of the state obtained from \(s\) by accessing \(x\).
public theorem mem_preferred_access_of_mem_pathEdges {x : V} {t : Tree V}
{p : List V} {e : V × V} (hft : findTree x s.forest = some t)
(hrp : rootPath x t = some p) (he : e ∈ pathEdges p) :
e ∈ (access x s).preferred
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
public def findTree (x : V) : List (Tree V) → Option (Tree V)
| [] => none
| t :: ts => if x ∈ Tree.vertices t then some t else findTree x ts
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:247
public def rootPath (x : V) : Tree V → Option (List V)
| .node r cs =>
if r = x then some [r] else (rootPathList x cs).map (fun p => r :: p)
where
rootPathList (x : V) : List (Tree V) → Option (List V)
| [] => none
| c :: cs =>
match rootPath x c with
| some p => some p
| none => rootPathList x cs
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:2324
public def pathEdges : List V → List (V × V)
| [] => []
| [_] => []
| a :: b :: rest => (a, b) :: pathEdges (b :: rest)
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:2608
public def access (x : V) (s : State V) : State V :=
match findTree x s.forest with
| some t =>
match rootPath x t with
| some p =>
⟨s.forest,
(s.preferred.filter (fun e => e.1 ∉ p)) ++ pathEdges p⟩
| none => s
| none => s
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:3349
TheoremAccess leaves the represented forest unchanged#✓fully proved
For every link-cut tree state \(s\) and every vertex \(x\), accessing \(x\) changes only the preferred edges: the represented forest of the resulting state equals the represented forest of \(s\).
public theorem access_forest (x : V) : (access x s).forest = s.forest
public def access (x : V) (s : State V) : State V :=
match findTree x s.forest with
| some t =>
match rootPath x t with
| some p =>
⟨s.forest,
(s.preferred.filter (fun e => e.1 ∉ p)) ++ pathEdges p⟩
| none => s
| none => s
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:3349
Uses 6
TheoremAfter access, the accessed vertex ends its preferred path#✓fully proved
Let \(s\) be a valid link-cut tree state and let \(x\) be a vertex of its represented forest. Then, after accessing \(x\), the preferred-path decomposition of the new state contains a path \(p\) whose last vertex is \(x\), and \(p\) is the path from the root down to \(x\) in some tree of the represented forest of \(s\).
Paths are listed from the root downward, so \(x\) is the deepest vertex of \(p\). No auxiliary splay tree is modeled, so this is only the endpoint property of the accessed preferred path.
public theorem access_last {x : V} (hs : s.Valid) (hx : s.Mem x) :
∃ p ∈ paths (access x s), p.getLast? = some x ∧
∃ t ∈ s.forest, rootPath x t = some p
public def paths (s : State V) : List (List V) :=
s.forest.flatMap (treePaths s.preferred)
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:3281
public def access (x : V) (s : State V) : State V :=
match findTree x s.forest with
| some t =>
match rootPath x t with
| some p =>
⟨s.forest,
(s.preferred.filter (fun e => e.1 ∉ p)) ++ pathEdges p⟩
| none => s
| none => s
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:3349
public def rootPath (x : V) : Tree V → Option (List V)
| .node r cs =>
if r = x then some [r] else (rootPathList x cs).map (fun p => r :: p)
where
rootPathList (x : V) : List (Tree V) → Option (List V)
| [] => none
| c :: cs =>
match rootPath x c with
| some p => some p
| none => rootPathList x cs
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:2324
Uses 17
TheoremAccess preserves validity#✓fully proved
If a link-cut tree state \(s\) is valid, then for every vertex \(x\) the state obtained from \(s\) by accessing \(x\) is again valid.
The new preferred edges are the retained off-path edges together with the edges of the accessed root path; the two groups have disjoint parent endpoints (off versus on the path), so duplicate-freeness and the at-most-one-preferred-child condition carry over.
public theorem Valid.access {x : V} (hs : s.Valid) : (State.access x s).Valid
public def access (x : V) (s : State V) : State V :=
match findTree x s.forest with
| some t =>
match rootPath x t with
| some p =>
⟨s.forest,
(s.preferred.filter (fun e => e.1 ∉ p)) ++ pathEdges p⟩
| none => s
| none => s
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:3349
Uses 11
DefinitionMaking a vertex the root in a link-cut tree state#✓fully proved
Given a vertex \(x\) and a state \(s\), the state \(\operatorname{makeRoot}(x, s)\) has no preferred edges (all edges dashed), and its forest is defined as follows. If \(x\) is not a vertex of the forest, the forest is unchanged. Otherwise the first represented tree containing \(x\) is rerooted at \(x\): the edges on the path from its old root to \(x\) are reversed, and when the tree has distinct vertices every undirected edge is kept. The rerooted tree replaces every tree containing \(x\) and is placed at the end of the forest.
public def makeRoot (x : V) (s : State V) : State V :=
{ s with
preferred := []
forest :=
match findTree x s.forest with
| some t =>
match rerootAt x t with
| some t' => removeTree x s.forest ++ [t']
| none => s.forest
| none => s.forest }
public structure State (V : Type u) where
/-- The represented forest. -/
forest : List (Tree V)
/-- The preferred edges, as `(parent, child)` pairs. -/
preferred : List (V × V)
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:3181
public def findTree (x : V) : List (Tree V) → Option (Tree V)
| [] => none
| t :: ts => if x ∈ Tree.vertices t then some t else findTree x ts
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:247
public def rerootAt (x : V) : Tree V → Option (Tree V)
| .node r cs =>
if r = x then some (.node r cs)
else
match rerootAtList x cs with
| some (c', rest, p) => graftAt p (.node r rest) c'
| none => none
where
/-- Reroot the first child subtree containing `x`; returns the rerooted
child, the remaining sibling subtrees in order, and the root of the
original child (the next vertex on the root-to-`x` path, under which the
caller reattaches the remainder). -/
⋯
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:1355
public def removeTree (x : V) : List (Tree V) → List (Tree V)
| [] => []
| t :: ts => if x ∈ Tree.vertices t then removeTree x ts else t :: removeTree x ts
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:293
Uses 5 · Used by 9
TheoremMaking a vertex the root installs a tree rooted there#✓fully proved
Let \(s\) be a link-cut tree state and \(x\) a vertex of its represented forest. After making \(x\) the root, some represented tree has root \(x\) and contains \(x\) as a vertex.
That tree is the rerooted old tree of \(x\).
public theorem makeRoot_root {x : V} (hx : s.Mem x) :
∃ t ∈ (makeRoot x s).forest, t.root = x ∧ x ∈ Tree.vertices t
public def makeRoot (x : V) (s : State V) : State V :=
{ s with
preferred := []
forest :=
match findTree x s.forest with
| some t =>
match rerootAt x t with
| some t' => removeTree x s.forest ++ [t']
| none => s.forest
| none => s.forest }
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:3544
def vertices (t : Tree V) : List V :=
verticesAux t []
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:108
Uses 16
TheoremMaking a vertex the root keeps its connections#✓fully proved
Let \(s\) be a valid link-cut tree state and let \(x\) and \(y\) be connected in \(s\). Then \(x\) and \(y\) are still connected in the state obtained from \(s\) by making \(x\) the root of its represented tree.
Rerooting spans the same vertex set as the old tree and keeps every undirected edge; vertex disjointness of the represented trees pins down which tree contains \(x\).
public theorem connected_makeRoot {x y : V} (hs : s.Valid)
(h : s.Connected x y) : (makeRoot x s).Connected x y
public def makeRoot (x : V) (s : State V) : State V :=
{ s with
preferred := []
forest :=
match findTree x s.forest with
| some t =>
match rerootAt x t with
| some t' => removeTree x s.forest ++ [t']
| none => s.forest
| none => s.forest }
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:3544
Uses 19
TheoremRerooting a link-cut tree state preserves validity#✓fully proved
For every valid link-cut tree state \(s\) and every vertex \(x\), the state obtained from \(s\) by making \(x\) the root of its represented tree is valid.
The new forest has the same flat vertex list as the old one up to permutation (the rerooted tree replaces its original), and the preferred edges are reset.
public theorem Valid.makeRoot {x : V} (hs : s.Valid) :
(State.makeRoot x s).Valid
public def makeRoot (x : V) (s : State V) : State V :=
{ s with
preferred := []
forest :=
match findTree x s.forest with
| some t =>
match rerootAt x t with
| some t' => removeTree x s.forest ++ [t']
| none => s.forest
| none => s.forest }
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:3544
Uses 12 · Used by 3
DefinitionLinking two trees of a link-cut tree state#✓fully proved
Given vertices \(x\) and \(y\) and a state \(s\), the state \(\operatorname{link}(x, y, s)\) has no preferred edges (all edges dashed), and its forest is defined as follows. If \(x\) or \(y\) is not a vertex of the forest, the forest is unchanged. Otherwise let \(t_x\) and \(t_y\) be the first represented trees containing \(x\) and \(y\). If \(x\) is a vertex of \(t_y\), the forest is unchanged. Otherwise \(t_x\) is rerooted at \(x\) (the edges on its old root-to-\(x\) path are reversed, so \(x\) becomes its root), the result is attached as a new last child subtree of the first node labelled \(y\) in \(t_y\), which adds the edge from \(y\) to \(x\), and this joined tree replaces every tree containing \(x\) or \(y\), placed at the end of the forest.
Cslib.Algorithms.Lean.LinkCutTree.State.link · 15 lines
public def link (x y : V) (s : State V) : State V :=
{ s with
preferred := []
forest :=
match findTree x s.forest, findTree y s.forest with
| some tx, some ty =>
if x ∈ Tree.vertices ty then s.forest
else
match rerootAt x tx with
| some tx' =>
match graftAt y tx' ty with
| some tj => removeTree x (removeTree y s.forest) ++ [tj]
| none => s.forest
| none => s.forest
| _, _ => s.forest }
public structure State (V : Type u) where
/-- The represented forest. -/
forest : List (Tree V)
/-- The preferred edges, as `(parent, child)` pairs. -/
preferred : List (V × V)
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:3181
public def findTree (x : V) : List (Tree V) → Option (Tree V)
| [] => none
| t :: ts => if x ∈ Tree.vertices t then some t else findTree x ts
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:247
def vertices (t : Tree V) : List V :=
verticesAux t []
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:108
public def rerootAt (x : V) : Tree V → Option (Tree V)
| .node r cs =>
if r = x then some (.node r cs)
else
match rerootAtList x cs with
| some (c', rest, p) => graftAt p (.node r rest) c'
| none => none
where
/-- Reroot the first child subtree containing `x`; returns the rerooted
child, the remaining sibling subtrees in order, and the root of the
original child (the next vertex on the root-to-`x` path, under which the
caller reattaches the remainder). -/
⋯
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:1355
public def graftAt (y : V) (newChild : Tree V) : Tree V → Option (Tree V)
| .node r cs =>
if r = y then some (.node r (cs ++ [newChild]))
else (graftAtList y newChild cs).map (.node r)
where
graftAtList (y : V) (newChild : Tree V) :
List (Tree V) → Option (List (Tree V))
| [] => none
| c :: cs =>
match graftAt y newChild c with
| some c' => some (c' :: cs)
| none => (graftAtList y newChild cs).map (c :: ·)
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:856
public def removeTree (x : V) : List (Tree V) → List (Tree V)
| [] => []
| t :: ts => if x ∈ Tree.vertices t then removeTree x ts else t :: removeTree x ts
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:293
TheoremLinking connects the endpoints#✓fully proved
Let \(s\) be a link-cut tree state and let \(x\) and \(y\) be vertices of its represented forest. Then in the state obtained from \(s\) by linking \(x\) to \(y\), the vertices \(x\) and \(y\) are connected, that is, some represented tree contains both. No invariant on the state is needed.
public theorem connected_link {x y : V} (hx : s.Mem x) (hy : s.Mem y) :
(link x y s).Connected x y
public def link (x y : V) (s : State V) : State V :=
{ s with
preferred := []
forest :=
match findTree x s.forest, findTree y s.forest with
| some tx, some ty =>
if x ∈ Tree.vertices ty then s.forest
else
match rerootAt x tx with
| some tx' =>
match graftAt y tx' ty with
| some tj => removeTree x (removeTree y s.forest) ++ [tj]
⋯
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:3635
Uses 17
TheoremLinking in a link-cut tree preserves validity#✓fully proved
For every valid link-cut tree state \(s\) and all vertices \(x\) and \(y\), the state obtained from \(s\) by linking \(x\) and \(y\) is valid.
The joined tree has the union of the two old vertex lists up to permutation (rerooting and grafting both permute), the rest of the forest is untouched, and the preferred edges are reset.
public theorem Valid.link {x y : V} (hs : s.Valid) :
(State.link x y s).Valid
public def link (x y : V) (s : State V) : State V :=
{ s with
preferred := []
forest :=
match findTree x s.forest, findTree y s.forest with
| some tx, some ty =>
if x ∈ Tree.vertices ty then s.forest
else
match rerootAt x tx with
| some tx' =>
match graftAt y tx' ty with
| some tj => removeTree x (removeTree y s.forest) ++ [tj]
⋯
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:3635
Uses 14
DefinitionCutting off the subtree at a vertex#✓fully proved
Cutting at a vertex \(x\) resets the preferred edges of the state to the empty list and changes its forest as follows. If no tree of the forest contains \(x\), the forest is unchanged. Otherwise let \(T\) be the first tree containing \(x\) and \(S\) the first subtree of \(T\) rooted at \(x\) in preorder. Every tree containing \(x\) is removed from the forest, and two trees are appended at the end: first the remainder of \(T\) with every subtree rooted at \(x\) pruned off, then \(S\). When \(x\) is the root of \(T\) nothing remains, and only \(S\) is appended.
public def cut (x : V) (s : State V) : State V :=
{ s with
preferred := []
forest :=
match findTree x s.forest with
| some t =>
match findSubtree x t with
| some sub =>
match pruneAt x t with
| some rem => removeTree x s.forest ++ [rem, sub]
| none => removeTree x s.forest ++ [sub]
| none => s.forest
| none => s.forest }
public structure State (V : Type u) where
/-- The represented forest. -/
forest : List (Tree V)
/-- The preferred edges, as `(parent, child)` pairs. -/
preferred : List (V × V)
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:3181
public def findTree (x : V) : List (Tree V) → Option (Tree V)
| [] => none
| t :: ts => if x ∈ Tree.vertices t then some t else findTree x ts
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:247
public def findSubtree (x : V) : Tree V → Option (Tree V)
| .node r cs => if r = x then some (.node r cs) else findSubtreeList x cs
where
findSubtreeList (x : V) : List (Tree V) → Option (Tree V)
| [] => none
| c :: cs =>
match findSubtree x c with
| some s => some s
| none => findSubtreeList x cs
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:395
public def pruneAt (x : V) : Tree V → Option (Tree V)
| .node r cs => if r = x then none else some (.node r (pruneList x cs))
where
pruneList (x : V) : List (Tree V) → List (Tree V)
| [] => []
| c :: cs =>
match pruneAt x c with
| some c' => c' :: pruneList x cs
| none => pruneList x cs
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:1809
public def removeTree (x : V) : List (Tree V) → List (Tree V)
| [] => []
| t :: ts => if x ∈ Tree.vertices t then removeTree x ts else t :: removeTree x ts
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:293
Uses 6 · Used by 9
TheoremA cut disconnects a vertex from everything outside its subtree#✓fully proved
Let \(s\) be a link-cut tree state, let \(t\) be the first tree of its represented forest containing the vertex \(x\), and let \(u\) be the first subtree of \(t\) in preorder whose root is \(x\). After cutting \(s\) at \(x\), the vertex \(x\) is not connected to any vertex \(y\) that is not a vertex of \(u\).
No invariant on the state is needed.
public theorem not_connected_cut {x y : V} {t sub : Tree V}
(hft : findTree x s.forest = some t) (hsub : findSubtree x t = some sub)
(hy : y ∉ Tree.vertices sub) :
¬ (cut x s).Connected x y
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
public def findTree (x : V) : List (Tree V) → Option (Tree V)
| [] => none
| t :: ts => if x ∈ Tree.vertices t then some t else findTree x ts
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:247
public def findSubtree (x : V) : Tree V → Option (Tree V)
| .node r cs => if r = x then some (.node r cs) else findSubtreeList x cs
where
findSubtreeList (x : V) : List (Tree V) → Option (Tree V)
| [] => none
| c :: cs =>
match findSubtree x c with
| some s => some s
| none => findSubtreeList x cs
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:395
def vertices (t : Tree V) : List V :=
verticesAux t []
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:108
public def cut (x : V) (s : State V) : State V :=
{ s with
preferred := []
forest :=
match findTree x s.forest with
| some t =>
match findSubtree x t with
| some sub =>
match pruneAt x t with
| some rem => removeTree x s.forest ++ [rem, sub]
| none => removeTree x s.forest ++ [sub]
| none => s.forest
⋯
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:3785
Uses 13 · Used by 1
TheoremBoth sides of a cut remain in the forest#✓fully proved
Let \(s\) be a link-cut tree state, let \(x\) and \(y\) be vertices, and let \(t\) be the first tree of the represented forest of \(s\) that contains \(x\). Suppose no vertex occurs twice in \(t\), and let \(T_x\) be the subtree of \(t\) rooted at \(x\). If \(y\) is a vertex of \(t\) but not of \(T_x\), then after cutting \(s\) at \(x\) both \(x\) and \(y\) are vertices of the represented forest.
public theorem mem_cut {x y : V} {t sub : Tree V}
(hnodup : (Tree.vertices t).Nodup)
(hft : findTree x s.forest = some t) (hsub : findSubtree x t = some sub)
(hy : y ∈ Tree.vertices t) (hy' : y ∉ Tree.vertices sub) :
(cut x s).Mem x ∧ (cut x s).Mem y
inductive Tree (V : Type u) where
| node (root : V) (children : List (Tree V)) : Tree V
deriving Repr
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:54
def vertices (t : Tree V) : List V :=
verticesAux t []
CSLibExt/Algorithms/Lean/DataStructures/EulerTourTree.lean:108
public def findTree (x : V) : List (Tree V) → Option (Tree V)
| [] => none
| t :: ts => if x ∈ Tree.vertices t then some t else findTree x ts
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:247
public def findSubtree (x : V) : Tree V → Option (Tree V)
| .node r cs => if r = x then some (.node r cs) else findSubtreeList x cs
where
findSubtreeList (x : V) : List (Tree V) → Option (Tree V)
| [] => none
| c :: cs =>
match findSubtree x c with
| some s => some s
| none => findSubtreeList x cs
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:395
public def cut (x : V) (s : State V) : State V :=
{ s with
preferred := []
forest :=
match findTree x s.forest with
| some t =>
match findSubtree x t with
| some sub =>
match pruneAt x t with
| some rem => removeTree x s.forest ++ [rem, sub]
| none => removeTree x s.forest ++ [sub]
| none => s.forest
⋯
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:3785
TheoremCutting preserves validity#✓fully proved
If \(s\) is a valid link-cut tree state, then for every vertex \(x\) the state obtained from \(s\) by cutting off the subtree rooted at \(x\) is again valid.
Pruning splits the vertices of the cut tree into those of the remainder and those of the detached subtree, the rest of the forest is untouched, and the preferred edges are reset.
public theorem Valid.cut {x : V} (hs : s.Valid) : (State.cut x s).Valid
public def cut (x : V) (s : State V) : State V :=
{ s with
preferred := []
forest :=
match findTree x s.forest with
| some t =>
match findSubtree x t with
| some sub =>
match pruneAt x t with
| some rem => removeTree x s.forest ++ [rem, sub]
| none => removeTree x s.forest ++ [sub]
| none => s.forest
⋯
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:3785
Uses 13 · Used by 1
DefinitionCutting an edge of a link-cut tree#✓fully proved
For vertices \(x\) and \(y\) and a link-cut tree state \(s\), cutting the edge between \(x\) and \(y\) works as follows. If \(x\) and \(y\) are adjacent in some tree of the represented forest of \(s\), the result is obtained from \(s\) by first making \(x\) the root of its represented tree and then cutting off the subtree rooted at \(y\). Otherwise the represented forest is left unchanged. In both cases the list of preferred edges becomes empty.
When \(x\) and \(y\) are joined by an edge of a valid state, making \(x\) the root turns \(y\) into the root of a child subtree of \(x\), so the cut separates the two sides of the edge between \(x\) and \(y\) and keeps every other edge.
The adjacency test is necessary: without it the composite would cut at \(y\) regardless of \(x\). For instance, on the chain \(1 \to 2\) it would detach \(2\) when asked to cut the edge between \(99\) and \(2\), although there is no such edge.
public def cutEdge (x y : V) (s : State V) : State V :=
if s.forest.any (adjacentB x y) then cut y (makeRoot x s)
else { s with preferred := [] }
public structure State (V : Type u) where
/-- The represented forest. -/
forest : List (Tree V)
/-- The preferred edges, as `(parent, child)` pairs. -/
preferred : List (V × V)
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:3181
public def adjacentB (a b : V) : Tree V → Bool
| .node r cs =>
(decide (r = a) && cs.any (fun c => decide (c.root = b))) ||
(decide (r = b) && cs.any (fun c => decide (c.root = a))) ||
adjacentBList a b cs
where
/-- Adjacency test over a list of subtrees. -/
adjacentBList (a b : V) : List (Tree V) → Bool
| [] => false
| c :: cs => adjacentB a b c || adjacentBList a b cs
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:721
public def cut (x : V) (s : State V) : State V :=
{ s with
preferred := []
forest :=
match findTree x s.forest with
| some t =>
match findSubtree x t with
| some sub =>
match pruneAt x t with
| some rem => removeTree x s.forest ++ [rem, sub]
| none => removeTree x s.forest ++ [sub]
| none => s.forest
⋯
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:3785
public def makeRoot (x : V) (s : State V) : State V :=
{ s with
preferred := []
forest :=
match findTree x s.forest with
| some t =>
match rerootAt x t with
| some t' => removeTree x s.forest ++ [t']
| none => s.forest
| none => s.forest }
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:3544
Uses 5 · Used by 5
TheoremEdge cut on an adjacent pair#✓fully proved
Let \(s\) be a link-cut tree state and let \(x\) and \(y\) be adjacent in some tree of the represented forest of \(s\). Then cutting the edge between \(x\) and \(y\) in \(s\) gives the same state as first making \(x\) the root of its represented tree and then cutting off the subtree rooted at \(y\).
public theorem cutEdge_eq_cut_makeRoot_of_adjacent {x y : V}
(hadj : ∃ t ∈ s.forest, Adjacent x y t) :
cutEdge x y s = cut y (makeRoot x s)
public def Adjacent (a b : V) : Tree V → Prop
| .node r cs =>
(r = a ∧ ∃ c ∈ cs, c.root = b) ∨ (r = b ∧ ∃ c ∈ cs, c.root = a) ∨
AdjacentList a b cs
where
/-- Adjacency inside one of a list of subtrees. -/
AdjacentList (a b : V) : List (Tree V) → Prop
| [] => False
| c :: cs => Adjacent a b c ∨ AdjacentList a b cs
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:606
public def cutEdge (x y : V) (s : State V) : State V :=
if s.forest.any (adjacentB x y) then cut y (makeRoot x s)
else { s with preferred := [] }
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:3980
public def cut (x : V) (s : State V) : State V :=
{ s with
preferred := []
forest :=
match findTree x s.forest with
| some t =>
match findSubtree x t with
| some sub =>
match pruneAt x t with
| some rem => removeTree x s.forest ++ [rem, sub]
| none => removeTree x s.forest ++ [sub]
| none => s.forest
⋯
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:3785
public def makeRoot (x : V) (s : State V) : State V :=
{ s with
preferred := []
forest :=
match findTree x s.forest with
| some t =>
match rerootAt x t with
| some t' => removeTree x s.forest ++ [t']
| none => s.forest
| none => s.forest }
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:3544
Uses 9 · Used by 2
TheoremEdge cut on a non-adjacent pair#✓fully proved
Let \(s\) be a link-cut tree state and let \(x\) and \(y\) be adjacent in no tree of the represented forest of \(s\). Then cutting the edge between \(x\) and \(y\) in \(s\) leaves the represented forest unchanged and makes the list of preferred edges empty.
In particular, no other edge at \(y\) is cut.
public theorem cutEdge_eq_of_not_adjacent {x y : V}
(hadj : ¬ ∃ t ∈ s.forest, Adjacent x y t) :
cutEdge x y s = { s with preferred := [] }
public def Adjacent (a b : V) : Tree V → Prop
| .node r cs =>
(r = a ∧ ∃ c ∈ cs, c.root = b) ∨ (r = b ∧ ∃ c ∈ cs, c.root = a) ∨
AdjacentList a b cs
where
/-- Adjacency inside one of a list of subtrees. -/
AdjacentList (a b : V) : List (Tree V) → Prop
| [] => False
| c :: cs => Adjacent a b c ∨ AdjacentList a b cs
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:606
public def cutEdge (x y : V) (s : State V) : State V :=
if s.forest.any (adjacentB x y) then cut y (makeRoot x s)
else { s with preferred := [] }
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:3980
Uses 9
TheoremEdge cutting preserves validity#✓fully proved
If \(s\) is a valid link-cut tree state, then for all vertices \(x\) and \(y\) the state obtained from \(s\) by cutting the edge between \(x\) and \(y\) is again valid.
On an adjacent pair the edge cut makes \(x\) the root of its tree and then cuts off the subtree rooted at \(y\); otherwise it only resets the preferred edges.
public theorem Valid.cutEdge {x y : V} (hs : s.Valid) :
(State.cutEdge x y s).Valid
public def cutEdge (x y : V) (s : State V) : State V :=
if s.forest.any (adjacentB x y) then cut y (makeRoot x s)
else { s with preferred := [] }
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:3980
Uses 12
TheoremCutting an edge separates its endpoints#✓fully proved
Let \(s\) be a valid link-cut tree state and let \(x\) and \(y\) be adjacent in some tree of the represented forest of \(s\). After the edge cut of \(x\) and \(y\) in \(s\), the vertices \(x\) and \(y\) are not connected: no represented tree contains both.
public theorem not_connected_cutEdge {x y : V} (hs : s.Valid)
(hadj : ∃ t ∈ s.forest, Adjacent x y t) :
¬ (cutEdge x y s).Connected x y
public def Adjacent (a b : V) : Tree V → Prop
| .node r cs =>
(r = a ∧ ∃ c ∈ cs, c.root = b) ∨ (r = b ∧ ∃ c ∈ cs, c.root = a) ∨
AdjacentList a b cs
where
/-- Adjacency inside one of a list of subtrees. -/
AdjacentList (a b : V) : List (Tree V) → Prop
| [] => False
| c :: cs => Adjacent a b c ∨ AdjacentList a b cs
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:606
public def cutEdge (x y : V) (s : State V) : State V :=
if s.forest.any (adjacentB x y) then cut y (makeRoot x s)
else { s with preferred := [] }
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:3980
Uses 30
TheoremAn edge cut keeps every other edge#✓fully proved
Let \(s\) be a valid link-cut tree state and let \(x\) and \(y\) be adjacent in some tree of its represented forest. If \(a\) and \(b\) are adjacent in some tree of the represented forest of \(s\), and neither \(a = x\) and \(b = y\) nor \(a = y\) and \(b = x\), then \(a\) and \(b\) are adjacent in some tree of the represented forest obtained from \(s\) by cutting the edge between \(x\) and \(y\).
Edges of other trees pass through untouched; edges of the cut tree survive the rerooting at \(x\) and then lie on one side of the prune at \(y\), and the only edge crossing the prune is the edge between \(x\) and \(y\).
public theorem adjacent_cutEdge {x y a b : V} (hs : s.Valid)
(hadj : ∃ t ∈ s.forest, Adjacent x y t)
(hab : ∃ t ∈ s.forest, Adjacent a b t)
(hxy : ¬ ((a = x ∧ b = y) ∨ (a = y ∧ b = x))) :
∃ t ∈ (cutEdge x y s).forest, Adjacent a b t
public def Adjacent (a b : V) : Tree V → Prop
| .node r cs =>
(r = a ∧ ∃ c ∈ cs, c.root = b) ∨ (r = b ∧ ∃ c ∈ cs, c.root = a) ∨
AdjacentList a b cs
where
/-- Adjacency inside one of a list of subtrees. -/
AdjacentList (a b : V) : List (Tree V) → Prop
| [] => False
| c :: cs => Adjacent a b c ∨ AdjacentList a b cs
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:606
public def cutEdge (x y : V) (s : State V) : State V :=
if s.forest.any (adjacentB x y) then cut y (makeRoot x s)
else { s with preferred := [] }
CSLibExt/Algorithms/Lean/DataStructures/LinkCutTree.lean:3980
Uses 32
Loading dependency explorer…
The dependency explorer needs JavaScript and its graph data.