Skip to content

While loop - #184

Draft
crei wants to merge 12 commits into
origin_mainfrom
while_loop
Draft

While loop#184
crei wants to merge 12 commits into
origin_mainfrom
while_loop

Conversation

@crei

@crei crei commented Sep 5, 2026

Copy link
Copy Markdown
Owner

No description provided.

mathlib-nightly-testing Bot and others added 12 commits August 31, 2026 20:30
Bump `mathlib` dependency to
[e06eff5](leanprover-community/mathlib4@e06eff5):
chore(Data): move some files to Basic (#43176) (2026-08-31)
Previously at:
[0fa18d4](leanprover-community/mathlib4@0fa18d4):
refactor: change the default value of `Measure.map` to a Dirac mass
(#42322) (2026-08-26)

Closes leanprover#847

Failure log from the validation run:
[download](https://github.com/leanprover-community/downstream-reports/actions/runs/33406502145/artifacts/9763801315)
_(link expires after 1 year)_

---

This PR bumps `mathlib` to an identified incompatible (first-known-bad)
commit (`e06eff5`) so you can reproduce and fix the incompatibility
locally by checking out this branch.

_Opened automatically by
[downstream-reports/track-incompatibility](https://github.com/leanprover-community/downstream-reports)
via [this workflow
run](https://github.com/leanprover/cslib/actions/runs/33434556067)._

---------

Co-authored-by: mathlib-nightly-testing[bot] <mathlib-nightly-testing[bot]@users.noreply.github.com>
Co-authored-by: Chris Henson <chrishenson.net@gmail.com>
Drop an `obtain` that the following `grind` does not need, as flagged by
[the weekly `mergeWithGrind`
report](https://leanprover.zulipchat.com/#narrow/channel/513188-CSLib/topic/Weekly.20linting.20log/near/620201866).
…eanprover#851)

Golf a heavy proof that was recently flagged as such (in leanprover#850) by
splitting `all_goals` into bullets and doing the work.
Restructure the complexity definitions and add the scaffolding for the
loop combinators of multi-tape Turing machines.

Deterministic.lean:
* rework the hierarchy of computability definitions into three layers:
  `ComputesFunInTimeAndSpace` (behaviour of a given machine, generic
  alphabet), `ComputableInTimeAndSpace` (existence of a finite machine
  over `Bool`) and `ComputableInTimeAndSpaceOfLength` (bounds depending
  only on the input length), with all bounds depending on the input
  rather than on its length
* add `Function.Embedding.listMap`, the `mono` lemmas and
  `ComputableInTimeAndSpace.congr`, which reads a computation as a
  computation of a different function at different encodings

Combinators:
* `Loop`: the loop with a fused body `α → Option α`, its partial
  function `loopFunction` and the statement of its complexity
* `While`: the loop with an explicit condition, characterised by
  `WhileRel` and by the iterates of its body, with its complexity
  derived from the loop by fusing the condition into the body
* `Ite`, `Comp`: the complexity of a conditional and of a composition

Encodings:
* requirements on encodings instead of fixed encodings, starting with
  `IsOptionEncoding` and the canonical `encOption`

Plumbing:
* the machine-level constructions the combinators are built from:
  sequential composition (proved), running a machine on other tapes,
  the clean-halting normal form, tape contents and redirecting the
  input and output of a machine to work tapes

The constructions themselves are still missing; the files state their
results as `proof_wanted` and both new directories have a README
describing the plan.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Prove `computableInTimeAndSpace_loopFunction` modulo the plumbing, which is
stated as `sorry`ed theorems. `Loop.lean` itself contains no `sorry`.

`proof_wanted` emits a private declaration and its `❰…❱` reference syntax
resolves only within one file, so the plumbing results a combinator builds on
have to be real declarations. The ones the loop needs are therefore stated as
theorems with a `sorry` body; `lake build --wfail` fails on them until they are
filled in.

Words.lean (new): the interface the combinators use.
* `TapesHold` and `TransformsTapes`: `TransformsCfg` restricted to
  configurations in which every work tape holds a word, with the input head
  normalised to position `1` and the output preserved. Untouched tapes are
  described by the postcondition rather than by a set of tape indices, so
  `Cfg.AgreesOutside` never appears in a combinator.
* scratch tapes are hidden behind `∃ m c, ∀ k i o keep, …`, so a caller names
  an input tape, an output tape and the tapes to keep, and never an embedding.
* `exists_transformsTapes_repeat`: the loop-back that `seq` cannot express.
  `seq` sends the halting state of one machine to the initial state of the
  *next* one; a loop sends it back to the initial state of the *same* one.
  This was missing from the plan and is the only reason the loop combinator
  needs the machine level at all.
* `exists_transformsTapes_branch` is family-indexed. Since the bounds of
  `TransformsCfg` are numbers, a specification whose bounds depend on the input
  is a family over one fixed machine, which the unindexed `exists_branchOnTape`
  cannot provide.
* `exists_transformsTapes_ofComputable` and its input-tape variant fold together
  the clean normal form, `onTape` and `liftTapes`.

Loop:
* `mem_loopFunction_iff` and the lemmas on `loopIterate` it rests on, relating
  the function the loop computes to the iterates the machine runs through
  (proved, and free of `sorry`).
* `computableInTimeAndSpace_loopFunction`: the machine copies its input onto
  `T1`, runs the body into `T3`, and then repeats "compute the flag on `T4`;
  either stop or clear `T4`, clear `T1`, destruct `T3` onto `T1`, clear `T3`
  and run the body again", finally emitting `T1`. The loop invariant is keyed
  on the current value rather than on the round index, so one round is a single
  `TransformsTapes` statement per input.

Deterministic:
* `length_output_runFrom_le` and `ComputableInTimeAndSpace.length_encOut_le`:
  a machine emits at most one symbol per step. This is the only bound available
  on the length of an intermediate result, since a machine can produce an output
  much longer than the space it uses; the loop needs it to bound
  `(encOpt (some x)).length`, which `hsize` does not bound.

Encodings/Option:
* `computableInTimeAndSpace_isNone` is proved: it is `Option.isNone` being
  constant outside `{none}`.

Comp:
* `computableInTimeAndSpace_id`, the streaming copy, used to move the input of
  the loop onto a work tape.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants