Skip to content

Commit fce31d0

Browse files
authored
Fix deprecations and update exposition page CI (#199)
2 parents d3e829a + 9ac376c commit fce31d0

11 files changed

Lines changed: 146 additions & 66 deletions

File tree

‎.github/workflows/blueprint.yml‎

Lines changed: 97 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,18 @@ permissions:
2424
actions: write # Write access to GitHub Actions
2525

2626
env:
27-
LEAN_EXPOSITION_REPO: LeanMachineLearning/exposition
28-
LEAN_EXPOSITION_REF: main
27+
REFEREE_REPO: LeanMachineLearning/exposition
28+
# The referee release to use. Leave empty for the most recent one; set a tag (e.g. `v0.1.0`) to
29+
# pin the site generator, which is worth doing once the output is being read by anyone.
30+
#
31+
# A *release* rather than a run artifact on purpose: release assets of a public repository need no
32+
# authentication and never expire, while a cross-repository artifact download needs a PAT with
33+
# `actions:read` (a workflow's own GITHUB_TOKEN cannot reach another repository's artifacts) and
34+
# is deleted after 90 days.
35+
REFEREE_VERSION: ""
36+
# Kept as `exposition` rather than renamed to `referee` along with the tool: this path is the
37+
# published URL, and existing links to it would break.
38+
REFEREE_SITE_URL: https://leanmachinelearning.org/LML/exposition
2939

3040
jobs:
3141
build_project:
@@ -59,29 +69,89 @@ jobs:
5969
run: |
6070
./scripts/build_docs.sh
6171
62-
- name: Clone lean-exposition
72+
- name: Download referee binary
6373
if: github.event_name == 'push'
74+
env:
75+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
6476
run: |
65-
git clone --depth 1 --branch "$LEAN_EXPOSITION_REF" \
66-
"https://github.com/$LEAN_EXPOSITION_REPO" /tmp/lean-exposition
77+
set -euo pipefail
78+
mkdir -p /tmp/referee
79+
gh release download ${REFEREE_VERSION:+"$REFEREE_VERSION"} \
80+
-R "$REFEREE_REPO" \
81+
--pattern 'referee-linux-x86_64-*.tar.gz' \
82+
--dir /tmp/referee --clobber
83+
tar -xzf /tmp/referee/referee-linux-x86_64-*.tar.gz -C /tmp/referee
84+
referee_bin=$(echo /tmp/referee/referee-linux-x86_64-*/referee)
85+
chmod +x "$referee_bin"
86+
echo "REFEREE_BIN=$referee_bin" >> "$GITHUB_ENV"
6787
68-
- name: Build exposition binary
88+
# `referee` is a Lean executable built with `supportInterpreter := true`, so it loads the
89+
# shared library of the toolchain it was compiled against and has to match this project's.
90+
# Checked here because the alternative is a link-time failure four steps later that says
91+
# nothing about the cause.
92+
want=$(tr -d '[:space:]' < lean-toolchain)
93+
got=$(jq -r .lean_toolchain "$(dirname "$referee_bin")/metadata.json" | tr -d '[:space:]')
94+
if [ "$want" != "$got" ]; then
95+
echo "::error::referee was built for $got but this project uses $want. Publish a \
96+
referee release from a matching toolchain, or pin REFEREE_VERSION to one."
97+
exit 1
98+
fi
99+
100+
# The previous run's collected data, so the site can say what changed since it. Optional in
101+
# every direction: the first run has nothing to download, a failed lookup is swallowed, and
102+
# `build-site` simply omits the Changes page when no baseline reaches it.
103+
- name: Fetch previous referee data for the revision diff
69104
if: github.event_name == 'push'
105+
continue-on-error: true
106+
env:
107+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
70108
run: |
71-
cd /tmp/lean-exposition && lake build exposition
72-
echo "EXPOSITION_BIN=/tmp/lean-exposition/.lake/build/bin/exposition" >> "$GITHUB_ENV"
109+
set -euo pipefail
110+
run_id=$(gh run list -R "$GITHUB_REPOSITORY" \
111+
--workflow "${{ github.workflow }}" --branch "${{ github.ref_name }}" \
112+
--status success --limit 1 --json databaseId --jq '.[0].databaseId // empty')
113+
[ -n "$run_id" ] || { echo "no earlier successful run; skipping the baseline"; exit 0; }
114+
gh run download "$run_id" -R "$GITHUB_REPOSITORY" \
115+
-n referee-data -D /tmp/referee-baseline
116+
echo "REFEREE_BASELINE=/tmp/referee-baseline/referee-data.json" >> "$GITHUB_ENV"
73117
74-
- name: Build exposition documentation
118+
- name: Build the referee site
75119
if: github.event_name == 'push'
76120
run: |
77-
lake env "$EXPOSITION_BIN" \
78-
--root LeanMachineLearning \
79-
--repo-url https://github.com/LeanMachineLearning/LML \
80-
--site-url https://leanmachinelearning.org/LML/exposition \
81-
--output ./exposition \
82-
--exclude-lib LMLTutorial
83-
mkdir -p home_page/exposition
84-
cp -r exposition/html-multi/* home_page/exposition
121+
set -euo pipefail
122+
# The phase split: everything needing a Lean environment produces data, and rendering is a
123+
# pure function of that data. `--exclude-lib` applies to the three phases that import the
124+
# project, and to none of `build-site`, which reads only the JSON. `highlight-extracted`
125+
# is deliberately skipped — it re-elaborates every extracted file and costs more than the
126+
# rest of this job combined; without it the standalone files are still written and linked,
127+
# just not rendered inline.
128+
lake env "$REFEREE_BIN" collect \
129+
--root LeanMachineLearning --exclude-lib LMLTutorial --data referee-data.json
130+
lake env "$REFEREE_BIN" extract \
131+
--data referee-data.json --exclude-lib LMLTutorial --output ./referee-site
132+
lake env "$REFEREE_BIN" highlight \
133+
--data referee-data.json --output ./referee-site
134+
# `--trust` is an editorial claim, not a derived fact: it says whoever publishes this site
135+
# vouches for Mathlib and everything under it. Drop it and every upstream package counts
136+
# as unaudited; name more packages to vouch for more.
137+
"$REFEREE_BIN" build-site \
138+
--data referee-data.json \
139+
--output ./referee-site \
140+
--repo-url "https://github.com/$GITHUB_REPOSITORY" \
141+
--site-url "$REFEREE_SITE_URL" \
142+
--trust mathlib \
143+
${REFEREE_BASELINE:+--baseline "$REFEREE_BASELINE"} \
144+
${REFEREE_BASELINE:+--baseline-label "the previous build"}
145+
146+
# Kept as an artifact so the *next* run can diff against it. Also the thing to download when
147+
# you want to re-render the site locally without re-importing the project.
148+
- name: Upload referee data
149+
if: github.event_name == 'push'
150+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
151+
with:
152+
name: referee-data
153+
path: referee-data.json
154+
retention-days: 90
85155

86156
- name: Compile blueprint and documentation
87157
uses: leanprover-community/docgen-action@7b5b9a1822650bd45aaeb4182d94bceba2030f89 # 2026-04-14
@@ -91,6 +161,16 @@ jobs:
91161
build-page: false
92162
deploy: false
93163

164+
# After the docs step, which writes into the same folder alongside `tutorial/` from
165+
# `build_docs.sh`. Those steps only ever add, so the order is not load-bearing — but copying
166+
# last keeps the referee output out of reach of anything else that writes there.
167+
- name: Add the referee site to the home page
168+
if: github.event_name == 'push'
169+
run: |
170+
set -euo pipefail
171+
mkdir -p home_page/exposition
172+
cp -r referee-site/html-multi/. home_page/exposition/
173+
94174
- name: "Upload website (API documentation, blueprint and any home page)"
95175
if: github.event_name == 'push'
96176
uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0

‎LeanMachineLearning/ForMathlib/MeasureTheory/Order/MeasurableArg.lean‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ lemma measurable_argmax [MeasurableSpace ι] [MeasurableEq α] [MeasurableSup₂
7474
refine MeasurableSet.iUnion fun S ↦ (.iUnion fun hS ↦ ?_)
7575
exact measurableSet_eq_fun (by fun_prop) measurable_const
7676
ext f
77-
simp only [Set.mem_setOf_eq, Set.mem_iUnion, exists_prop, exists_eq_right']
77+
simp only [Set.mem_ofPred_eq, Set.mem_iUnion, exists_prop, exists_eq_right']
7878
constructor
7979
· intro hf x hx
8080
rw [← hf]

‎LeanMachineLearning/ForMathlib/Probability/Independence/CondDistrib.lean‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -457,7 +457,7 @@ lemma condDistrib_prod_of_forall_condDistrib_cond [Countable Ω'] [IsFiniteMeasu
457457
(Measure.map (fun ω ↦ (X ω, Z ω)) μ ⊗ₘ κ) (s ∩ {p | p.1.2 = b}) by
458458
have hs_iUnion : s = ⋃ b, s ∩ {p | p.1.2 = b} := by
459459
ext p
460-
simp only [Set.mem_iUnion, Set.mem_inter_iff, Set.mem_setOf_eq]
460+
simp only [Set.mem_iUnion, Set.mem_inter_iff, Set.mem_ofPred_eq]
461461
grind
462462
have h_disj : Pairwise (Function.onFun Disjoint fun b ↦ s ∩ {p | p.1.2 = b}) := by
463463
intro i j hij
@@ -486,13 +486,13 @@ lemma condDistrib_prod_of_forall_condDistrib_cond [Countable Ω'] [IsFiniteMeasu
486486
((measurableSet_singleton _).preimage (by fun_prop))
487487
· fun_prop
488488
· exact (measurableSet_singleton _).preimage (by fun_prop)
489-
simp only [Set.preimage_setOf_eq]
489+
simp only [Set.preimage_ofPred_eq]
490490
classical
491491
have h_le : ∫⁻ a, (κ (X a, Z a)) {a_1 | Z a = b} ∂μ ≤
492492
∫⁻ a, {a' | Z a' = b}.indicator (fun _ ↦ κ.bound) a ∂μ := by
493493
gcongr with a
494494
by_cases hZ : Z a = b
495-
· simp only [hZ, Set.setOf_true, Set.mem_setOf_eq, Set.indicator_of_mem]
495+
· simp only [hZ, Set.ofPred_true, Set.mem_ofPred_eq, Set.indicator_of_mem]
496496
exact κ.measure_le_bound _ _
497497
· simp [hZ]
498498
refine le_antisymm (h_le.trans ?_) zero_le
@@ -525,8 +525,8 @@ lemma condDistrib_prod_of_forall_condDistrib_cond [Countable Ω'] [IsFiniteMeasu
525525
rw [← h1, ← mul_assoc, ENNReal.mul_inv_cancel hb (by simp), one_mul]
526526
convert h1'
527527
· ext x
528-
simp only [Set.preimage_inter, Set.preimage_setOf_eq, Set.mem_inter_iff, Set.mem_preimage,
529-
Set.mem_setOf_eq]
528+
simp only [Set.preimage_inter, Set.preimage_ofPred_eq, Set.mem_inter_iff, Set.mem_preimage,
529+
Set.mem_ofPred_eq]
530530
grind
531531
· rw [Measure.compProd_apply, Measure.compProd_apply, lintegral_map, lintegral_map]
532532
rotate_left
@@ -538,7 +538,7 @@ lemma condDistrib_prod_of_forall_condDistrib_cond [Countable Ω'] [IsFiniteMeasu
538538
· exact hs'
539539
· exact hs.inter ((measurableSet_singleton _).preimage (by fun_prop))
540540
rw [lintegral_cond, ← mul_assoc, ENNReal.mul_inv_cancel hb (by simp), one_mul]
541-
simp only [Set.preimage_inter, Set.preimage_setOf_eq, Kernel.coe_comap, Function.comp_apply]
541+
simp only [Set.preimage_inter, Set.preimage_ofPred_eq, Kernel.coe_comap, Function.comp_apply]
542542
classical
543543
have h_eq : (fun a ↦ κ (X a, Z a) (Prod.mk (X a, Z a) ⁻¹' s ∩ {a_1 | Z a = b})) =
544544
{a | Z a = b}.indicator
@@ -550,7 +550,7 @@ lemma condDistrib_prod_of_forall_condDistrib_cond [Countable Ω'] [IsFiniteMeasu
550550
swap; · exact (measurableSet_singleton _).preimage (by fun_prop)
551551
refine setLIntegral_congr_fun ((measurableSet_singleton _).preimage (by fun_prop)) fun a ha ↦ ?_
552552
congr 1 with ω
553-
simp only [Set.mem_inter_iff, Set.mem_preimage, Set.mem_setOf_eq, and_iff_left_iff_imp]
553+
simp only [Set.mem_inter_iff, Set.mem_preimage, Set.mem_ofPred_eq, and_iff_left_iff_imp]
554554
grind
555555

556556
lemma cond_of_indepFun [IsZeroOrProbabilityMeasure μ] (h : IndepFun X T μ)

‎LeanMachineLearning/ForMathlib/Probability/Kernel/KernelSub.lean‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ lemma measurableSet_eq (κ η : Kernel α β) [IsFiniteKernel κ] [IsFiniteKerne
149149
classical
150150
have h_sub : {a | κ a = η a} = {a | (κ - η) a = 0} ∩ {a | (η - κ) a = 0} := by
151151
ext1 a
152-
simp only [Set.mem_setOf_eq, Set.mem_inter_iff, sub_apply_eq_zero_iff_le]
152+
simp only [Set.mem_ofPred_eq, Set.mem_inter_iff, sub_apply_eq_zero_iff_le]
153153
exact ⟨fun h ↦ by simp [h], fun h ↦ le_antisymm h.1 h.2⟩
154154
rw [h_sub]
155155
refine MeasurableSet.inter ?_ ?_

‎LeanMachineLearning/Online/Bandit/Algorithms/ETC.lean‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ lemma expectation_pullCount_le [Nonempty (Fin K)]
226226
have : (fun ω ↦ (pullCount A a n ω : ℝ))
227227
=ᵐ[P] fun ω ↦ m + (n - K * m) * {ω' | A (K * m) ω' = a}.indicator (fun _ ↦ 1) ω := by
228228
filter_upwards [pullCount_of_ge h a hm hn] with ω h
229-
simp only [h, Set.indicator_apply, Set.mem_setOf_eq, mul_ite, mul_one, mul_zero, Nat.cast_add,
229+
simp only [h, Set.indicator_apply, Set.mem_ofPred_eq, mul_ite, mul_one, mul_zero, Nat.cast_add,
230230
Nat.cast_ite, CharP.cast_eq_zero, add_right_inj]
231231
norm_cast
232232
rw [integral_congr_ae this, integral_add (integrable_const _), integral_const_mul]

‎LeanMachineLearning/Online/Bandit/Algorithms/Regret/BayesRegretTS.lean‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ lemma integral_sum_range_actionMean_bestAction_sub_ucb_bestAction_le {alg : Algo
233233
intro ω hω
234234
apply sum_nonpos
235235
intro t ht
236-
rw [Set.mem_compl_iff, Set.mem_setOf_eq] at hω
236+
rw [Set.mem_compl_iff, Set.mem_ofPred_eq] at hω
237237
push Not at hω
238238
grind [hω t (mem_range.mp ht), ucb, actionMean]
239239
_ ≤ ∫ ω in F, ∑ t ∈ range n, (u - l) ∂P := by
@@ -284,7 +284,7 @@ lemma integral_sum_range_ucb_action_sub_actionMean_action_le {alg : Algorithm (F
284284
· apply setIntegral_mono_on (Integrable.integrableOn (by fun_prop))
285285
(Integrable.integrableOn (by fun_prop)) hF.compl
286286
intro ω hω
287-
rw [Set.mem_compl_iff, Set.mem_setOf_eq] at hω
287+
rw [Set.mem_compl_iff, Set.mem_ofPred_eq] at hω
288288
push Not at hω
289289
exact sum_ucb_sub_mean_le (fun a ↦ (κ (E ω, a))[id]) (hm (E ω)) hlu
290290
(fun t ht hpc ↦ hω t ht (A t ω) hpc)

‎LeanMachineLearning/Online/Bandit/Algorithms/UCB.lean‎

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ lemma prob_ucbIndex_le [Nonempty (Fin K)] {alg : Algorithm (Fin K) ℝ}
216216
1 / (n + 1) ^ (c - 1) := by
217217
let s : Set (ℕ × ℝ) := {(m, x) | 0 < m ∧ x / m + √(2 * (c * σ2) * log (↑n + 1) / m) ≤ (ν a)[id]}
218218
have hs : MeasurableSet s := by
219-
simp only [Nat.cast_nonneg, sqrt_div', id_eq, measurableSet_setOf, s]
219+
simp only [Nat.cast_nonneg, sqrt_div', id_eq, measurableSet_setOfPred, s]
220220
fun_prop
221221
classical
222222
calc P {h | 0 < pullCount A a n h ∧ empMean A R a n h + ucbWidth A (c * σ2) a n h ≤ (ν a)[id]}
@@ -234,8 +234,8 @@ lemma prob_ucbIndex_le [Nonempty (Fin K)] {alg : Algorithm (Fin K) ℝ}
234234
refine Finset.sum_congr rfl fun k hk ↦ ?_
235235
congr with ω
236236
have hk : 0 < k := by grind
237-
simp only [Nat.cast_nonneg, sqrt_div', id_eq, Set.preimage_setOf_eq, hk, true_and,
238-
Set.mem_setOf_eq, s]
237+
simp only [Nat.cast_nonneg, sqrt_div', id_eq, Set.preimage_ofPred_eq, hk, true_and,
238+
Set.mem_ofPred_eq, s]
239239
grind
240240
_ ≤ ∑ k ∈ Icc 1 n, (1 : ℝ≥0∞) / (n + 1) ^ c := by
241241
gcongr with k hk
@@ -259,7 +259,7 @@ lemma prob_ucbIndex_ge [Nonempty (Fin K)] {alg : Algorithm (Fin K) ℝ}
259259
(ν a)[id] ≤ empMean A R a n h - ucbWidth A (c * σ2) a n h} ≤ 1 / (n + 1) ^ (c - 1) := by
260260
let s : Set (ℕ × ℝ) := {(m, x) | 0 < m ∧ (ν a)[id] ≤ x / m - √(2 * (c * σ2) * log (↑n + 1) / m)}
261261
have hs : MeasurableSet s := by
262-
simp only [Nat.cast_nonneg, sqrt_div', id_eq, measurableSet_setOf, s]
262+
simp only [Nat.cast_nonneg, sqrt_div', id_eq, measurableSet_setOfPred, s]
263263
fun_prop
264264
classical
265265
calc P {h | 0 < pullCount A a n h ∧ (ν a)[id] ≤ empMean A R a n h - ucbWidth A (c * σ2) a n h}
@@ -277,8 +277,8 @@ lemma prob_ucbIndex_ge [Nonempty (Fin K)] {alg : Algorithm (Fin K) ℝ}
277277
refine Finset.sum_congr rfl fun k hk ↦ ?_
278278
congr with ω
279279
have hk : 0 < k := by grind
280-
simp only [id_eq, Nat.cast_nonneg, sqrt_div', Set.preimage_setOf_eq, hk, true_and,
281-
Set.mem_setOf_eq, s]
280+
simp only [id_eq, Nat.cast_nonneg, sqrt_div', Set.preimage_ofPred_eq, hk, true_and,
281+
Set.mem_ofPred_eq, s]
282282
grind
283283
_ ≤ ∑ k ∈ Icc 1 n, (1 : ℝ≥0∞) / (n + 1) ^ c := by
284284
gcongr with k hk
@@ -397,7 +397,7 @@ lemma some_sum_eq_zero [Nonempty (Fin K)]
397397
have h_gt := time_gt_of_pullCount_gt_one h a (ν := ν) (c := c * σ2) (hK := hK)
398398
filter_upwards [h_ae, h_gt] with ω h_le h_time_ge
399399
simp only [id_eq, tsub_le_iff_right, sum_eq_zero_iff, mem_range, Set.indicator_apply_eq_zero,
400-
Set.mem_setOf_eq, Pi.one_apply, one_ne_zero, imp_false, not_and, not_le]
400+
Set.mem_ofPred_eq, Pi.one_apply, one_ne_zero, imp_false, not_and, not_le]
401401
intro k hn h_arm hC_lt h_le_best
402402
by_contra! h_le_arm
403403
have h := pullCount_arm_le (by positivity : 0 ≤ c * σ2) h_le_best (by simpa) ?_ ?_ ?_
@@ -472,12 +472,12 @@ lemma expectation_pullCount_le'
472472
(measurableSet_lt (by fun_prop) (by fun_prop))
473473
have h_meas_1 b : Measurable fun h ↦ {s | 0 < pullCount A a s h ∧ (ν a)[id] <
474474
empMean A R a s h - ucbWidth A (c * σ2) a s h}.indicator (1 : ℕ → ℕ) b := by
475-
simp only [id_eq, Set.indicator_apply, Set.mem_setOf_eq, Pi.one_apply]
475+
simp only [id_eq, Set.indicator_apply, Set.mem_ofPred_eq, Pi.one_apply]
476476
exact Measurable.ite (h_set_1 _) (by fun_prop) (by fun_prop)
477477
have h_meas_2 b : Measurable fun h ↦ {s | 0 < pullCount A (bestArm ν) s h ∧
478478
empMean A R (bestArm ν) s h + ucbWidth A (c * σ2) (bestArm ν) s h <
479479
(ν (bestArm ν))[id]}.indicator (1 : ℕ → ℕ) b := by
480-
simp only [id_eq, Set.indicator_apply, Set.mem_setOf_eq, Pi.one_apply]
480+
simp only [id_eq, Set.indicator_apply, Set.mem_ofPred_eq, Pi.one_apply]
481481
exact Measurable.ite (h_set_2 _) (by fun_prop) (by fun_prop)
482482
calc ∫⁻ ω, pullCount A a n ω ∂P
483483
_ ≤ ∫⁻ ω, C a + 1 +

0 commit comments

Comments
 (0)