Documentation

EconCSLib.Algorithm.Online

EconCSLib.Algorithm.Online #

Online algorithms as deterministic state machines.

Design #

An online algorithm processes a stream of requests one at a time. The characteristic constraint — no visibility of the future — is encoded structurally: each step depends only on the current state and the current request. The state summarises whatever the algorithm needs to know about the past; future requests are inaccessible because there is no syntactic hook to refer to them.

This is orthogonal to cost accounting (Foundation.CostM): online is about the information available to each decision, CostM is about the resource consumed. The two can be composed but neither requires the other.

Main definitions #

Design: the no-input step #

The transition step : StateOption InputState × Option Output receives some r for a genuine request and none for end of input. The none case lets the algorithm act when the stream is exhausted — a secretary forced to hire the last candidate, an auction posting a final clearance — rather than silently doing nothing. Both shapes of online problem are supported; only the driver differs.

run returns a pair: (run …).1 is the terminal state (after the end-of-input step) and (run …).2 is the decision. Compositional facts about splitting a request stream — needed e.g. to isolate one bidder — are proved per instance from run_cons_some / run_cons_none; for the single-item auction the end-of-input step preserves the state, which keeps those splitting lemmas clean.

References #

structure Online.OnlineAlgorithm (Input : Type u_1) (State : Type u_2) (Output : Type u_3) :
Type (max (max u_1 u_2) u_3)

A deterministic online algorithm as a state machine.

The state State summarises the relevant past; step consumes the current state and the current input to produce the next state together with an optional output — without ever seeing any future input. The input is Option Input: some r is a genuine request, none signals end of input, the algorithm's chance to act when the stream is exhausted. A step that emits some o halts the run with result o; a step that emits none defers, recording what it learned into the next state.

  • init : State

    Initial state, before any input is processed.

  • step : StateOption InputState × Option Output

    One-step transition. Depends only on the current state and the current input — by construction, the future is invisible. The input is some r for a request and none for end of input. Emitting some o halts the run; none defers.

Instances For
    def Online.OnlineAlgorithm.run {α : Type u_1} {σ : Type u_2} {β : Type u_3} (alg : OnlineAlgorithm α σ β) :
    σList ασ × Option β

    Drive the machine across the requests, halting at the first step that emits an output. When the genuine requests are exhausted without a commitment, the machine is given the end-of-input step step _ none — its last chance to decide, since it never knew which request was last — and its (state, output) pair is the result. So (run s rs).1 is the terminal state and (run s rs).2 is the decision.

    Equations
    Instances For
      @[simp]
      theorem Online.OnlineAlgorithm.run_nil {α : Type u_1} {σ : Type u_2} {β : Type u_3} (alg : OnlineAlgorithm α σ β) (s : σ) :
      alg.run s [] = alg.step s none

      On no requests, run is exactly the end-of-input step.

      theorem Online.OnlineAlgorithm.run_cons {α : Type u_1} {σ : Type u_2} {β : Type u_3} (alg : OnlineAlgorithm α σ β) (s : σ) (r : α) (rs : List α) :
      alg.run s (r :: rs) = match alg.step s (some r) with | (s', some o) => (s', some o) | (s', none) => alg.run s' rs
      @[simp]
      theorem Online.OnlineAlgorithm.run_cons_some {α : Type u_1} {σ : Type u_2} {β : Type u_3} (alg : OnlineAlgorithm α σ β) (s s' : σ) (o : β) (r : α) (rs : List α) (h : alg.step s (some r) = (s', some o)) :
      alg.run s (r :: rs) = (s', some o)

      If the step on r halts with output o, the run halts there.

      @[simp]
      theorem Online.OnlineAlgorithm.run_cons_none {α : Type u_1} {σ : Type u_2} {β : Type u_3} (alg : OnlineAlgorithm α σ β) (s s' : σ) (r : α) (rs : List α) (h : alg.step s (some r) = (s', none)) :
      alg.run s (r :: rs) = alg.run s' rs

      If the step on r defers (none), the run continues on rs.

      @[reducible, inline]
      abbrev Online.OnlineAlgorithm.runResult {α : Type u_1} {σ : Type u_2} {β : Type u_3} (alg : OnlineAlgorithm α σ β) (s : σ) (rs : List α) :

      The decision run commits to — the second component of run.

      Equations
      Instances For
        @[reducible, inline]
        abbrev Online.OnlineAlgorithm.runStatus {α : Type u_1} {σ : Type u_2} {β : Type u_3} (alg : OnlineAlgorithm α σ β) (s : σ) (rs : List α) :
        σ

        The terminal status (state) run halts in — the first component of run, after the end-of-input step.

        Equations
        Instances For

          Streaming #

          runAll never halts: it gathers every emitted output in arrival order, including a possible final output from the end-of-input step. The driver for streaming problems — scheduling, matching, paging.

          def Online.OnlineAlgorithm.runAll {α : Type u_1} {σ : Type u_2} {β : Type u_3} (alg : OnlineAlgorithm α σ β) :
          σList αList β

          Collect every emitted output across the requests in order, plus a final output from the end-of-input step if it emits one.

          Equations
          Instances For
            theorem Online.OnlineAlgorithm.runAll_cons {α : Type u_1} {σ : Type u_2} {β : Type u_3} (alg : OnlineAlgorithm α σ β) (s : σ) (r : α) (rs : List α) :
            alg.runAll s (r :: rs) = match alg.step s (some r) with | (s', some o) => o :: alg.runAll s' rs | (s', none) => alg.runAll s' rs
            @[simp]
            theorem Online.OnlineAlgorithm.runAll_cons_some {α : Type u_1} {σ : Type u_2} {β : Type u_3} (alg : OnlineAlgorithm α σ β) (s s' : σ) (o : β) (r : α) (rs : List α) (h : alg.step s (some r) = (s', some o)) :
            alg.runAll s (r :: rs) = o :: alg.runAll s' rs

            If the step on r emits o, runAll records it and recurses.

            @[simp]
            theorem Online.OnlineAlgorithm.runAll_cons_none {α : Type u_1} {σ : Type u_2} {β : Type u_3} (alg : OnlineAlgorithm α σ β) (s s' : σ) (r : α) (rs : List α) (h : alg.step s (some r) = (s', none)) :
            alg.runAll s (r :: rs) = alg.runAll s' rs

            If the step on r emits nothing, runAll recurses unchanged.

            Competitive ratio #

            For each request sequence the algorithm produces a numerical value of interest (welfare, throughput, cost, …). The offline optimum opt is the best value achievable with full hindsight. The algorithm is c-competitive if it stays within a factor c of opt, in either the maximisation or minimisation direction.

            The definitions are deliberately abstract: the caller supplies both value (typically objalg.run alg.init) and opt (the offline benchmark for the problem at hand). The competitive ratio itself lives in any ordered multiplicative structure F.

            def Online.IsCompetitiveMax {α : Type u_1} {F : Type u_2} [Mul F] [LE F] (value opt : List αF) (c : F) :

            c-competitive for a maximisation objective: the algorithm's value on every request sequence is at least c · opt.

            Equations
            Instances For
              def Online.IsCompetitiveMin {α : Type u_1} {F : Type u_2} [Mul F] [LE F] (value opt : List αF) (c : F) :

              c-competitive for a minimisation objective: the algorithm's value on every request sequence is at most c · opt.

              Equations
              Instances For