Documentation

Std.Data.UnionFind.Basic

structure Std.UFNode :

Union-find node type

  • parent : Nat

    Parent of node

  • rank : Nat

    Rank of node

Instances For
    def Std.UnionFind.panicWith {α : Type u_1} (v : α) (msg : String) :
    α

    Panic with return value

    Equations
    Instances For
      @[simp]
      theorem Std.UnionFind.panicWith_eq {α : Type u_1} (v : α) (msg : String) :

      Parent of a union-find node, defaults to self when the node is a root

      Equations
      Instances For

        Rank of a union-find node, defaults to 0 when the node is a root

        Equations
        Instances For
          theorem Std.UnionFind.parentD_eq {arr : Array Std.UFNode} {i : Fin arr.size} :
          Std.UnionFind.parentD arr i = (arr.get i).parent
          theorem Std.UnionFind.parentD_eq' {arr : Array Std.UFNode} {i : Nat} (h : i < arr.size) :
          Std.UnionFind.parentD arr i = (arr.get i, h).parent
          theorem Std.UnionFind.rankD_eq {arr : Array Std.UFNode} {i : Fin arr.size} :
          Std.UnionFind.rankD arr i = (arr.get i).rank
          theorem Std.UnionFind.rankD_eq' {arr : Array Std.UFNode} {i : Nat} (h : i < arr.size) :
          Std.UnionFind.rankD arr i = (arr.get i, h).rank
          theorem Std.UnionFind.lt_of_parentD {arr : Array Std.UFNode} {i : Nat} :
          Std.UnionFind.parentD arr i ii < arr.size
          theorem Std.UnionFind.parentD_set {arr : Array Std.UFNode} {x : Fin arr.size} {v : Std.UFNode} {i : Nat} :
          Std.UnionFind.parentD (arr.set x v) i = if x = i then v.parent else Std.UnionFind.parentD arr i
          theorem Std.UnionFind.rankD_set {arr : Array Std.UFNode} {x : Fin arr.size} {v : Std.UFNode} {i : Nat} :
          Std.UnionFind.rankD (arr.set x v) i = if x = i then v.rank else Std.UnionFind.rankD arr i
          structure Std.UnionFind :

          Union-find data structure #

          The UnionFind structure is an implementation of disjoint-set data structure that uses path compression to make the primary operations run in amortized nearly linear time. The nodes of a UnionFind structure s are natural numbers smaller than s.size. The structure associates with a canonical representative from its equivalence class. The structure can be extended using the push operation and equivalence classes can be updated using the union operation.

          The main operations for UnionFind are:

          • empty/mkEmpty are used to create a new empty structure.
          • size returns the size of the data structure.
          • push adds a new node to a structure, unlinked to any other node.
          • union links two nodes of the data structure, joining their equivalence classes, and performs path compression.
          • find returns the canonical representative of a node and updates the data structure using path compression.
          • root returns the canonical representative of a node without altering the data structure.
          • checkEquiv checks whether two nodes have the same canonical representative and updates the structure using path compression.

          Most use cases should prefer find over root to benefit from the speedup from path-compression.

          The main operations use Fin s.size to represent nodes of the union-find structure. Some alternatives are provided:

          The noncomputable relation UnionFind.Equiv is provided to use the equivalence relation from a UnionFind structure in the context of proofs.

          Instances For
            theorem Std.UnionFind.parentD_lt (self : Std.UnionFind) {i : Nat} :
            i < self.arr.sizeStd.UnionFind.parentD self.arr i < self.arr.size

            Validity for parent nodes

            theorem Std.UnionFind.rankD_lt (self : Std.UnionFind) {i : Nat} :

            Validity for rank

            @[reducible, inline]

            Size of union-find structure.

            Equations
            • self.size = self.arr.size
            Instances For

              Create an empty union-find structure with specific capacity

              Equations
              Instances For

                Empty union-find structure

                Equations
                Instances For
                  @[reducible, inline]
                  abbrev Std.UnionFind.parent (self : Std.UnionFind) (i : Nat) :

                  Parent of union-find node

                  Equations
                  Instances For
                    theorem Std.UnionFind.parent'_lt (self : Std.UnionFind) (i : Fin self.size) :
                    (self.arr.get i).parent < self.size
                    theorem Std.UnionFind.parent_lt (self : Std.UnionFind) (i : Nat) :
                    self.parent i < self.size i < self.size
                    @[reducible, inline]
                    abbrev Std.UnionFind.rank (self : Std.UnionFind) (i : Nat) :

                    Rank of union-find node

                    Equations
                    Instances For
                      theorem Std.UnionFind.rank_lt {self : Std.UnionFind} {i : Nat} :
                      self.parent i iself.rank i < self.rank (self.parent i)
                      theorem Std.UnionFind.rank'_lt (self : Std.UnionFind) (i : Fin self.size) :
                      (self.arr.get i).parent iself.rank i < self.rank (self.arr.get i).parent
                      noncomputable def Std.UnionFind.rankMax (self : Std.UnionFind) :

                      Maximum rank of nodes in a union-find structure

                      Equations
                      Instances For
                        theorem Std.UnionFind.rank'_lt_rankMax (self : Std.UnionFind) (i : Fin self.size) :
                        (self.arr.get i).rank < self.rankMax
                        theorem Std.UnionFind.rank'_lt_rankMax.go {l : List Std.UFNode} {x : Std.UFNode} :
                        x lx.rank List.foldr (fun (x : Std.UFNode) => max x.rank) 0 l
                        theorem Std.UnionFind.rankD_lt_rankMax (self : Std.UnionFind) (i : Nat) :
                        Std.UnionFind.rankD self.arr i < self.rankMax
                        theorem Std.UnionFind.lt_rankMax (self : Std.UnionFind) (i : Nat) :
                        self.rank i < self.rankMax
                        theorem Std.UnionFind.push_rankD {i : Nat} (arr : Array Std.UFNode) :
                        Std.UnionFind.rankD (arr.push { parent := arr.size, rank := 0 }) i = Std.UnionFind.rankD arr i
                        theorem Std.UnionFind.push_parentD {i : Nat} (arr : Array Std.UFNode) :
                        Std.UnionFind.parentD (arr.push { parent := arr.size, rank := 0 }) i = Std.UnionFind.parentD arr i

                        Add a new node to a union-find structure, unlinked with any other nodes

                        Equations
                        • self.push = { arr := self.arr.push { parent := self.arr.size, rank := 0 }, parentD_lt := , rankD_lt := }
                        Instances For
                          def Std.UnionFind.root (self : Std.UnionFind) (x : Fin self.size) :
                          Fin self.size

                          Root of a union-find node.

                          Equations
                          • self.root x = if h : (self.arr.get x).parent = x then x else let_fun this := ; self.root (self.arr.get x).parent,
                          Instances For
                            def Std.UnionFind.rootN {n : Nat} (self : Std.UnionFind) (x : Fin n) (h : n = self.size) :
                            Fin n

                            Root of a union-find node.

                            Equations
                            • self.rootN x h = match n, h, x with | .(self.size), , x => self.root x
                            Instances For

                              Root of a union-find node. Panics if index is out of bounds.

                              Equations
                              Instances For

                                Root of a union-find node. Returns input if index is out of bounds.

                                Equations
                                • self.rootD x = if h : x < self.size then (self.root x, h) else x
                                Instances For
                                  theorem Std.UnionFind.parent_root (self : Std.UnionFind) (x : Fin self.size) :
                                  (self.arr.get (self.root x)).parent = (self.root x)
                                  theorem Std.UnionFind.parent_rootD (self : Std.UnionFind) (x : Nat) :
                                  self.parent (self.rootD x) = self.rootD x
                                  theorem Std.UnionFind.rootD_parent (self : Std.UnionFind) (x : Nat) :
                                  self.rootD (self.parent x) = self.rootD x
                                  theorem Std.UnionFind.rootD_lt {self : Std.UnionFind} {x : Nat} :
                                  self.rootD x < self.size x < self.size
                                  theorem Std.UnionFind.rootD_eq_self {self : Std.UnionFind} {x : Nat} :
                                  self.rootD x = x self.parent x = x
                                  theorem Std.UnionFind.rootD_rootD {self : Std.UnionFind} {x : Nat} :
                                  self.rootD (self.rootD x) = self.rootD x
                                  theorem Std.UnionFind.rootD_ext {m1 : Std.UnionFind} {m2 : Std.UnionFind} (H : ∀ (x : Nat), m1.parent x = m2.parent x) {x : Nat} :
                                  m1.rootD x = m2.rootD x
                                  theorem Std.UnionFind.le_rank_root {self : Std.UnionFind} {x : Nat} :
                                  self.rank x self.rank (self.rootD x)
                                  theorem Std.UnionFind.lt_rank_root {self : Std.UnionFind} {x : Nat} :
                                  self.rank x < self.rank (self.rootD x) self.parent x x
                                  structure Std.UnionFind.FindAux (n : Nat) :

                                  Auxiliary data structure for find operation

                                  • Array of nodes

                                  • root : Fin n

                                    Index of root node

                                  • size_eq : self.s.size = n

                                    Size requirement

                                  Instances For
                                    theorem Std.UnionFind.FindAux.size_eq {n : Nat} (self : Std.UnionFind.FindAux n) :
                                    self.s.size = n

                                    Size requirement

                                    def Std.UnionFind.findAux (self : Std.UnionFind) (x : Fin self.size) :

                                    Auxiliary function for find operation

                                    Equations
                                    • One or more equations did not get rendered due to their size.
                                    Instances For
                                      theorem Std.UnionFind.findAux_root {self : Std.UnionFind} {x : Fin self.size} :
                                      (self.findAux x).root = self.root x
                                      theorem Std.UnionFind.findAux_s {self : Std.UnionFind} {x : Fin self.size} :
                                      (self.findAux x).s = if (self.arr.get x).parent = x then self.arr else (self.findAux (self.arr.get x).parent, ).s.modify x fun (s : Std.UFNode) => { parent := self.rootD x, rank := s.rank }
                                      theorem Std.UnionFind.rankD_findAux {i : Nat} {self : Std.UnionFind} {x : Fin self.size} :
                                      Std.UnionFind.rankD (self.findAux x).s i = self.rank i
                                      theorem Std.UnionFind.parentD_findAux {i : Nat} {self : Std.UnionFind} {x : Fin self.size} :
                                      Std.UnionFind.parentD (self.findAux x).s i = if i = x then self.rootD x else Std.UnionFind.parentD (self.findAux (self.arr.get x).parent, ).s i
                                      theorem Std.UnionFind.parentD_findAux_rootD {self : Std.UnionFind} {x : Fin self.size} :
                                      Std.UnionFind.parentD (self.findAux x).s (self.rootD x) = self.rootD x
                                      theorem Std.UnionFind.parentD_findAux_lt {i : Nat} {self : Std.UnionFind} {x : Fin self.size} (h : i < self.size) :
                                      Std.UnionFind.parentD (self.findAux x).s i < self.size
                                      theorem Std.UnionFind.parentD_findAux_or (self : Std.UnionFind) (x : Fin self.size) (i : Nat) :
                                      Std.UnionFind.parentD (self.findAux x).s i = self.rootD i self.rootD i = self.rootD x Std.UnionFind.parentD (self.findAux x).s i = self.parent i
                                      theorem Std.UnionFind.lt_rankD_findAux {i : Nat} {self : Std.UnionFind} {x : Fin self.size} :
                                      Std.UnionFind.parentD (self.findAux x).s i iself.rank i < self.rank (Std.UnionFind.parentD (self.findAux x).s i)
                                      def Std.UnionFind.find (self : Std.UnionFind) (x : Fin self.size) :
                                      (s : Std.UnionFind) × { _root : Fin s.size // s.size = self.size }

                                      Find root of a union-find node, updating the structure using path compression.

                                      Equations
                                      • self.find x = let r := self.findAux x; { arr := r.s, parentD_lt := , rankD_lt := }, r.root, ,
                                      Instances For
                                        def Std.UnionFind.findN {n : Nat} (self : Std.UnionFind) (x : Fin n) (h : n = self.size) :

                                        Find root of a union-find node, updating the structure using path compression.

                                        Equations
                                        • self.findN x h = match n, h, x with | .(self.size), , x => match self.find x with | s, r, h => (s, Fin.cast h r)
                                        Instances For

                                          Find root of a union-find node, updating the structure using path compression. Panics if index is out of bounds.

                                          Equations
                                          • self.find! x = if h : x < self.size then match self.find x, h with | s, r, property => (s, r) else Std.UnionFind.panicWith (self, x) "index out of bounds"
                                          Instances For

                                            Find root of a union-find node, updating the structure using path compression. Returns inputs unchanged when index is out of bounds.

                                            Equations
                                            • self.findD x = if h : x < self.size then match self.find x, h with | s, r, property => (s, r) else (self, x)
                                            Instances For
                                              @[simp]
                                              theorem Std.UnionFind.find_size (self : Std.UnionFind) (x : Fin self.size) :
                                              (self.find x).fst.size = self.size
                                              @[simp]
                                              theorem Std.UnionFind.find_root_2 (self : Std.UnionFind) (x : Fin self.size) :
                                              (self.find x).snd.val = self.rootD x
                                              @[simp]
                                              theorem Std.UnionFind.find_parent_1 (self : Std.UnionFind) (x : Fin self.size) :
                                              (self.find x).fst.parent x = self.rootD x
                                              theorem Std.UnionFind.find_parent_or (self : Std.UnionFind) (x : Fin self.size) (i : Nat) :
                                              (self.find x).fst.parent i = self.rootD i self.rootD i = self.rootD x (self.find x).fst.parent i = self.parent i
                                              @[simp]
                                              theorem Std.UnionFind.find_root_1 (self : Std.UnionFind) (x : Fin self.size) (i : Nat) :
                                              (self.find x).fst.rootD i = self.rootD i
                                              def Std.UnionFind.linkAux (self : Array Std.UFNode) (x : Fin self.size) (y : Fin self.size) :

                                              Link two union-find nodes

                                              Equations
                                              • One or more equations did not get rendered due to their size.
                                              Instances For
                                                theorem Std.UnionFind.setParentBump_rankD_lt {arr' : Array Std.UFNode} {arr : Array Std.UFNode} {x : Fin arr.size} {y : Fin arr.size} (hroot : (arr.get x).rank < (arr.get y).rank (arr.get y).parent = y) (H : (arr.get x).rank (arr.get y).rank) {i : Nat} (rankD_lt : Std.UnionFind.parentD arr i iStd.UnionFind.rankD arr i < Std.UnionFind.rankD arr (Std.UnionFind.parentD arr i)) (hP : Std.UnionFind.parentD arr' i = if x = i then y else Std.UnionFind.parentD arr i) (hR : ∀ {i : Nat}, Std.UnionFind.rankD arr' i = if y = i (arr.get x).rank = (arr.get y).rank then (arr.get y).rank + 1 else Std.UnionFind.rankD arr i) :
                                                theorem Std.UnionFind.setParent_rankD_lt {arr : Array Std.UFNode} {x : Fin arr.size} {y : Fin arr.size} (h : (arr.get x).rank < (arr.get y).rank) {i : Nat} (rankD_lt : Std.UnionFind.parentD arr i iStd.UnionFind.rankD arr i < Std.UnionFind.rankD arr (Std.UnionFind.parentD arr i)) :
                                                let arr' := arr.set x { parent := y, rank := (arr.get x).rank }; Std.UnionFind.parentD arr' i iStd.UnionFind.rankD arr' i < Std.UnionFind.rankD arr' (Std.UnionFind.parentD arr' i)
                                                @[simp]
                                                theorem Std.UnionFind.linkAux_size {self : Array Std.UFNode} {x : Fin self.size} {y : Fin self.size} :
                                                (Std.UnionFind.linkAux self x y).size = self.size
                                                def Std.UnionFind.linkN {n : Nat} (self : Std.UnionFind) (x : Fin n) (y : Fin n) (yroot : self.parent y = y) (h : n = self.size) :

                                                Link a union-find node to a root node.

                                                Equations
                                                • self.linkN x y yroot h = match n, h, x, y, yroot with | .(self.size), , x, y, yroot => self.link x y yroot
                                                Instances For
                                                  def Std.UnionFind.link! (self : Std.UnionFind) (x : Nat) (y : Nat) (yroot : self.parent y = y) :

                                                  Link a union-find node to a root node. Panics if either index is out of bounds.

                                                  Equations
                                                  • self.link! x y yroot = if h : x < self.size y < self.size then self.link x, y, yroot else Std.UnionFind.panicWith self "index out of bounds"
                                                  Instances For
                                                    def Std.UnionFind.union (self : Std.UnionFind) (x : Fin self.size) (y : Fin self.size) :

                                                    Link two union-find nodes, uniting their respective classes.

                                                    Equations
                                                    • self.union x y = match self.find x with | self₁, rx, ex => let_fun hy := ; match eq : self₁.find y, hy with | self₂, ry, ey => self₂.link rx, ry
                                                    Instances For
                                                      def Std.UnionFind.unionN {n : Nat} (self : Std.UnionFind) (x : Fin n) (y : Fin n) (h : n = self.size) :

                                                      Link two union-find nodes, uniting their respective classes.

                                                      Equations
                                                      • self.unionN x y h = match n, h, x, y with | .(self.size), , x, y => self.union x y
                                                      Instances For

                                                        Link two union-find nodes, uniting their respective classes. Panics if either index is out of bounds.

                                                        Equations
                                                        • self.union! x y = if h : x < self.size y < self.size then self.union x, y, else Std.UnionFind.panicWith self "index out of bounds"
                                                        Instances For
                                                          def Std.UnionFind.checkEquiv (self : Std.UnionFind) (x : Fin self.size) (y : Fin self.size) :

                                                          Check whether two union-find nodes are equivalent, updating structure using path compression.

                                                          Equations
                                                          • self.checkEquiv x y = match self.find x with | s, r₁, isLt, h => match s.find (y) with | s_1, r₂, isLt, property => (s_1, r₁ == r₂)
                                                          Instances For
                                                            def Std.UnionFind.checkEquivN {n : Nat} (self : Std.UnionFind) (x : Fin n) (y : Fin n) (h : n = self.size) :

                                                            Check whether two union-find nodes are equivalent, updating structure using path compression.

                                                            Equations
                                                            • self.checkEquivN x y h = match n, h, x, y with | .(self.size), , x, y => self.checkEquiv x y
                                                            Instances For

                                                              Check whether two union-find nodes are equivalent, updating structure using path compression. Panics if either index is out of bounds.

                                                              Equations
                                                              • self.checkEquiv! x y = if h : x < self.size y < self.size then self.checkEquiv x, y, else Std.UnionFind.panicWith (self, false) "index out of bounds"
                                                              Instances For

                                                                Check whether two union-find nodes are equivalent with path compression, returns x == y if either index is out of bounds

                                                                Equations
                                                                • self.checkEquivD x y = match self.findD x with | (s, x) => match s.findD y with | (s, y) => (s, x == y)
                                                                Instances For
                                                                  def Std.UnionFind.Equiv (self : Std.UnionFind) (a : Nat) (b : Nat) :

                                                                  Equivalence relation from a UnionFind structure

                                                                  Equations
                                                                  • self.Equiv a b = (self.rootD a = self.rootD b)
                                                                  Instances For