Draft — mutable and not usable as a dependency; its citation marks the draft state.

Lax11.InstanceEncoding

Encoding a graph together with a k-expression

concepts/Lax11/InstanceEncoding.lean · lax-11

definition

Loading review…

Sign in with ORCID

Community review

Flags

Each flag is tied to a public ORCID identity and explains why this concept may be incorrect.

No flags have been submitted.

    Community review

    Flag this concept

    State precisely what appears incorrect. This explanation will be public under your ORCID name.

    No source line selected.

    Concept map

    Proven claimDefinitionThis conceptRelated conceptA → B: B builds on A

    Definition

    An algorithm on graphs of bounded cliquewidth is handed a graph together with a k-expression for it, and this is the word that presents the pair. It has two blocks. The first is the graph itself, in the compressed sparse row form used everywhere in this submission. The second is the k-expression, as a tree: the number of nodes, then one number per node giving that node's parent, then one per node giving the operation performed there, then one per node giving the vertex name it creates. Children are numbered before their parents and the root is the last node.

    Lean source view on GitHub

    1import Lax11.GraphEncoding
    2import Lax11.CliqueExpr
    3
    4/-!
    5---
    6title: Encoding a graph together with a k-expression
    7type: definition
    8---
    9An algorithm on graphs of bounded cliquewidth is handed a graph
    10together with a *k*-expression for it, and this is the word that
    11presents the pair. It has two blocks. The first is the graph itself, in
    12the compressed sparse row form used everywhere in this submission. The
    13second is the *k*-expression, as a tree: the number of nodes, then one
    14number per node giving that node's parent, then one per node giving the
    15operation performed there, then one per node giving the vertex name it
    16creates. Children are numbered before their parents and the root is the
    17last node.
    18
    19# Formalization notes
    20
    21The expression block is a certificate, and it is required to be a
    22correct one: the encoding says that the arrays describe some valid
    23expression that evaluates to exactly the graph in the first block.
    24Since the two blocks describe the same graph, a statement is not
    25weakened by carrying both — the first block is what makes a sentence
    26`Sat G φ` refer to a graph, and the second is what makes the input
    27admissible. The arrays determine the expression completely, the vertex
    28names included, so the existential quantifier over expressions ranges
    29over at most one thing: the certificate is data in the word, not a
    30choice made about it.
    31
    32The vertex-name array is part of the input even though a program
    33evaluating the expression never reads it. Without it the second block
    34would not be a *k*-expression, only the shape of one, and a reader
    35could not check against the first block what the certificate claims.
    36Its presence costs nothing: it is one number per node, so it only
    37lengthens the input, and a linear bound is linear in that length.
    38
    39Children are numbered before their parents, so the root is the last
    40node. That is what lets a machine evaluate the expression in a single
    41left-to-right sweep, with no recursion, no stack and no second pass,
    42and it is where a linear bound comes from. It restricts the *encoding*,
    43not the class of graphs: every rooted tree admits such a numbering —
    44any postorder is one — and one can be produced from an arbitrary
    45numbering by a sort, which this format simply asks the writer of the
    46input to have done. An encoding that accepted arbitrary parent arrays
    47would describe the same graphs at the price of a renumbering pass
    48inside the program.
    49
    50Cells are read with `List.getD`, which returns `0` outside the word,
    51exactly as in the compressed sparse row encoding; the length condition
    52pins the expression block down completely, so the default value is
    53never reached at a position the other conditions constrain.
    54-/
    55
    56namespace Lax11.InstanceEncoding
    57
    58open Lax11.GraphEncoding Lax11.CliqueExpr
    59
    60/-- The number of nodes declared by an expression block: its first
    61entry. -/
    62def nodeCount (t : List ℕ) : ℕ := t.getD 0 0
    63
    64/-- The parent of node `i`: the parents follow the header entry. -/
    65def parent (t : List ℕ) (i : ℕ) : ℕ := t.getD (1 + i) 0
    66
    67/-- The operation performed at node `i`, as a number: the operations
    68follow the parents. -/
    69def opCode (t : List ℕ) (i : ℕ) : ℕ := t.getD (1 + nodeCount t + i) 0
    70
    71/-- The vertex name created at node `i`, meaningful when the operation
    72there creates a vertex: the names follow the operations. -/
    73def vertexName (t : List ℕ) (i : ℕ) : ℕ := t.getD (1 + 2 * nodeCount t + i) 0
    74
    75/-- The children of node `i`: the earlier nodes whose parent is `i`,
    76in increasing order. -/
    77def children (par : ℕ → ℕ) (i : ℕ) : List ℕ :=
    78 (List.range i).filter (fun c => par c == i)
    79
    80/-- The word `t` is an expression block for a tree whose operations are
    81operations of `k`-expressions. The number of nodes is the block's own
    82first entry, so it is read off `t` rather than quantified over. -/
    83structure EncodesExprTree (t : List ℕ) (k : ℕ) : Prop where
    84 /-- There is at least one node: an expression has a root. -/
    85 pos : 1nodeCount t
    86 /-- The block consists of the header entry and three arrays of one
    87 number per node. -/
    88 length_eq : t.length = 1 + 3 * nodeCount t
    89 /-- Every node but the last has a parent, which is a later node — so
    90 children are numbered before their parents and the root is the last
    91 node. -/
    92 parent_gt : ∀ i, i + 1 < nodeCount t → i < parent t i ∧ parent t i < nodeCount t
    93 /-- Every operation entry is the number of an operation. -/
    94 opCode_lt : ∀ i < nodeCount t, opCode t i < opCard k
    95
    96/-- The node `i` of the tree given by the three arrays is the
    97expression `e`: the operation number at `i` is the one of `e`'s
    98outermost operation, the vertex name at `i` is the one `e` creates if
    99`e` is a leaf, and the children of `i` — which are listed in increasing
    100order — are the nodes of `e`'s immediate subexpressions, the left one
    101first. -/
    102def EncodesExpr {n k : ℕ} (par lab ids : ℕ → ℕ) : ℕ → Expr n k → Prop
    103 | i, .leaf v l => children par i = [] ∧ lab i = (Op.leaf l).code ∧ ids i = (v : ℕ)
    104 | i, .union e₁ e₂ => ∃ c₁ c₂, children par i = [c₁, c₂] ∧
    105 lab i = (Op.union : Op k).code
    106 EncodesExpr par lab ids c₁ e₁ ∧ EncodesExpr par lab ids c₂ e₂
    107 | i, .addEdges a b e => ∃ c, children par i = [c] ∧
    108 lab i = (Op.eta a b).codeEncodesExpr par lab ids c e
    109 | i, .relabel a b e => ∃ c, children par i = [c] ∧
    110 lab i = (Op.rho a b).codeEncodesExpr par lab ids c e
    111
    112/-- The word `x` presents the graph `G` on `n` vertices together with a
    113`k`-expression for it: a compressed sparse row block encoding `G`,
    114followed by an expression block whose arrays describe a valid
    115`k`-expression, rooted at its last node, that evaluates to `G`. This is
    116the instance format of a model checking problem on graphs of bounded
    117cliquewidth. -/
    118def EncodesModelCheckingInstance (x : List ℕ) (n : ℕ) (G : SimpleGraph (Fin n))
    119 (k : ℕ) : Prop :=
    120 ∃ (g t : List ℕ) (e : Expr n k),
    121 x = g ++ t ∧ EncodesGraph g n G ∧ EncodesExprTree t k ∧
    122 EncodesExpr (parent t) (opCode t) (vertexName t) (nodeCount t - 1) e ∧ ValidFor e G
    123
    124end Lax11.InstanceEncoding
    125

    Formalization notes

    The expression block is a certificate, and it is required to be a correct one: the encoding says that the arrays describe some valid expression that evaluates to exactly the graph in the first block. Since the two blocks describe the same graph, a statement is not weakened by carrying both — the first block is what makes a sentence SatGφSat G φ refer to a graph, and the second is what makes the input admissible. The arrays determine the expression completely, the vertex names included, so the existential quantifier over expressions ranges over at most one thing: the certificate is data in the word, not a choice made about it.

    The vertex-name array is part of the input even though a program evaluating the expression never reads it. Without it the second block would not be a k-expression, only the shape of one, and a reader could not check against the first block what the certificate claims. Its presence costs nothing: it is one number per node, so it only lengthens the input, and a linear bound is linear in that length.

    Children are numbered before their parents, so the root is the last node. That is what lets a machine evaluate the expression in a single left-to-right sweep, with no recursion, no stack and no second pass, and it is where a linear bound comes from. It restricts the encoding, not the class of graphs: every rooted tree admits such a numbering — any postorder is one — and one can be produced from an arbitrary numbering by a sort, which this format simply asks the writer of the input to have done. An encoding that accepted arbitrary parent arrays would describe the same graphs at the price of a renumbering pass inside the program.

    Cells are read with List.getDList.getD, which returns 00 outside the word, exactly as in the compressed sparse row encoding; the length condition pins the expression block down completely, so the default value is never reached at a position the other conditions constrain.

    From Mathlib

    none

    Community review

    Discussion

    Ask a question or add context. Endorsements and structured flags are kept in the review panel above; your ORCID profile must share a public name.

    0 comments

    Loading discussion…