Documentation

DescriptiveComplexity.Examples.GraphCrawling

Worked example: web crawling – data acquisition as graph crawling #

This file is the library's second tutorial, a companion to DescriptiveComplexity.Examples.ConjunctiveQueries: it walks, step by step, through the addition of a new problem domain, ending in an NP-completeness theorem and a machine-checked concrete encoding. The domain is Web data acquisition: graph crawling, the optimization problem underlying focused crawling of structured documents, formalized by Gauquier–Manolescu–Senellart 2026. A website is a rooted directed graph of pages and hyperlinks; a crawl is an r-rooted subtree; the decision problem asks for a crawl containing every target page within a cost budget. The paper proves this NP-complete (its Prop. 4) already for unit page costs, by reduction from Set Cover; that unit-cost variant is what this file formalizes, following the paper's proof.

The file follows the user-first arc of the conjunctive-query tutorial: start from the concrete problem in the user's own formalism (step 1), construct the encoding with the machinery of DescriptiveComplexity.Encoding – size bounds discharged at construction (step 3) – prove the encoded problem equivalent to the concrete one (step 6), and only then establish the NP-completeness of the encoded variant (steps 7–9), which faithfulness reads back to the concrete instances. Every step exercises machinery the CQ file does not, which is why this example is worth reading second:

Main results:

Step 1: the concrete problem, in the user's own formalism #

A user does not start from finite structures: they start from the data of their own development. Here that is a packaged crawling instance – a page count, a set of links, a root, a set of targets, a budget – with the textbook semantics as a plain Lean predicate. Nothing in this step mentions model theory; it is the problem as the paper states it, and it is what the final completeness theorem will be about, through the faithfulness theorem of step 5.

A packaged concrete crawling instance: n + 1 pages, the hyperlinks, the root page, the target pages, and the budget (clamped to n + 1 by its type: a crawl never has more pages than the site).

  • n :

    The page count, minus one: pages are Fin (n + 1), so a website is never empty.

  • edges : Finset (Fin (self.n + 1) × Fin (self.n + 1))

    The hyperlinks.

  • root : Fin (self.n + 1)

    The root page, where crawls start.

  • targets : Finset (Fin (self.n + 1))

    The target pages.

  • budget : Fin (self.n + 2)

    The budget, clamped by its type: a crawl never has more pages than the site.

Instances For
    Dependency graph
    Equations
    • One or more equations did not get rendered due to their size.
    Instances For
      Dependency graph
      Dependency graph

      The textbook size of a packaged instance: pages, links, targets, and the budget in unary. The one audited line of the encoding.

      Equations
      Instances For
        Dependency graph

        The textbook semantics of a packaged instance: some set of pages containing the root and every target, each of its pages reachable from the root by links inside it, within budget.

        Equations
        • One or more equations did not get rendered due to their size.
        Instances For
          Dependency graph

          Step 2: the vocabulary of website graphs #

          An instance is a single finite structure: the pages, the directed links, a mark for the root, a mark for the targets, and a marked set whose cardinality is the budget – the unary representation of numbers, as used by Set Cover, Steiner Tree and the other threshold problems of the catalog.

          Relation symbols of the language of website graphs.

          Instances For
            Dependency graph
            Dependency graph
            def FirstOrder.Language.instDecidableEqSiteGraphRel.decEq {a✝ : } (x✝ x✝¹ : siteGraphRel a✝) :
            Decidable (x✝ = x✝¹)
            Equations
            • One or more equations did not get rendered due to their size.
            Instances For
              Dependency graph

              The relational language of website graphs: directed links, a root, a set of target pages, and a marked set whose cardinality is the crawling budget.

              Equations
              Instances For
                Dependency graph
                Dependency graph
                @[reducible, inline]

                The edge symbol of website graphs.

                Equations
                Instances For
                  Dependency graph
                  @[reducible, inline]

                  The root symbol of website graphs.

                  Equations
                  Instances For
                    Dependency graph
                    @[reducible, inline]

                    The target symbol of website graphs.

                    Equations
                    Instances For
                      Dependency graph
                      @[reducible, inline]

                      The mark symbol of website graphs.

                      Equations
                      Instances For
                        Dependency graph

                        Step 3: the encoding, size bounds discharged at construction #

                        With the vocabulary fixed, the concrete instances are encoded as finite structures using DescriptiveComplexity.Encoding: a computable encoder (crawlRelBool, standalone so it can be audited in isolation) and the bundle whose card_le/le_card fields force the encoding to be size-honest – no padding, no compression – before anything is proved about its meaning.

                        Two packaging choices are dictated by the machinery:

                        The encoder, standalone and auditable (cf. cqRelBool): a plain def, so the compiler vouches that it computes, and the #guards below run it.

                        Equations
                        Instances For
                          Dependency graph

                          The encoding of packaged crawling instances by Language.siteGraph-structures: the pages themselves as universe, the budget decoded as the marked initial segment DescriptiveComplexity.initSeg. Both size bounds are discharged at construction.

                          Equations
                          • One or more equations did not get rendered due to their size.
                          Instances For
                            Dependency graph

                            Step 4: abstract semantics – rooted reachability, crawls, and their certificates #

                            The paper defines a crawl as an r-rooted subtree of the website; the semantics below phrases "some r-rooted subtree with node set S" as "every node of S is reachable from r by edges inside S" – equivalent, since the parent pointers of a breadth-first traversal assemble any such reachable set into a tree, and it is precisely those parent pointers that the first-order certificate recovers (each non-root node has an in-neighbour strictly closer to the root). Reachability itself is a transitive-closure condition, not first-order; as for connectivity in the Steiner-tree problem, the certificate is what makes the membership proof possible, and it reuses the DescriptiveComplexity.reachIn staging for the distance that Relation.ReflTransGen does not carry.

                            def DescriptiveComplexity.ReachesAllOn {A : Type} (Adjp : AAProp) (r : A) (S : AProp) :

                            Every member of S is reachable from r by directed steps inside S – the shape of an r-rooted subtree with node set S, reachability being all a breadth-first traversal needs to assemble the tree.

                            Equations
                            Instances For
                              Dependency graph
                              theorem DescriptiveComplexity.reachesAllOn_iff_exists_order {A : Type} [Finite A] (Adjp : AAProp) (r : A) (S : AProp) :
                              ReachesAllOn Adjp r S ∃ (Lt : AAProp), (∀ (x y z : A), Lt x yLt y zLt x z) (∀ (x : A), ¬Lt x x) ∀ (x : A), S xx r∃ (y : A), S y Adjp y x Lt y x

                              Rooted reachability is first-order certifiable: every member of S is reachable from r inside S exactly when some strict partial order makes every non-root member of S have a chosen in-neighbour strictly below it. Walking down the order reaches the root; the order “distance to the root” witnesses the converse. The in-neighbours below are the parent pointers of an r-rooted spanning subtree of S.

                              Dependency graph

                              The crawling property #

                              def DescriptiveComplexity.CrawlOn {A : Type} (Adjp : AAProp) (Rp Tp Kp : AProp) :

                              Some marked root admits a crawl: a set of pages containing the root and every target, entirely reachable from the root inside itself, of size (the paper's total cost, at unit page costs) at most the number encoded by the marked set.

                              Equations
                              • One or more equations did not get rendered due to their size.
                              Instances For
                                Dependency graph
                                theorem DescriptiveComplexity.crawlOn_iff_certificate {A : Type} [Finite A] (Adjp : AAProp) (Rp Tp Kp : AProp) :
                                CrawlOn Adjp Rp Tp Kp ∃ (S : AProp), (∀ (x : A), Tp xS x) (∃ (Rt : AProp), (∃ (x : A), Rt x) (∀ (x : A), Rt xRp x S x) (∀ (x y : A), Rt xRt yx = y) ∃ (Lt : AAProp), (∀ (x y z : A), Lt x yLt y zLt x z) (∀ (x : A), ¬Lt x x) ∀ (x : A), S x¬Rt x∃ (y : A), S y Adjp y x Lt y x) Nonempty ({ x : A // S x } { x : A // Kp x })

                                The certified form, with reachability witnessed by an order on the chosen set and the budget by an injection into the marked set: the shape the second-order definition guesses. The root is guessed as a relation constrained to hold of exactly one element, which the object language can express.

                                Dependency graph
                                theorem DescriptiveComplexity.CrawlOn.of_equiv {A B : Type} (u : B A) {AdjB : BBProp} {RB TB KB : BProp} {AdjA : AAProp} {RA TA KA : AProp} (hadj : ∀ (b b' : B), AdjB b b' AdjA (u b) (u b')) (hR : ∀ (b : B), RB b RA (u b)) (hT : ∀ (b : B), TB b TA (u b)) (hK : ∀ (b : B), KB b KA (u b)) (h : CrawlOn AdjB RB TB KB) :
                                CrawlOn AdjA RA TA KA

                                CrawlOn transports along an equivalence commuting with the four predicates.

                                Dependency graph
                                theorem DescriptiveComplexity.CrawlOn.equiv_iff {A B : Type} (u : B A) {AdjB : BBProp} {RB TB KB : BProp} {AdjA : AAProp} {RA TA KA : AProp} (hadj : ∀ (b b' : B), AdjB b b' AdjA (u b) (u b')) (hR : ∀ (b : B), RB b RA (u b)) (hT : ∀ (b : B), TB b TA (u b)) (hK : ∀ (b : B), KB b KA (u b)) :
                                CrawlOn AdjB RB TB KB CrawlOn AdjA RA TA KA

                                CrawlOn transports along an equivalence, iff version.

                                Dependency graph

                                Step 5: isomorphism-invariance and the bundled problem #

                                As always, the invariance proof is a transport of the RelMap shorthands along the isomorphism via the shared relMap_equiv₁/ lemmas; the junk conventions were stated with the semantics (a structure marking no root is a no-instance, one marking several is read disjunctively).

                                Dependency graph
                                Dependency graph
                                Dependency graph
                                Dependency graph

                                A website graph admits a crawl within budget: a set of pages containing the marked root and every target, reachable from the root inside itself, with at most as many pages as the marked set has elements. (Finiteness of the universe is part of the property: cardinality thresholds are only meaningful on finite structures.)

                                Equations
                                • One or more equations did not get rendered due to their size.
                                Instances For
                                  Dependency graph
                                  Dependency graph

                                  GRAPH CRAWLING (Gauquier–Manolescu–Senellart 2026, decision variant, unit page costs), as a problem on website graphs: is there a crawl – a set of pages containing the marked root and every target, reachable from the root inside itself – of at most as many pages as the marked set has elements?

                                  Equations
                                  Instances For
                                    Dependency graph

                                    Step 6: faithfulness – the encoded problem is the concrete one #

                                    The bridge between steps 1 and 5: the abstract problem computes the textbook semantics on every encoded instance (Encoding.Faithful). With the size bounds already discharged by the bundle of step 3, this equivalence is the whole of the encoding obligation – from here on, every theorem about GraphCrawling reads back to the concrete instances. The worked instance and the #guards then run the encoder against a hand computation.

                                    The decoding direction is where well-formedness earns its keep. An abstract structure may mark several roots (read disjunctively by the semantics), and no packaged instance – carrying a single root – transcribes such a structure without deciding which root works, a computation a decoder should not contain. The well-formedness sentence crawlWFSentence ("exactly one root") removes these, and on well-formed structures a computable decoder crawlDecode exists: find the root, read the links, targets and clamped budget off the tables. It assembles into DescriptiveComplexity.crawlDecoding, runs (#guards below), and step 9 restricts the completeness theorem to well-formed instances accordingly (crawlWF_NP_complete). See DescriptiveComplexity/Decoding.lean for why the bundled computation – and not an -only covering statement – is the meaningful notion.

                                    The packaged encoding is faithful: the abstract problem GraphCrawling computes the textbook semantics on every encoded instance – obligation (1), with obligation (2) already discharged by the bundle.

                                    Dependency graph

                                    A small worked instance: four pages, root 0, links 0 → 1, 1 → 2 and 0 → 3, targets {2, 3}, budget 4 – a tight yes-instance (both targets need the whole chain through 1).

                                    Equations
                                    Instances For
                                      Dependency graph

                                      The packaged instance is a concrete yes-instance: crawl everything.

                                      Dependency graph

                                      As in the CQ tutorial, the encoder can be run: the #guards evaluate the encoded relations of the worked instance against the hand computation.

                                      The well-formedness sentence, its meaning, and the decoder.

                                      Well-formedness of a website graph: exactly one root page. What makes an honest decoder possible.

                                      Equations
                                      • One or more equations did not get rendered due to their size.
                                      Instances For
                                        Dependency graph
                                        Dependency graph
                                        Dependency graph
                                        Dependency graph

                                        Decode a presented website whose unique root has been found: read the links, targets and budget off the tables, the budget clamped to the page count as the packaging requires. (The root's existence is what makes the page count positive.)

                                        Equations
                                        • One or more equations did not get rendered due to their size.
                                        Instances For
                                          Dependency graph

                                          The decoder: none unless the site has exactly one root.

                                          Equations
                                          • One or more equations did not get rendered due to their size.
                                          Instances For
                                            Dependency graph
                                            Dependency graph
                                            Dependency graph

                                            The computable decoding of well-formed website graphs. Together with crawlEncoding_faithful it closes the loop between the concrete and the abstract problem – a decoder that exists only because well-formedness removed the multi-root structures.

                                            Equations
                                            Instances For
                                              Dependency graph

                                              The worked instance of step 1, presented as raw tables.

                                              Equations
                                              • One or more equations did not get rendered due to their size.
                                              Instances For
                                                Dependency graph

                                                Step 7: membership in NP #

                                                NP is defined as Σ₁ second-order definability, so membership means exhibiting a second-order sentence: guess an object-level certificate, check it with a first-order kernel. The certificate is the one of DescriptiveComplexity.crawlOn_iff_certificate: the crawled set, its root, the order witnessing reachability, and the injection witnessing the budget – four relation variables, nine first-order clauses. The construction mirrors the Steiner-tree kernel (DescriptiveComplexity.Problems.Steiner.Membership), with three differences worth spotting: the step clause walks into each crawled page along a directed edge, the guessed root must exist and carry the vocabulary's root mark, and the budget injection is total on the whole crawled set, since the paper's cost counts every crawled page.

                                                The four relation variables guessed by the Σ₁ definition of Graph Crawling.

                                                • set : CrawlGuess

                                                  The crawled set of pages.

                                                • root : CrawlGuess

                                                  The root the crawl starts from.

                                                • order : CrawlGuess

                                                  The order certifying reachability from the root.

                                                • inj : CrawlGuess

                                                  The injection witnessing the budget.

                                                Instances For
                                                  Dependency graph
                                                  Dependency graph
                                                  @[instance_reducible]
                                                  Equations
                                                  • One or more equations did not get rendered due to their size.
                                                  Dependency graph

                                                  The single existential block of the Σ₁ definition of Graph Crawling.

                                                  Equations
                                                  • One or more equations did not get rendered due to their size.
                                                  Instances For
                                                    Dependency graph
                                                    Dependency graph
                                                    Dependency graph
                                                    Dependency graph
                                                    Dependency graph
                                                    Dependency graph
                                                    @[reducible, inline]

                                                    The edge symbol in the kernel's vocabulary.

                                                    Equations
                                                    Instances For
                                                      Dependency graph
                                                      @[reducible, inline]

                                                      The root-mark symbol in the kernel's vocabulary.

                                                      Equations
                                                      Instances For
                                                        Dependency graph
                                                        @[reducible, inline]

                                                        The target symbol in the kernel's vocabulary.

                                                        Equations
                                                        Instances For
                                                          Dependency graph
                                                          @[reducible, inline]

                                                          The budget-mark symbol in the kernel's vocabulary.

                                                          Equations
                                                          Instances For
                                                            Dependency graph
                                                            @[reducible, inline]

                                                            The crawled-set symbol in the kernel's vocabulary.

                                                            Equations
                                                            Instances For
                                                              Dependency graph
                                                              @[reducible, inline]

                                                              The root symbol in the kernel's vocabulary.

                                                              Equations
                                                              Instances For
                                                                Dependency graph
                                                                @[reducible, inline]

                                                                The order symbol in the kernel's vocabulary.

                                                                Equations
                                                                Instances For
                                                                  Dependency graph
                                                                  @[reducible, inline]

                                                                  The injection symbol in the kernel's vocabulary.

                                                                  Equations
                                                                  Instances For
                                                                    Dependency graph

                                                                    The clauses #

                                                                    The first-order kernel of the Σ₁ definition of Graph Crawling.

                                                                    Equations
                                                                    • One or more equations did not get rendered due to their size.
                                                                    Instances For
                                                                      Dependency graph

                                                                      Realization #

                                                                      Graph Crawling is Σ₁-definable: guess the crawled set, its root, an order certifying that everything crawled is reachable from the root, and an injection of the crawled set into the marked set, then check the nine conditions first-order.

                                                                      Dependency graph

                                                                      Step 8: NP-hardness, by reduction from Set Cover #

                                                                      The hardness half follows the paper's proof: a set-cover instance becomes a depth-2 website – a root linking to one page per set of the family, each set page linking to the elements it contains – whose targets are the elements, and a cover of at most B sets is exactly a crawl of at most |U| + B + 1 pages (the root, the chosen sets, and all the elements).

                                                                      The budget |U| + B + 1 is assembled per tag: the marked set of the produced instance is the elements (on the element tag, |U|), the marked elements of the source (on the set tag, B), and one copy of the minimum of the input's order (on the root tag, 1). The + 1 is why this is an ordered reduction: a marked set with exactly one more element needs a canonical singleton, which only an order provides. The root mark and the root's out-edges are guarded by minimality too, so the junk copies of the root tag are unmarked and edgeless.

                                                                      Cardinality bookkeeping is by tag slices: a set of interpreted elements that is a per-tag family of subsets of the input has as cardinality the sum of the slices (DescriptiveComplexity.ncard_tagged_eq_sum), and both the crawl produced from a cover and the marked set decompose this way, so both directions of the correctness proof reduce to arithmetic on three slice sizes.

                                                                      Tags for the interpretation of website graphs in set systems.

                                                                      • root : CrawlTag

                                                                        (root, a): a copy of the crawl root (only the copy of the minimum is marked as root, linked, and counted).

                                                                      • fam : CrawlTag

                                                                        (fam, a): the page of the set a of the family.

                                                                      • elem : CrawlTag

                                                                        (elem, a): the page of the ground element a – a target.

                                                                      Instances For
                                                                        Dependency graph
                                                                        Dependency graph
                                                                        Dependency graph
                                                                        @[instance_reducible]
                                                                        Equations
                                                                        • One or more equations did not get rendered due to their size.
                                                                        Dependency graph
                                                                        @[reducible, inline]

                                                                        The ground-element symbol over the ordered expansion of set systems.

                                                                        Equations
                                                                        Instances For
                                                                          Dependency graph
                                                                          @[reducible, inline]

                                                                          The family symbol over the ordered expansion of set systems.

                                                                          Equations
                                                                          Instances For
                                                                            Dependency graph
                                                                            @[reducible, inline]

                                                                            The incidence symbol over the ordered expansion of set systems.

                                                                            Equations
                                                                            Instances For
                                                                              Dependency graph
                                                                              @[reducible, inline]

                                                                              The mark symbol over the ordered expansion of set systems.

                                                                              Equations
                                                                              Instances For
                                                                                Dependency graph

                                                                                The interpretation producing, from a set system, the depth-2 website of the paper's reduction: the minimum's root copy links to every set of the family, each set links to its elements, the elements are the targets, and the marked set carries |U| + B + 1.

                                                                                Equations
                                                                                • One or more equations did not get rendered due to their size.
                                                                                Instances For
                                                                                  Dependency graph
                                                                                  @[simp]
                                                                                  theorem DescriptiveComplexity.crawl_edge_iff {A : Type} [FirstOrder.Language.setSystem.Structure A] [LinearOrder A] (t t' : CrawlTag) (w w' : Fin 1A) :
                                                                                  WSEdge (t, w) (t', w') t = CrawlTag.root t' = CrawlTag.fam (∀ (a : A), w 0 a) SSFam (w' 0) t = CrawlTag.fam t' = CrawlTag.elem (SSMem (w' 0) (w 0) SSFam (w 0)) SSElem (w' 0)
                                                                                  Dependency graph
                                                                                  Dependency graph
                                                                                  Dependency graph
                                                                                  @[simp]
                                                                                  theorem DescriptiveComplexity.crawl_marked_iff {A : Type} [FirstOrder.Language.setSystem.Structure A] [LinearOrder A] (t : CrawlTag) (w : Fin 1A) :
                                                                                  WSMarked (t, w) match t with | CrawlTag.root => ∀ (a : A), w 0 a | CrawlTag.fam => SSMarked (w 0) | CrawlTag.elem => SSElem (w 0)
                                                                                  Dependency graph

                                                                                  Counting by tag slices #

                                                                                  def DescriptiveComplexity.InSlices {A : Type} (s : CrawlTagSet A) (p : CrawlTag × (Fin 1A)) :

                                                                                  Membership in a per-tag family of subsets of the input, stated at the raw product type so that it applies to interpreted elements.

                                                                                  Equations
                                                                                  Instances For
                                                                                    Dependency graph

                                                                                    The cardinality of a per-tag family of slices is the sum of the slice sizes.

                                                                                    Dependency graph

                                                                                    The tag slices of the crawl produced from a subfamily G: the minimum on the root tag, G on the set tag, the ground elements on the element tag. Instantiated at G := SSMarked this is also the decomposition of the marked set.

                                                                                    Equations
                                                                                    Instances For
                                                                                      Dependency graph
                                                                                      theorem DescriptiveComplexity.ncard_min_slice {A : Type} [LinearOrder A] [Finite A] [Nonempty A] :
                                                                                      {a : A | ∀ (b : A), a b}.ncard = 1

                                                                                      On a finite linearly ordered nonempty type, the set of minima is a singleton.

                                                                                      Dependency graph

                                                                                      The marked set of the interpreted website decomposes into tag slices.

                                                                                      Dependency graph

                                                                                      Correctness #

                                                                                      Correctness of the interpretation: the set system has a small cover iff the interpreted website has a cheap crawl.

                                                                                      Dependency graph

                                                                                      Set Cover ordered-FO-reduces to Graph Crawling – the reduction of Gauquier–Manolescu–Senellart 2026, Prop. 4: a cover of at most B sets is a crawl of at most |U| + B + 1 pages of the depth-2 website.

                                                                                      Equations
                                                                                      • One or more equations did not get rendered due to their size.
                                                                                      Instances For
                                                                                        Dependency graph

                                                                                        Step 9: completeness #

                                                                                        Membership and hardness combine into the completeness theorem – the formalized counterpart of Prop. 4 of Gauquier–Manolescu–Senellart 2026. Through the faithfulness theorem of step 6, it is a statement about the packaged concrete instances of step 1: ConcreteCrawlHolds is decided by a problem that is NP-complete, over an encoding that provably neither pads nor compresses.

                                                                                        Dependency graph

                                                                                        Graph Crawling is NP-hard: Set Cover, which is NP-hard, reduces to it by an ordered FO reduction.

                                                                                        Dependency graph
                                                                                        Dependency graph

                                                                                        The image of the hardness reduction is well-formed: the only root-marked page of an interpreted website is the minimum's root copy.

                                                                                        Dependency graph

                                                                                        Well-formed graph crawling is NP-complete: crawling restricted to websites with exactly one root – the instances the decoder of step 6 handles. Both halves are one-line upgrades of the plain completeness proof (OrderedFOReduction.withInvariant, SigmaSODefinable.inf_ofSentence).

                                                                                        Dependency graph