test: add tests and benchmarks for cbv tactic (#12345)

This PR adds two benchmarks (sieve of Eratosthenes, removing duplicates
from the list) and one test (a function with sublinear complexity
defined via well-founded recursion evaluated on large naturals with up
to `60` digits).

The tests have been suggested by @b-mehta.
This commit is contained in:
Wojciech Różowski 2026-02-06 11:41:03 +00:00 committed by GitHub
parent 8d29c591e6
commit d2176cb5fb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 96 additions and 0 deletions

View file

@ -0,0 +1,16 @@
import Std
set_option cbv.warning false
def dedup (l : List Nat) : List Nat := Id.run do
let mut S : Std.TreeSet Nat := ∅
for i in l do
S := S.insert i
return S.toList
example : dedup [1] = [1] := by conv => lhs; cbv
example : dedup [1,2] = [1,2] := by conv => lhs; cbv
example : dedup [1,1] = [1] := by conv => lhs; cbv
example : dedup [1,2,2] = [1,2] := by conv => lhs; cbv

View file

@ -0,0 +1,30 @@
import Lean
open Lean
def divisorsList (n : Nat) : List Nat :=
(List.range' 1 n).filter fun d => n % d = 0
def mkProblem (n : Nat) : Expr := mkApp (mkConst ``divisorsList) (mkNatLit n)
def runProblem (n : Nat) : MetaM Unit := do
let problem := mkProblem n
let startTime ← IO.monoNanosNow
let executed ← Lean.Meta.Tactic.Cbv.cbvEntry problem
let endTime ← IO.monoNanosNow
let ms := (endTime - startTime).toFloat / 1000000.0
match executed with
| .rfl _ => IO.println s!"goal_{n}: {ms} ms"
| .step _ proof _ =>
let startTime ← IO.monoNanosNow
Meta.checkWithKernel proof
let endTime ← IO.monoNanosNow
let kernelMs := (endTime - startTime).toFloat / 1000000.0
IO.println s!"cbv: goal_{n}: {ms} ms, kernel: {kernelMs} ms"
def runCbvTests : MetaM Unit := do
IO.println "=== Call-By-Value Tactic Tests ==="
IO.println ""
for n in List.range 200 do
runProblem n
#eval runCbvTests

View file

@ -671,3 +671,15 @@
run_config:
<<: *time
cmd: lean ./cbv/leroy.lean
- attributes:
description: cbv tactic (Eratosthenes' sieve)
tags: [other]
run_config:
<<: *time
cmd: lean ./cbv/divisors.lean
- attributes:
description: cbv tactic (removing duplicates from the list)
tags: [other]
run_config:
<<: *time
cmd: lean ./cbv/dedup.lean

38
tests/lean/run/cbv2.lean Normal file
View file

@ -0,0 +1,38 @@
set_option cbv.warning false
def popcount : Nat → Nat
| 0 => 0
| 1 => 1
| n@(_+2) => if n % 2 = 0 then popcount (n / 2) else popcount (n / 2) + 1
termination_by n => n
/--
error: Tactic `decide` failed for proposition
popcount 123498203491224398 = 32
because its `Decidable` instance
instDecidableEqNat (popcount 123498203491224398) 32
did not reduce to `isTrue` or `isFalse`.
After unfolding the instances `instDecidableEqNat` and `Nat.decEq`, reduction got stuck at the `Decidable` instance
match h : (popcount 123498203491224398).beq 32 with
| true => isTrue ⋯
| false => isFalse ⋯
-/
#guard_msgs in
example : popcount 123498203491224398 = 32 := by decide
example : popcount 123498203491224398 = 32 := by conv => lhs; cbv
example : popcount 1234982034912243981 = 30 := by conv => lhs; cbv
example : popcount 1234982034912243981523 = 35 := by conv => lhs; cbv
example : popcount 12349820349122439815231238 = 42 := by conv => lhs; cbv
example : popcount 12349820349122439815231238098123 = 49 := by conv => lhs; cbv
example : popcount 1234982034912243981523123809812323 = 65 := by conv => lhs; cbv
example : popcount 1234982034912243981523123809812323982928213984812309234 = 101 := by conv => lhs; cbv
example : popcount 1234982034912243981523123809812323982928213984812309234213989 = 84 := by conv => lhs; cbv