Documentation

Batteries.Data.UnionFind.Basic

Union-find node type

  • parent : Nat

    Parent of node

  • rank : Nat

    Rank of node

Instances For
    def Batteries.UnionFind.parentD (arr : Array UFNode) (i : Nat) :
    Nat

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

    Equations
    Instances For
      def Batteries.UnionFind.rankD (arr : Array UFNode) (i : Nat) :
      Nat

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

      Equations
      Instances For
        theorem Batteries.UnionFind.parentD_eq {arr : Array UFNode} {i : Nat} (h : i < arr.size) :
        parentD arr i = arr[i].parent
        theorem Batteries.UnionFind.rankD_eq {arr : Array UFNode} {i : Nat} (h : i < arr.size) :
        rankD arr i = arr[i].rank
        theorem Batteries.UnionFind.parentD_of_not_lt {i : Nat} {arr : Array UFNode} :
        ยฌi < arr.size โ†’ parentD arr i = i
        theorem Batteries.UnionFind.lt_of_parentD {arr : Array UFNode} {i : Nat} :
        parentD arr i โ‰  i โ†’ i < arr.size
        theorem Batteries.UnionFind.parentD_set {arr : Array UFNode} {x : Nat} {v : UFNode} {i : Nat} {h : x < arr.size} :
        parentD (arr.set x v h) i = if x = i then v.parent else parentD arr i
        theorem Batteries.UnionFind.rankD_set {arr : Array UFNode} {x : Nat} {v : UFNode} {i : Nat} {h : x < arr.size} :
        rankD (arr.set x v h) i = if x = i then v.rank else rankD arr i

        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
          @[reducible, inline]
          abbrev Batteries.UnionFind.size (self : UnionFind) :
          Nat

          Size of union-find structure.

          Equations
          Instances For

            Create an empty union-find structure with specific capacity

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

              Parent of union-find node

              Equations
              Instances For
                theorem Batteries.UnionFind.parent'_lt (self : UnionFind) (i : Nat) (h : i < self.arr.size) :
                self.arr[i].parent < self.size
                theorem Batteries.UnionFind.parent_lt (self : UnionFind) (i : Nat) :
                self.parent i < self.size โ†” i < self.size
                @[reducible, inline]
                abbrev Batteries.UnionFind.rank (self : UnionFind) (i : Nat) :
                Nat

                Rank of union-find node

                Equations
                Instances For
                  theorem Batteries.UnionFind.rank_lt {self : UnionFind} {i : Nat} :
                  self.parent i โ‰  i โ†’ self.rank i < self.rank (self.parent i)
                  theorem Batteries.UnionFind.rank'_lt (self : UnionFind) (i : Nat) (h : i < self.arr.size) :
                  self.arr[i].parent โ‰  i โ†’ self.rank i < self.rank self.arr[i].parent
                  noncomputable def Batteries.UnionFind.rankMax (self : UnionFind) :
                  Nat

                  Maximum rank of nodes in a union-find structure

                  Equations
                  Instances For
                    theorem Batteries.UnionFind.rank'_lt_rankMax (self : UnionFind) (i : Nat) (h : i < self.arr.size) :
                    self.arr[i].rank < self.rankMax
                    theorem Batteries.UnionFind.push_rankD {i : Nat} (arr : Array UFNode) :
                    rankD (arr.push { parent := arr.size, rank := 0 }) i = rankD arr i
                    theorem Batteries.UnionFind.push_parentD {i : Nat} (arr : Array UFNode) :
                    parentD (arr.push { parent := arr.size, rank := 0 }) i = 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
                      @[irreducible]
                      def Batteries.UnionFind.root (self : UnionFind) (x : Fin self.size) :
                      Fin self.size

                      Root of a union-find node.

                      Equations
                      • self.root x = if h : self.arr[โ†‘x].parent = โ†‘x then x else have this := โ‹ฏ; self.root โŸจself.arr[โ†‘x].parent, โ‹ฏโŸฉ
                      Instances For
                        def Batteries.UnionFind.rootN {n : Nat} (self : UnionFind) (x : Fin n) (h : n = self.size) :
                        Fin n

                        Root of a union-find node.

                        Equations
                        Instances For
                          def Batteries.UnionFind.root! (self : UnionFind) (x : Nat) :
                          Nat

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

                          Equations
                          Instances For
                            def Batteries.UnionFind.rootD (self : UnionFind) (x : Nat) :
                            Nat

                            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
                              @[irreducible]
                              theorem Batteries.UnionFind.parent_root (self : UnionFind) (x : Fin self.size) :
                              self.arr[โ†‘(self.root x)].parent = โ†‘(self.root x)
                              theorem Batteries.UnionFind.parent_rootD (self : UnionFind) (x : Nat) :
                              self.parent (self.rootD x) = self.rootD x
                              theorem Batteries.UnionFind.rootD_parent (self : UnionFind) (x : Nat) :
                              self.rootD (self.parent x) = self.rootD x
                              theorem Batteries.UnionFind.rootD_lt {self : UnionFind} {x : Nat} :
                              self.rootD x < self.size โ†” x < self.size
                              theorem Batteries.UnionFind.rootD_eq_self {self : UnionFind} {x : Nat} :
                              self.rootD x = x โ†” self.parent x = x
                              theorem Batteries.UnionFind.rootD_rootD {self : UnionFind} {x : Nat} :
                              self.rootD (self.rootD x) = self.rootD x
                              @[irreducible]
                              theorem Batteries.UnionFind.rootD_ext {m1 m2 : UnionFind} (H : โˆ€ (x : Nat), m1.parent x = m2.parent x) {x : Nat} :
                              m1.rootD x = m2.rootD x
                              @[irreducible]
                              theorem Batteries.UnionFind.le_rank_root {self : UnionFind} {x : Nat} :
                              self.rank x โ‰ค self.rank (self.rootD x)
                              theorem Batteries.UnionFind.lt_rank_root {self : UnionFind} {x : Nat} :
                              self.rank x < self.rank (self.rootD x) โ†” self.parent x โ‰  x
                              structure Batteries.UnionFind.FindAux (n : Nat) :

                              Auxiliary data structure for find operation

                              • s : Array UFNode

                                Array of nodes

                              • root : Fin n

                                Index of root node

                              • size_eq : self.s.size = n

                                Size requirement

                              Instances For
                                @[irreducible]
                                def Batteries.UnionFind.findAux (self : 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
                                  @[irreducible]
                                  theorem Batteries.UnionFind.findAux_root {self : UnionFind} {x : Fin self.size} :
                                  (self.findAux x).root = self.root x
                                  theorem Batteries.UnionFind.findAux_s {self : UnionFind} {x : Fin self.size} :
                                  (self.findAux x).s = if self.arr[โ†‘x].parent = โ†‘x then self.arr else (self.findAux โŸจself.arr[โ†‘x].parent, โ‹ฏโŸฉ).s.modify โ†‘x fun (s : UFNode) => { parent := self.rootD โ†‘x, rank := s.rank }
                                  @[irreducible]
                                  theorem Batteries.UnionFind.rankD_findAux {i : Nat} {self : UnionFind} {x : Fin self.size} :
                                  rankD (self.findAux x).s i = self.rank i
                                  theorem Batteries.UnionFind.parentD_findAux {i : Nat} {self : UnionFind} {x : Fin self.size} :
                                  parentD (self.findAux x).s i = if i = โ†‘x then self.rootD โ†‘x else parentD (self.findAux โŸจself.arr[โ†‘x].parent, โ‹ฏโŸฉ).s i
                                  @[irreducible]
                                  theorem Batteries.UnionFind.parentD_findAux_rootD {self : UnionFind} {x : Fin self.size} :
                                  parentD (self.findAux x).s (self.rootD โ†‘x) = self.rootD โ†‘x
                                  @[irreducible]
                                  theorem Batteries.UnionFind.parentD_findAux_lt {i : Nat} {self : UnionFind} {x : Fin self.size} (h : i < self.size) :
                                  parentD (self.findAux x).s i < self.size
                                  @[irreducible]
                                  theorem Batteries.UnionFind.parentD_findAux_or (self : UnionFind) (x : Fin self.size) (i : Nat) :
                                  parentD (self.findAux x).s i = self.rootD i โˆง self.rootD i = self.rootD โ†‘x โˆจ parentD (self.findAux x).s i = self.parent i
                                  @[irreducible]
                                  theorem Batteries.UnionFind.lt_rankD_findAux {i : Nat} {self : UnionFind} {x : Fin self.size} :
                                  parentD (self.findAux x).s i โ‰  i โ†’ self.rank i < self.rank (parentD (self.findAux x).s i)
                                  def Batteries.UnionFind.find (self : UnionFind) (x : Fin self.size) :
                                  (s : 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 = โŸจ{ arr := (self.findAux x).s, parentD_lt := โ‹ฏ, rankD_lt := โ‹ฏ }, โŸจโŸจโ†‘(self.findAux x).root, โ‹ฏโŸฉ, โ‹ฏโŸฉโŸฉ
                                  Instances For
                                    def Batteries.UnionFind.findN {n : Nat} (self : UnionFind) (x : Fin n) (h : n = self.size) :
                                    UnionFind ร— Fin n

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

                                    Equations
                                    • self.findN x_2 โ‹ฏ = match self.find x_2 with | โŸจs, โŸจr, hโŸฉโŸฉ => (s, Fin.cast h r)
                                    Instances For
                                      def Batteries.UnionFind.find! (self : UnionFind) (x : Nat) :
                                      UnionFind ร— Nat

                                      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 Batteries.panicWith (self, x) "index out of bounds"
                                      Instances For
                                        def Batteries.UnionFind.findD (self : UnionFind) (x : Nat) :
                                        UnionFind ร— Nat

                                        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 Batteries.UnionFind.find_size (self : UnionFind) (x : Fin self.size) :
                                          (self.find x).fst.size = self.size
                                          @[simp]
                                          theorem Batteries.UnionFind.find_root_2 (self : UnionFind) (x : Fin self.size) :
                                          โ†‘(self.find x).snd.val = self.rootD โ†‘x
                                          @[simp]
                                          theorem Batteries.UnionFind.find_parent_1 (self : UnionFind) (x : Fin self.size) :
                                          (self.find x).fst.parent โ†‘x = self.rootD โ†‘x
                                          theorem Batteries.UnionFind.find_parent_or (self : 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, irreducible]
                                          theorem Batteries.UnionFind.find_root_1 (self : UnionFind) (x : Fin self.size) (i : Nat) :
                                          (self.find x).fst.rootD i = self.rootD i
                                          def Batteries.UnionFind.linkAux (self : Array UFNode) (x y : Fin self.size) :
                                          Array UFNode

                                          Link two union-find nodes

                                          Equations
                                          • One or more equations did not get rendered due to their size.
                                          Instances For
                                            theorem Batteries.UnionFind.setParentBump_rankD_lt {arr' arr : Array UFNode} {x y : Fin arr.size} (hroot : arr[โ†‘x].rank < arr[โ†‘y].rank โˆจ arr[โ†‘y].parent = โ†‘y) (H : arr[โ†‘x].rank โ‰ค arr[โ†‘y].rank) {i : Nat} (rankD_lt : parentD arr i โ‰  i โ†’ rankD arr i < rankD arr (parentD arr i)) (hP : parentD arr' i = if โ†‘x = i then โ†‘y else parentD arr i) (hR : โˆ€ {i_1 : Nat}, rankD arr' i_1 = if โ†‘y = i_1 โˆง arr[โ†‘x].rank = arr[โ†‘y].rank then arr[โ†‘y].rank + 1 else rankD arr i_1) :
                                            ยฌparentD arr' i = i โ†’ rankD arr' i < rankD arr' (parentD arr' i)
                                            theorem Batteries.UnionFind.setParent_rankD_lt {arr : Array UFNode} {x y : Fin arr.size} (h : arr[โ†‘x].rank < arr[โ†‘y].rank) {i : Nat} (rankD_lt : parentD arr i โ‰  i โ†’ rankD arr i < rankD arr (parentD arr i)) :
                                            have arr' := arr.set โ†‘x { parent := โ†‘y, rank := arr[x].rank } โ‹ฏ; parentD arr' i โ‰  i โ†’ rankD arr' i < rankD arr' (parentD arr' i)
                                            @[simp]
                                            theorem Batteries.UnionFind.linkAux_size {self : Array UFNode} {x y : Fin self.size} :
                                            (linkAux self x y).size = self.size
                                            def Batteries.UnionFind.linkN {n : Nat} (self : UnionFind) (x 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_2 y_2 yroot_2 โ‹ฏ = self.link x_2 y_2 yroot_2
                                            Instances For
                                              def Batteries.UnionFind.link! (self : UnionFind) (x 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 Batteries.panicWith self "index out of bounds"
                                              Instances For
                                                def Batteries.UnionFind.union (self : UnionFind) (x 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โŸฉโŸฉ => have hy := โ‹ฏ; match eq : selfโ‚.find โŸจโ†‘y, hyโŸฉ with | โŸจselfโ‚‚, โŸจry, eyโŸฉโŸฉ => selfโ‚‚.link โŸจโ†‘rx, โ‹ฏโŸฉ ry โ‹ฏ
                                                Instances For
                                                  def Batteries.UnionFind.unionN {n : Nat} (self : UnionFind) (x y : Fin n) (h : n = self.size) :

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

                                                  Equations
                                                  Instances For

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

                                                    Equations
                                                    Instances For
                                                      def Batteries.UnionFind.checkEquiv (self : UnionFind) (x y : Fin self.size) :
                                                      UnionFind ร— Bool

                                                      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 Batteries.UnionFind.checkEquivN {n : Nat} (self : UnionFind) (x y : Fin n) (h : n = self.size) :
                                                        UnionFind ร— Bool

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

                                                        Equations
                                                        Instances For
                                                          def Batteries.UnionFind.checkEquiv! (self : UnionFind) (x y : Nat) :
                                                          UnionFind ร— Bool

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

                                                          Equations
                                                          Instances For
                                                            def Batteries.UnionFind.checkEquivD (self : UnionFind) (x y : Nat) :
                                                            UnionFind ร— Bool

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

                                                            Equations
                                                            Instances For
                                                              def Batteries.UnionFind.Equiv (self : UnionFind) (a b : Nat) :

                                                              Equivalence relation from a UnionFind structure

                                                              Equations
                                                              Instances For