Documentation

DescriptiveComplexity.Numbers.BinRel

Binary numbers carried by a relation #

The layer between DescriptiveComplexity.Numbers.Binary, which decodes a set of bits sitting on a genuine LinearOrder, and the problems carrying binary numbers, whose order is a relation symbol of the vocabulary and therefore an arbitrary binary relation until the yes-instances say otherwise.

Everything transports along equivalences commuting with the relations, which is what the DecisionProblem.iso_invariant proofs of the group need.

The arithmetic the Σ₁ definitions need – that a bitwise ripple-carry chain computes an addition – is built on DescriptiveComplexity.binNum_peel_min, which peels the lowest position off a decoded number: binNum = bit at the bottom + 2 * (the rest), the recursion binary numbers actually satisfy. The same recursion gives the two facts a kernel needs about whole numbers rather than their bits: DescriptiveComplexity.binNum_inj_on, two numbers are equal exactly when their bits agree, and DescriptiveComplexity.binNum_lt_iff, one is smaller exactly when they differ and the higher bit is the second's – both bitwise, hence first-order, which is why a kernel can compare numbers it has guessed.

Linear orders, as a property of a relation #

def DescriptiveComplexity.IsLinOrd {A : Type} (Le : AAProp) :

A binary relation is a linear order: reflexive, transitive, antisymmetric and total.

Equations
Instances For
    Dependency graph
    theorem DescriptiveComplexity.IsLinOrd.of_equiv {A B : Type} (u : B A) {LeB : BBProp} {LeA : AAProp} (hle : ∀ (b b' : B), LeB b b' LeA (u b) (u b')) (h : IsLinOrd LeB) :

    Linearity transports along an equivalence.

    Dependency graph

    Building linear orders #

    Reductions into a problem carrying binary numbers have to construct the order of the instance they produce, and a Σ₁ certificate sometimes has to exhibit one. Both do it the same way: read the elements through a key into a lexicographic product of orders already at hand.

    def DescriptiveComplexity.lexRel {α β : Type} (Ra : ααProp) (Rb : ββProp) :
    α × βα × βProp

    The lexicographic product of two relations.

    Equations
    Instances For
      Dependency graph
      theorem DescriptiveComplexity.isLinOrd_lexRel {α β : Type} {Ra : ααProp} {Rb : ββProp} (ha : IsLinOrd Ra) (hb : IsLinOrd Rb) :

      The lexicographic product of two linear orders is a linear order.

      Dependency graph
      theorem DescriptiveComplexity.isLinOrd_of_key {M K : Type} {LeK : KKProp} {R : MMProp} (hK : IsLinOrd LeK) (key : MK) (hinj : Function.Injective key) (h : ∀ (a b : M), R a b LeK (key a) (key b)) :

      A relation read through an injective key into a linear order is a linear order.

      Dependency graph
      @[instance_reducible]
      noncomputable def DescriptiveComplexity.IsLinOrd.toLinearOrder {A : Type} {Le : AAProp} (h : IsLinOrd Le) :

      A relation that is a linear order induces a LinearOrder structure, which is what Mathlib's order library asks for. Guessed orders – a schedule, a circuit – arrive as relations, so this is the bridge to it.

      Equations
      • One or more equations did not get rendered due to their size.
      Instances For
        Dependency graph
        theorem DescriptiveComplexity.isLinOrd_le {α : Type} [LinearOrder α] :
        IsLinOrd fun (x1 x2 : α) => x1 x2

        The natural order of a linear order, as a relation.

        Dependency graph

        Decoding a set of positions #

        noncomputable def DescriptiveComplexity.bitRank {A : Type} (Le : AAProp) (Posn : AProp) (p : A) :

        The rank of a position: the number of positions strictly below it. This is the place value's exponent.

        Equations
        Instances For
          Dependency graph
          noncomputable def DescriptiveComplexity.binNum {A : Type} (Le : AAProp) (Posn b : AProp) :

          The number encoded by the set b of positions: ∑ 2 ^ rank.

          Equations
          Instances For
            Dependency graph
            theorem DescriptiveComplexity.binNum_congr {A : Type} {Le : AAProp} {Posn b b' : AProp} (h : ∀ (p : A), b p b' p) :
            binNum Le Posn b = binNum Le Posn b'
            Dependency graph
            theorem DescriptiveComplexity.binNum_congr_on {A : Type} {Le : AAProp} {Posn b b' : AProp} (h : ∀ (p : A), Posn p → (b p b' p)) :
            binNum Le Posn b = binNum Le Posn b'

            Only the bits at positions matter.

            Dependency graph
            @[simp]
            theorem DescriptiveComplexity.binNum_bot {A : Type} (Le : AAProp) (Posn : AProp) :
            (binNum Le Posn fun (x : A) => False) = 0

            The value of the empty set of positions is zero.

            Dependency graph
            theorem DescriptiveComplexity.bitRank_equiv {A B : Type} (u : B A) {LeB : BBProp} {PosnB : BProp} {LeA : AAProp} {PosnA : AProp} (hle : ∀ (b b' : B), LeB b b' LeA (u b) (u b')) (hp : ∀ (b : B), PosnB b PosnA (u b)) (p : B) :
            bitRank LeB PosnB p = bitRank LeA PosnA (u p)

            The rank of a position transports along an equivalence commuting with the two relations.

            Dependency graph
            theorem DescriptiveComplexity.binNum_equiv {A B : Type} (u : B A) {LeB : BBProp} {PosnB bB : BProp} {LeA : AAProp} {PosnA bA : AProp} (hle : ∀ (b b' : B), LeB b b' LeA (u b) (u b')) (hp : ∀ (b : B), PosnB b PosnA (u b)) (hb : ∀ (b : B), bB b bA (u b)) :
            binNum LeB PosnB bB = binNum LeA PosnA bA

            The decoded number transports along an equivalence commuting with the three relations.

            Dependency graph

            Peeling the lowest position #

            theorem DescriptiveComplexity.bitRank_erase_min {A : Type} [Finite A] {Le : AAProp} {Posn : AProp} {p₀ : A} (h₀ : Posn p₀) (hmin : ∀ (q : A), Posn qLe p₀ q) {p : A} (hp : Posn p) (hne : p p₀) :
            bitRank Le Posn p = bitRank Le (fun (q : A) => Posn q q p₀) p + 1

            Removing the lowest position lowers every other rank by one.

            Dependency graph
            theorem DescriptiveComplexity.binNum_peel_min {A : Type} [Finite A] {Le : AAProp} {Posn b : AProp} {p₀ : A} (hlin : IsLinOrd Le) (h₀ : Posn p₀) (hmin : ∀ (q : A), Posn qLe p₀ q) :
            binNum Le Posn b = (if b p₀ then 1 else 0) + 2 * binNum Le (fun (q : A) => Posn q q p₀) b

            The recursion binary numbers satisfy: the value is the lowest bit plus twice the value of the rest.

            Dependency graph

            The full adder #

            The majority of three propositions: the carry produced by a full adder.

            Equations
            Instances For
              Dependency graph
              theorem DescriptiveComplexity.fullAdder (x y z : Prop) :
              ((if Xor x (Xor y z) then 1 else 0) + 2 * if maj x y z then 1 else 0) = (if x then 1 else 0) + ((if y then 1 else 0) + if z then 1 else 0)

              The full-adder identity: the sum bit plus twice the carry is the sum of the three input bits.

              Dependency graph

              Ripple-carry addition #

              def DescriptiveComplexity.MinPos {A : Type} (Le : AAProp) (Posn : AProp) (p : A) :

              p is a lowest position.

              Equations
              Instances For
                Dependency graph
                def DescriptiveComplexity.MaxPos {A : Type} (Le : AAProp) (Posn : AProp) (p : A) :

                p is a highest position.

                Equations
                Instances For
                  Dependency graph
                  def DescriptiveComplexity.SuccPos {A : Type} (Le : AAProp) (Posn : AProp) (p q : A) :

                  q is the next position above p.

                  Equations
                  Instances For
                    Dependency graph
                    theorem DescriptiveComplexity.exists_minPos {A : Type} [Finite A] {Le : AAProp} {Posn : AProp} (hlin : IsLinOrd Le) (hne : ∃ (p : A), Posn p) :
                    ∃ (p : A), MinPos Le Posn p

                    A nonempty set of positions has a lowest one: minimize the rank.

                    Dependency graph
                    theorem DescriptiveComplexity.bitRank_lt {A : Type} [Finite A] {Le : AAProp} {Posn : AProp} (hlin : IsLinOrd Le) {p q : A} (hp : Posn p) (hle : Le p q) (hne : p q) :
                    bitRank Le Posn p < bitRank Le Posn q

                    Rank is strictly monotone: a lower position has a smaller rank.

                    Dependency graph
                    theorem DescriptiveComplexity.succPos_left_unique {A : Type} {Le : AAProp} {Posn : AProp} (hlin : IsLinOrd Le) {p p' q : A} (h : SuccPos Le Posn p q) (h' : SuccPos Le Posn p' q) :
                    p = p'

                    The element immediately below a given one is unique.

                    Dependency graph
                    theorem DescriptiveComplexity.IsLinOrd.reverse {A : Type} {Le : AAProp} (hlin : IsLinOrd Le) :
                    IsLinOrd fun (a b : A) => Le b a

                    The reverse of a linear order is a linear order.

                    Dependency graph
                    theorem DescriptiveComplexity.exists_maxPos {A : Type} [Finite A] {Le : AAProp} {Posn : AProp} (hlin : IsLinOrd Le) (hne : ∃ (p : A), Posn p) :
                    ∃ (p : A), MaxPos Le Posn p

                    A nonempty set of positions has a highest one.

                    Dependency graph
                    theorem DescriptiveComplexity.exists_predPos {A : Type} [Finite A] {Le : AAProp} {Posn : AProp} (hlin : IsLinOrd Le) {p : A} (hp : Posn p) (hmin : ¬MinPos Le Posn p) :
                    ∃ (q : A), SuccPos Le Posn q p

                    Every position that is not the lowest has one immediately below it.

                    Dependency graph
                    theorem DescriptiveComplexity.binNum_ripple {A : Type} [Finite A] {Le : AAProp} (hlin : IsLinOrd Le) {a b s : AProp} (n : ) (Posn c : AProp) (cin cout : Prop) :
                    {p : A | Posn p}.ncard = n(∀ (p : A), Posn p → (s p Xor (a p) (Xor (b p) (c p))))(∀ (p q : A), SuccPos Le Posn p q → (c q maj (a p) (b p) (c p)))(∀ (p : A), MinPos Le Posn p → (c p cin))(∀ (p : A), MaxPos Le Posn p → (cout maj (a p) (b p) (c p)))((∀ (p : A), ¬Posn p) → (cout cin)) → (binNum Le Posn s + 2 ^ n * if cout then 1 else 0) = binNum Le Posn a + binNum Le Posn b + if cin then 1 else 0

                    Ripple-carry addition is addition. If s is the bitwise sum of a and b with carries c – each bit the exclusive or of the three, each carry the majority of the three below – then the decoded numbers add up, the carry in at the bottom and the carry out at the top accounting for the difference.

                    Dependency graph
                    theorem DescriptiveComplexity.binNum_lt_two_pow {A : Type} [Finite A] {Le : AAProp} (hlin : IsLinOrd Le) (n : ) (Posn : AProp) :
                    {p : A | Posn p}.ncard = n∀ (b : AProp), binNum Le Posn b < 2 ^ n

                    A decoded number is smaller than 2 to the number of positions.

                    Dependency graph
                    theorem DescriptiveComplexity.exists_ripple {A : Type} [Finite A] {Le : AAProp} (hlin : IsLinOrd Le) (n : ) (Posn a b : AProp) (cin : Prop) :
                    {p : A | Posn p}.ncard = n(binNum Le Posn a + binNum Le Posn b + if cin then 1 else 0) < 2 ^ n∃ (s : AProp) (c : AProp), (∀ (p : A), Posn p → (s p Xor (a p) (Xor (b p) (c p)))) (∀ (p q : A), SuccPos Le Posn p q → (c q maj (a p) (b p) (c p))) (∀ (p : A), MinPos Le Posn p → (c p cin)) (∀ (p : A), MaxPos Le Posn p¬maj (a p) (b p) (c p)) binNum Le Posn s = binNum Le Posn a + binNum Le Posn b + if cin then 1 else 0

                    A ripple-carry certificate exists. Whenever the sum fits in the available positions, the bitwise sum and the carries that witness it can be produced – this is the certificate that the Σ₁ definition of a binary-weighted problem guesses.

                    Dependency graph
                    theorem DescriptiveComplexity.exists_binNum {A : Type} [Finite A] {Le : AAProp} (hlin : IsLinOrd Le) (n : ) (Posn : AProp) :
                    {p : A | Posn p}.ncard = nk < 2 ^ n, ∃ (b : AProp), binNum Le Posn b = k

                    Every number that fits can be written: a value below 2 to the number of positions is decoded from some set of bits.

                    Dependency graph
                    theorem DescriptiveComplexity.binNum_inj_on {A : Type} [Finite A] {Le : AAProp} (hlin : IsLinOrd Le) (n : ) (Posn : AProp) :
                    {p : A | Posn p}.ncard = n∀ (b b' : AProp), binNum Le Posn b = binNum Le Posn b'∀ (p : A), Posn p → (b p b' p)

                    The decoding is injective on the positions: two sets of bits with the same value agree wherever it matters.

                    Dependency graph
                    theorem DescriptiveComplexity.binNum_lt_iff {A : Type} [Finite A] {Le : AAProp} (hlin : IsLinOrd Le) (n : ) (Posn : AProp) :
                    {p : A | Posn p}.ncard = n∀ (b b' : AProp), binNum Le Posn b < binNum Le Posn b' ∃ (p : A), Posn p ¬b p b' p ∀ (q : A), Posn qLe p qq p → (b q b' q)

                    Comparison by the highest differing position: one decoded number is smaller than another exactly when there is a position carrying 0 in the first and 1 in the second above which the two agree. Unlike the value itself, this is a first-order reading of <, which is what a kernel comparing two guessed numbers writes.

                    Dependency graph