Documentation

Complexity.Algorithms.Lean.Queue

A modular queue implemented with two stacks #

The behavior proof mentions no concrete stack representation or resource model. The front stack stores the next elements to dequeue; the reversed rear stack stores newly enqueued elements. When the front is empty, the implementation queries the rear size and transfers those elements. This standard construction follows Cormen et al., Exercise 10.1-6; the potential method is described in Chapter 17.

Main definitions #

Main results #

For a primitive weight bound K, a client performing m queue operations satisfies weight + 2 K rearFinal.length ≤ 3 K m + 2 K rearInitial.length. This is a conditional bound on backend traces, not a machine instruction-count theorem. Pure client computation is uncharged; backend implementations must justify their primitive weights and state independence separately.

References #

Stack operations with typed answers.

Instances For
    def Cslib.Algorithms.Lean.Queue.instDecidableEqStackOp.decEq {α✝ : Type} [DecidableEq α✝] (x✝ x✝¹ : StackOp α✝) :
    Decidable (x✝ = x✝¹)
    Instances For
      @[instance_reducible]
      @[reducible, inline]

      A total stack specification; popping an empty stack returns none.

      Instances For
        @[reducible, inline]

        Two independently addressable stacks.

        Instances For

          FIFO queue operations with typed answers.

          Instances For
            @[instance_reducible]
            def Cslib.Algorithms.Lean.Queue.instDecidableEqQueueOp.decEq {α✝ : Type} [DecidableEq α✝] (x✝ x✝¹ : QueueOp α✝) :
            Decidable (x✝ = x✝¹)
            Instances For
              @[reducible, inline]

              A total FIFO queue specification.

              Instances For

                Move at most n items from the rear stack to the front stack. The fuel is obtained through an explicit size call, rather than inspecting hidden state.

                Instances For

                  The same queue methods work for every realization of the stack interface.

                  Instances For

                    Primitive-operation trace of transferring the rear contents to the front.

                    Instances For
                      theorem Cslib.Algorithms.Lean.Queue.transfer_run {α : Type} (front back : List α) :
                      (stackPair α).runClient (front, back) (transfer back.length) = ((), (back.reverse ++ front, []), transferTrace back)

                      The queue's sole traversal argument: abstract stack calls reverse the rear contents.

                      Representation and behavior are proved once, before selecting a backend or cost model.

                      Instances For

                        Each transferred element incurs one pop and one push.

                        The queue has a three-call amortized bound; rear-stack credit remains private to the module. This counts stack calls, not execution of pure continuations or machine instructions.

                        theorem Cslib.Algorithms.Lean.Queue.realized_client {α C Trace β : Type} {exec : Stateful.Execution (stackPair α) C Trace} (R : Stateful.Realization (stackPair α) exec) (weight : Trace → ℕ) (K : ℕ) (B : Stateful.Bound R weight fun (x : (stackPair α).State) (x_1 : (stackPair α).Op) => K) (p : (queue α).Client β) {q : List α} {s : (stackPair α).State} {c : C} (hrep : implementation.rep q s) (hbackend : R.rep s c) :
                        ∃ (c' : C) (traces : List Trace) (s' : (stackPair α).State), Stateful.Executes exec (Stateful.link methods p) c ((queue α).runClient q p).1 c' traces ∧ implementation.rep ((queue α).runClient q p).2.1 s' ∧ R.rep s' c' ∧ Stateful.total weight traces + K * (2 * List.length s'.2) ≤ ((queue α).runClient q p).2.2.length * (3 * K) + K * (2 * List.length s.2)

                        Uniform primitive bounds can be chosen after proving queue correctness. The same theorem applies to any additive measure on any backend's native traces. It also retains leftover credit.

                        theorem Cslib.Algorithms.Lean.Queue.realized_client_bound {α C Trace β : Type} {exec : Stateful.Execution (stackPair α) C Trace} (R : Stateful.Realization (stackPair α) exec) (weight : Trace → ℕ) (K : ℕ) (B : Stateful.Bound R weight fun (x : (stackPair α).State) (x_1 : (stackPair α).Op) => K) (p : (queue α).Client β) {q : List α} {s : (stackPair α).State} {c c' : C} {a : β} {traces : List Trace} (hrep : implementation.rep q s) (hbackend : R.rep s c) (he : Stateful.Executes exec (Stateful.link methods p) c a c' traces) :
                        a = ((queue α).runClient q p).1 ∧ ∃ (s' : (stackPair α).State), implementation.rep ((queue α).runClient q p).2.1 s' ∧ R.rep s' c' ∧ Stateful.total weight traces + K * (2 * List.length s'.2) ≤ ((queue α).runClient q p).2.2.length * (3 * K) + K * (2 * List.length s.2)

                        Correctness and the same resource bound hold for every supplied flattened execution.