Skip to content

Commit

Permalink
Trigger CI for leanprover/lean4#6329
Browse files Browse the repository at this point in the history
  • Loading branch information
leanprover-community-mathlib4-bot committed Jan 28, 2025
2 parents 3d37878 + 20c29cc commit d0d659f
Show file tree
Hide file tree
Showing 38 changed files with 1,082 additions and 606 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ on:

name: ci

concurrency:
group: build-${{ github.sha }}
cancel-in-progress: true

jobs:
build:
name: Build
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/docs-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:

- name: Build Docs
working-directory: docs
run: lake build -q Batteries:docs
run: lake build --keep-toolchain -q Batteries:docs

- name: Deploy Docs
run: |
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/docs-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:

- name: Build Docs
working-directory: docs
run: lake build -q Batteries:docs
run: lake build --keep-toolchain -q Batteries:docs

- name: Compress Docs
working-directory: docs
Expand Down
117 changes: 117 additions & 0 deletions .github/workflows/nightly_detect_failure.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,120 @@ jobs:
result = client.send_message(request)
print(result)
shell: python

# Next, determine if we should remind the humans to create a new PR to the `bump/v4.X.0` branch.

- name: Check for matching bump/nightly-YYYY-MM-DD branch
id: check_branch
uses: actions/github-script@v7
with:
script: |
const branchName = `bump/nightly-${process.env.NIGHTLY}`;
const branches = await github.rest.repos.listBranches({
owner: context.repo.owner,
repo: context.repo.repo
});
const exists = branches.data.some(branch => branch.name === branchName);
if (exists) {
console.log(`Branch ${branchName} exists.`);
return true;
} else {
console.log(`Branch ${branchName} does not exist.`);
return false;
}
result-encoding: string

- name: Exit if matching branch exists
if: steps.check_branch.outputs.result == 'true'
run: |
echo "Matching bump/nightly-YYYY-MM-DD branch found, no further action needed."
exit 0
- name: Fetch latest bump branch name
id: latest_bump_branch
uses: actions/github-script@v7
with:
script: |
const branches = await github.paginate(github.rest.repos.listBranches, {
owner: context.repo.owner,
repo: context.repo.repo
});
const bumpBranches = branches
.map(branch => branch.name)
.filter(name => name.match(/^bump\/v4\.\d+\.0$/))
.sort((a, b) => b.localeCompare(a, undefined, {numeric: true, sensitivity: 'base'}));
if (!bumpBranches.length) {
throw new Exception("Did not find any bump/v4.x.0 branch")
}
const latestBranch = bumpBranches[0];
return latestBranch;
- name: Fetch lean-toolchain from latest bump branch
id: bump_version
uses: actions/github-script@v7
with:
script: |
const response = await github.rest.repos.getContent({
owner: context.repo.owner,
repo: context.repo.repo,
path: 'lean-toolchain',
ref: ${{ steps.latest_bump_branch.outputs.result }}
});
const content = Buffer.from(response.data.content, 'base64').toString();
const version = content.match(/leanprover\/lean4:nightly-(\d{4}-\d{2}-\d{2})/)[1];
return version;
- name: Compare versions and post a reminder.
env:
BUMP_VERSION: ${{ steps.bump_version.outputs.result }}
BUMP_BRANCH: ${{ steps.latest_bump_branch.outputs.result }}
SHA: ${{ env.SHA }}
ZULIP_API_KEY: ${{ secrets.ZULIP_API_KEY }}
shell: python
run: |
import os
import zulip
client = zulip.Client(email='[email protected]', api_key=os.getenv('ZULIP_API_KEY'), site='https://leanprover.zulipchat.com')
current_version = os.getenv('NIGHTLY')
bump_version = os.getenv('BUMP_VERSION')
bump_branch = os.getenv('BUMP_BRANCH')
sha = os.getenv('SHA')
print(f'Current version: {current_version}, Bump version: {bump_version}, SHA: {sha}')
if current_version > bump_version:
print('Lean toolchain in `nightly-testing` is ahead of the bump branch.')
# Get the last message in the 'Batteries bump branch reminders' topic
request = {
'anchor': 'newest',
'num_before': 1,
'num_after': 0,
'narrow': [{'operator': 'stream', 'operand': 'nightly-testing'}, {'operator': 'topic', 'operand': 'Batteries bump branch reminders'}],
'apply_markdown': False # Otherwise the content test below fails.
}
response = client.get_messages(request)
messages = response['messages']
bump_branch_suffix = bump_branch.replace('bump/', '')
payload = f"🛠️: it looks like it's time to create a new bump/nightly-{current_version} branch from nightly-testing (specifically {sha}), and then PR that to {bump_branch}. "
payload += "To do so semi-automatically, run the following script from mathlib root:\n\n"
payload += f"```bash\n./scripts/create-adaptation-pr.sh --bumpversion={bump_branch_suffix} --nightlydate={current_version} --nightlysha={sha}\n```\n"
# Only post if the message is different
# We compare the first 160 characters, since that includes the date and bump version
if not messages or messages[0]['content'][:160] != payload[:160]:
# Log messages, because the bot seems to repeat itself...
if messages:
print("###### Last message:")
print(messages[0]['content'])
print("###### Current message:")
print(payload)
else:
print('The strings match!')
# Post the reminder message
request = {
'type': 'stream',
'to': 'nightly-testing',
'topic': 'Batteries bump branch reminders',
'content': payload
}
result = client.send_message(request)
print(result)
else:
print('No action needed.')
3 changes: 3 additions & 0 deletions Batteries.lean
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,11 @@ import Batteries.Data.HashMap
import Batteries.Data.LazyList
import Batteries.Data.List
import Batteries.Data.MLList
import Batteries.Data.NameSet
import Batteries.Data.Nat
import Batteries.Data.PairingHeap
import Batteries.Data.RBMap
import Batteries.Data.Random
import Batteries.Data.Range
import Batteries.Data.Rat
import Batteries.Data.Stream
Expand Down Expand Up @@ -87,6 +89,7 @@ import Batteries.Tactic.NoMatch
import Batteries.Tactic.OpenPrivate
import Batteries.Tactic.PermuteGoals
import Batteries.Tactic.PrintDependents
import Batteries.Tactic.PrintOpaques
import Batteries.Tactic.PrintPrefix
import Batteries.Tactic.SeqFocus
import Batteries.Tactic.ShowUnused
Expand Down
11 changes: 1 addition & 10 deletions Batteries/Data/Array/Lemmas.lean
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,6 @@ theorem forIn_eq_forIn_toList [Monad m]
@[deprecated (since := "2024-09-09")] alias data_zipWith := toList_zipWith
@[deprecated (since := "2024-08-13")] alias zipWith_eq_zipWith_data := data_zipWith

/-! ### filter -/

theorem size_filter_le (p : α → Bool) (l : Array α) :
(l.filter p).size ≤ l.size := by
simp only [← length_toList, toList_filter]
apply List.length_filter_le

/-! ### flatten -/

@[deprecated (since := "2024-09-09")] alias data_join := toList_flatten
Expand All @@ -49,7 +42,7 @@ where
((l.toList.drop i).indexOf? a).map (·+i) = (indexOfAux l a i).map Fin.val := by
rw [indexOfAux]
if h : i < l.size then
rw [List.drop_eq_getElem_cons h, ←getElem_eq_getElem_toList, List.indexOf?_cons]
rw [List.drop_eq_getElem_cons h, getElem_toList, List.indexOf?_cons]
if h' : l[i] == a then
simp [h, h']
else
Expand All @@ -76,8 +69,6 @@ theorem size_set! (a : Array α) (i v) : (a.set! i v).size = a.size := by simp

/-! ### mem -/

theorem mem_singleton : a ∈ #[b] ↔ a = b := by simp

/-! ### insertAt -/

@[simp] private theorem size_insertIdx_loop (as : Array α) (i : Nat) (j : Fin as.size) :
Expand Down
23 changes: 12 additions & 11 deletions Batteries/Data/Array/Monadic.lean
Original file line number Diff line number Diff line change
Expand Up @@ -125,36 +125,37 @@ theorem SatisfiesM_foldrM [Monad m] [LawfulMonad m]
simp [foldrM]; split; {exact go _ h0}
· next h => exact .pure (Nat.eq_zero_of_not_pos h ▸ h0)

theorem SatisfiesM_mapFinIdxM [Monad m] [LawfulMonad m] (as : Array α) (f : Fin as.size → α → m β)
theorem SatisfiesM_mapFinIdxM [Monad m] [LawfulMonad m] (as : Array α)
(f : (i : Nat) → α → (h : i < as.size) → m β)
(motive : Nat → Prop) (h0 : motive 0)
(p : Fin as.size → β → Prop)
(hs : ∀ i, motive i.1 → SatisfiesM (p i · ∧ motive (i + 1)) (f i as[i])) :
(p : (i : Nat) → β → (h : i < as.size)Prop)
(hs : ∀ i h, motive i → SatisfiesM (p i · h ∧ motive (i + 1)) (f i as[i] h)) :
SatisfiesM
(fun arr => motive as.size ∧ ∃ eq : arr.size = as.size, ∀ i h, p ⟨i, h⟩ arr[i])
(fun arr => motive as.size ∧ ∃ eq : arr.size = as.size, ∀ i h, p i arr[i] h)
(Array.mapFinIdxM as f) := by
let rec go {bs i j h} (h₁ : j = bs.size) (h₂ : ∀ i h h', p ⟨i, h⟩ bs[i]) (hm : motive j) :
let rec go {bs i j h} (h₁ : j = bs.size) (h₂ : ∀ i h h', p i bs[i] h) (hm : motive j) :
SatisfiesM
(fun arr => motive as.size ∧ ∃ eq : arr.size = as.size, ∀ i h, p ⟨i, h⟩ arr[i])
(fun arr => motive as.size ∧ ∃ eq : arr.size = as.size, ∀ i h, p i arr[i] h)
(Array.mapFinIdxM.map as f i j h bs) := by
induction i generalizing j bs with simp [mapFinIdxM.map]
| zero =>
have := (Nat.zero_add _).symm.trans h
exact .pure ⟨this ▸ hm, h₁ ▸ this, fun _ _ => h₂ ..⟩
| succ i ih =>
refine (hs _ (by exact hm)).bind fun b hb => ih (by simp [h₁]) (fun i hi hi' => ?_) hb.2
refine (hs _ _ (by exact hm)).bind fun b hb => ih (by simp [h₁]) (fun i hi hi' => ?_) hb.2
simp at hi'; simp [getElem_push]; split
· next h => exact h₂ _ _ h
· next h => cases h₁.symm ▸ (Nat.le_or_eq_of_le_succ hi').resolve_left h; exact hb.1
simp [mapFinIdxM]; exact go rfl nofun h0

theorem SatisfiesM_mapIdxM [Monad m] [LawfulMonad m] (as : Array α) (f : Nat → α → m β)
(motive : Nat → Prop) (h0 : motive 0)
(p : Fin as.size → β → Prop)
(hs : ∀ i, motive i.1 → SatisfiesM (p i · ∧ motive (i + 1)) (f i as[i])) :
(p : (i : Nat) → β → (h : i < as.size)Prop)
(hs : ∀ i h, motive i → SatisfiesM (p i · h ∧ motive (i + 1)) (f i as[i])) :
SatisfiesM
(fun arr => motive as.size ∧ ∃ eq : arr.size = as.size, ∀ i h, p ⟨i, h⟩ arr[i])
(fun arr => motive as.size ∧ ∃ eq : arr.size = as.size, ∀ i h, p i arr[i] h)
(as.mapIdxM f) :=
SatisfiesM_mapFinIdxM as (fun i => f i) motive h0 p hs
SatisfiesM_mapFinIdxM as (fun i a _ => f i a) motive h0 p hs

theorem size_modifyM [Monad m] [LawfulMonad m] (a : Array α) (i : Nat) (f : α → m α) :
SatisfiesM (·.size = a.size) (a.modifyM i f) := by
Expand Down
4 changes: 2 additions & 2 deletions Batteries/Data/ByteArray.lean
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ theorem get_push_lt (a : ByteArray) (x : UInt8) (i : Nat) (h : i < a.size) :
Array.size_set ..

@[simp] theorem get_set_eq (a : ByteArray) (i : Fin a.size) (v : UInt8) : (a.set i v)[i.val] = v :=
Array.get_set_eq ..
Array.getElem_set_self _ _ _ _ (eq := rfl) _

theorem get_set_ne (a : ByteArray) (i : Fin a.size) (v : UInt8) (hj : j < a.size) (h : i.val ≠ j) :
(a.set i v)[j]'(a.size_set .. ▸ hj) = a[j] :=
Expand All @@ -76,7 +76,7 @@ theorem set_set (a : ByteArray) (i : Fin a.size) (v v' : UInt8) :

@[simp] theorem data_append (a b : ByteArray) : (a ++ b).data = a.data ++ b.data := by
rw [←append_eq]; simp [ByteArray.append, size]
rw [Array.extract_empty_of_stop_le_start (h:=Nat.le_add_right ..), Array.append_nil]
rw [Array.extract_empty_of_stop_le_start (h:=Nat.le_add_right ..), Array.append_empty]
@[deprecated (since := "2024-08-13")] alias append_data := data_append

theorem size_append (a b : ByteArray) : (a ++ b).size = a.size + b.size := by
Expand Down
3 changes: 0 additions & 3 deletions Batteries/Data/Char.lean
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@ import Batteries.Tactic.Alias
theorem Char.le_antisymm_iff {x y : Char} : x = y ↔ x ≤ y ∧ y ≤ x :=
Char.ext_iff.trans UInt32.le_antisymm_iff

theorem Char.le_antisymm {x y : Char} (h1 : x ≤ y) (h2 : y ≤ x) : x = y :=
Char.le_antisymm_iff.2 ⟨h1, h2⟩

instance : Batteries.LawfulOrd Char := .compareOfLessAndEq
(fun _ => Nat.lt_irrefl _) Nat.lt_trans Nat.not_lt Char.le_antisymm

Expand Down
1 change: 1 addition & 0 deletions Batteries/Data/Fin.lean
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import Batteries.Data.Fin.Basic
import Batteries.Data.Fin.Fold
import Batteries.Data.Fin.Lemmas
import Batteries.Data.Fin.OfBits
66 changes: 34 additions & 32 deletions Batteries/Data/Fin/Basic.lean
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/-
Copyright (c) 2017 Robert Y. Lewis. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Robert Y. Lewis, Keeley Hoek, Mario Carneiro
Authors: Robert Y. Lewis, Keeley Hoek, Mario Carneiro, François G. Dorais, Quang Dao
-/
import Batteries.Tactic.Alias
import Batteries.Data.Array.Basic
Expand All @@ -18,20 +18,6 @@ alias enum := Array.finRange
@[deprecated (since := "2024-11-15")]
alias list := List.finRange

/-- Heterogeneous fold over `Fin n` from the right: `foldr 3 f x = f 0 (f 1 (f 2 x))`, where
`f 2 : α 3 → α 2`, `f 1 : α 2 → α 1`, etc.
This is the dependent version of `Fin.foldr`. -/
@[inline] def dfoldr (n : Nat) (α : Fin (n + 1) → Sort _)
(f : ∀ (i : Fin n), α i.succ → α i.castSucc) (init : α (last n)) : α 0 :=
loop n (Nat.lt_succ_self n) init where
/-- Inner loop for `Fin.dfoldr`.
`Fin.dfoldr.loop n α f i h x = f 0 (f 1 (... (f i x)))` -/
@[specialize] loop (i : Nat) (h : i < n + 1) (x : α ⟨i, h⟩) : α 0 :=
match i with
| i + 1 => loop i (Nat.lt_of_succ_lt h) (f ⟨i, Nat.lt_of_succ_lt_succ h⟩ x)
| 0 => x

/-- Heterogeneous monadic fold over `Fin n` from right to left:
```
Fin.foldrM n f xₙ = do
Expand All @@ -41,25 +27,33 @@ Fin.foldrM n f xₙ = do
let x₀ : α 0 ← f 0 x₁
pure x₀
```
This is the dependent version of `Fin.foldrM`, defined using `Fin.dfoldr`. -/
@[inline] def dfoldrM [Monad m] (n : Nat) (α : Fin (n + 1) → Sort _)
This is the dependent version of `Fin.foldrM`. -/
@[inline] def dfoldrM [Monad m] (n : Nat) (α : Fin (n + 1) → Type _)
(f : ∀ (i : Fin n), α i.succ → m (α i.castSucc)) (init : α (last n)) : m (α 0) :=
dfoldr n (fun i => m (α i)) (fun i x => x >>= f i) (pure init)
loop n (Nat.lt_succ_self n) init where
/--
Inner loop for `Fin.dfoldrM`.
```
Fin.dfoldrM.loop n f i h xᵢ = do
let xᵢ₋₁ ← f (i-1) xᵢ
...
let x₁ ← f 1 x₂
let x₀ ← f 0 x₁
pure x₀
```
-/
@[specialize] loop (i : Nat) (h : i < n + 1) (x : α ⟨i, h⟩) : m (α 0) :=
match i with
| i + 1 => (f ⟨i, Nat.lt_of_succ_lt_succ h⟩ x) >>= loop i (Nat.lt_of_succ_lt h)
| 0 => pure x

/-- Heterogeneous fold over `Fin n` from the left: `foldl 3 f x = f 0 (f 1 (f 2 x))`, where
`f 0 : α 0 → α 1`, `f 1 : α 1 → α 2`, etc.
/-- Heterogeneous fold over `Fin n` from the right: `foldr 3 f x = f 0 (f 1 (f 2 x))`, where
`f 2 : α 3 → α 2`, `f 1 : α 2 → α 1`, etc.
This is the dependent version of `Fin.foldl`. -/
@[inline] def dfoldl (n : Nat) (α : Fin (n + 1) → Sort _)
(f : ∀ (i : Fin n), α i.castSucc → α i.succ) (init : α 0) : α (last n) :=
loop 0 (Nat.zero_lt_succ n) init where
/-- Inner loop for `Fin.dfoldl`. `Fin.dfoldl.loop n α f i h x = f n (f (n-1) (... (f i x)))` -/
@[semireducible, specialize] loop (i : Nat) (h : i < n + 1) (x : α ⟨i, h⟩) : α (last n) :=
if h' : i < n then
loop (i + 1) (Nat.succ_lt_succ h') (f ⟨i, h'⟩ x)
else
haveI : ⟨i, h⟩ = last n := by ext; simp; omega
_root_.cast (congrArg α this) x
This is the dependent version of `Fin.foldr`. -/
@[inline] def dfoldr (n : Nat) (α : Fin (n + 1) → Type _)
(f : ∀ (i : Fin n), α i.succ → α i.castSucc) (init : α (last n)) : α 0 :=
dfoldrM (m := Id) n α f init

/-- Heterogeneous monadic fold over `Fin n` from left to right:
```
Expand All @@ -71,7 +65,7 @@ Fin.foldlM n f x₀ = do
pure xₙ
```
This is the dependent version of `Fin.foldlM`. -/
@[inline] def dfoldlM [Monad m] (n : Nat) (α : Fin (n + 1) → Sort _)
@[inline] def dfoldlM [Monad m] (n : Nat) (α : Fin (n + 1) → Type _)
(f : ∀ (i : Fin n), α i.castSucc → m (α i.succ)) (init : α 0) : m (α (last n)) :=
loop 0 (Nat.zero_lt_succ n) init where
/-- Inner loop for `Fin.dfoldlM`.
Expand All @@ -89,3 +83,11 @@ This is the dependent version of `Fin.foldlM`. -/
else
haveI : ⟨i, h⟩ = last n := by ext; simp; omega
_root_.cast (congrArg (fun i => m (α i)) this) (pure x)

/-- Heterogeneous fold over `Fin n` from the left: `foldl 3 f x = f 0 (f 1 (f 2 x))`, where
`f 0 : α 0 → α 1`, `f 1 : α 1 → α 2`, etc.
This is the dependent version of `Fin.foldl`. -/
@[inline] def dfoldl (n : Nat) (α : Fin (n + 1) → Type _)
(f : ∀ (i : Fin n), α i.castSucc → α i.succ) (init : α 0) : α (last n) :=
dfoldlM (m := Id) n α f init
Loading

0 comments on commit d0d659f

Please sign in to comment.