lean4-htt/tests/lean/guessLexDiff.lean.expected.out
Joachim Breitner 4c57da4b0f
feat: infer termination arguments like xs.size - i (#3666)
a common pattern for recursive functions is
```
def countUp (n i acc : Nat) : Nat :=
  if i < n then
    countUp n (i+1) (acc + i)
  else
    acc
```
where we increase a value `i` until it hits an upper bound. This is
particularly common with array processing functions:
```
$ git grep 'termination_by.*size.*-' src/|wc -l
26
```

GuessLex now recognizes this pattern. The general approach is:

For every recursive call, check if the context contains hypotheses of
the form `e₁ < e₂` (or similar comparisions), and then consider `e₂ -
e₁` as a termination argument.

Currently, this only fires when `e₁` and `e₂` only depend on the
functions parameters, but not local let-bindings or variables bound in
local pattern matches.

Duplicates are removed.

In the table showing the termination argument failures, long termination
arguments are now given a number and abbreviated as e.g. `#4` in the
table headers.

More examples in the test file, here as some highlights:
```
def distinct (xs : Array Nat) : Bool :=
  let rec loop (i j : Nat) : Bool :=
    if _ : i < xs.size then
      if _ : j < i then
        if xs[j] = xs[i] then
          false
        else
          loop i (j+1)
      else
        loop (i+1) 0
    else
      true
  loop 0 0
```
infers
```
termination_by (Array.size xs - i, i - j)
```
and the weird functions where `i` goes up or down
```
def weird (xs : Array Nat) (i : Nat) : Bool :=
  if _ : i < xs.size then
    if _ : 0 < i then
      if xs[i] = 42 then
        weird xs.pop (i - 1)
      else
        weird xs (i+1)
    else
      weird xs (i+1)
  else
    true
decreasing_by all_goals simp_wf; omega
```
infers
```
termination_by (Array.size xs - i, i)
```
but unfortunately needs `decreasing_by` pending the “big
decreasing_tactic refactor” that
I expect we’ll want to do at some point.
2024-03-16 12:27:35 +00:00

95 lines
2.4 KiB
Text

Inferred termination argument:
termination_by n - i
Inferred termination argument:
termination_by Array.size xs - i
Inferred termination argument:
termination_by Array.size xs - i
Inferred termination argument:
termination_by (Array.size xs - i, Array.size ys - j)
Inferred termination argument:
termination_by (Array.size xs - i, i - j)
Inferred termination argument:
termination_by (Array.size xs - i, i)
guessLexDiff.lean:85:26-85:38: error: fail to show termination for
failure
with errors
argument #2 was not used for structural recursion
failed to eliminate recursive application
_root_.failure xs i
structural recursion cannot be used
Could not find a decreasing measure.
The arguments relate at each recursive call as follows:
(<, ≤, =: relation proved, ? all proofs failed, _: no proof attempted)
i #1 #2 i + i
1) 85:26-38 = = = =
2) 85:58-76 ? < _ _
3) 85:26-38 = = = =
4) 88:26-42 _ < _ _
5) 88:26-42 ? ≤ ≤ ?
6) 88:26-42 _ < _ _
7) 88:26-42 _ < _ _
8) 88:26-42 _ < _ _
9) 97:8-20 _ < _ _
#1: Array.size xs - i
#2: Array.size xs - (i + 1)
Please use `termination_by` to specify a decreasing measure.
guessLexDiff.lean:102:4-102:18: error: fail to show termination for
mutual_failure
mutual_failure2
with errors
structural recursion does not handle mutually recursive functions
Could not find a decreasing measure.
The arguments relate at each recursive call as follows:
(<, ≤, =: relation proved, ? all proofs failed, _: no proof attempted)
Call from mutual_failure to mutual_failure2 at 104:4-24:
i #1 #2
i = ? ?
#3 ? = ?
Call from mutual_failure to mutual_failure2 at 104:52-78:
i #1 #2
i ? _ _
#3 _ < _
Call from mutual_failure to mutual_failure2 at 104:4-24:
i #1 #2
i _ _ _
#3 _ = _
Call from mutual_failure to mutual_failure2 at 111:4-28:
i #1 #2
i _ _ _
#3 _ < _
Call from mutual_failure to mutual_failure2 at 117:8-28:
i #1 #2
i _ _ _
#3 _ ? _
Call from mutual_failure2 to mutual_failure at 123:4-23:
i #3
i _ _
#1 _ _
#2 _ _
Call from mutual_failure2 to mutual_failure at 123:50-75:
i #3
i _ _
#1 _ _
#2 _ _
Call from mutual_failure2 to mutual_failure at 127:4-27:
i #3
i _ _
#1 _ _
#2 _ _
Call from mutual_failure2 to mutual_failure at 133:8-27:
i #3
i _ _
#1 _ _
#2 _ _
#1: Array.size xs - i
#2: Array.size xs - (i + 1)
#3: Array.size xs - i
Please use `termination_by` to specify a decreasing measure.