Skip to content

Commit

Permalink
Trigger CI for leanprover/lean4#6261
Browse files Browse the repository at this point in the history
  • Loading branch information
leanprover-community-mathlib4-bot committed Jan 21, 2025
2 parents 802b4af + 157552e commit ca1e7b1
Show file tree
Hide file tree
Showing 52 changed files with 1,498 additions and 608 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.ref }}
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
4 changes: 3 additions & 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 All @@ -40,6 +40,8 @@ jobs:
- name: Release Docs
uses: softprops/action-gh-release@v2
with:
prerelease: ${{ contains(github.ref, 'rc') }}
make_latest: ${{ !contains(github.ref, 'rc') }}
files: |
docs/docs-${{ github.ref_name }}.tar.gz
docs/docs-${{ github.ref_name }}.zip
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.')
4 changes: 3 additions & 1 deletion 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,13 +89,13 @@ 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
import Batteries.Tactic.SqueezeScope
import Batteries.Tactic.Trans
import Batteries.Tactic.Unreachable
import Batteries.Tactic.Where
import Batteries.Util.Cache
import Batteries.Util.ExtendedBinder
import Batteries.Util.LibraryNote
Expand Down
18 changes: 2 additions & 16 deletions Batteries/Data/Array/Basic.lean
Original file line number Diff line number Diff line change
Expand Up @@ -137,23 +137,9 @@ This will perform the update destructively provided that `a` has a reference cou
abbrev setN (a : Array α) (i : Nat) (x : α) (h : i < a.size := by get_elem_tactic) : Array α :=
a.set i x

/--
`swapN a i j hi hj` swaps two `Nat` indexed entries in an `Array α`.
Uses `get_elem_tactic` to supply a proof that the indices are in range.
`hi` and `hj` are both given a default argument `by get_elem_tactic`.
This will perform the update destructively provided that `a` has a reference count of 1 when called.
-/
abbrev swapN (a : Array α) (i j : Nat)
(hi : i < a.size := by get_elem_tactic) (hj : j < a.size := by get_elem_tactic) : Array α :=
Array.swap a ⟨i,hi⟩ ⟨j, hj⟩
@[deprecated (since := "2024-11-24")] alias swapN := swap

/--
`swapAtN a i h x` swaps the entry with index `i : Nat` in the vector for a new entry `x`.
The old entry is returned alongwith the modified vector.
Automatically generates proof of `i < a.size` with `get_elem_tactic` where feasible.
-/
abbrev swapAtN (a : Array α) (i : Nat) (x : α) (h : i < a.size := by get_elem_tactic) :
α × Array α := swapAt a ⟨i,h⟩ x
@[deprecated (since := "2024-11-24")] alias swapAtN := swapAt

@[deprecated (since := "2024-11-20")] alias eraseIdxN := eraseIdx

Expand Down
8 changes: 2 additions & 6 deletions Batteries/Data/Array/Lemmas.lean
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
Authors: Mario Carneiro, Gabriel Ebner
-/
import Batteries.Data.List.Lemmas
import Batteries.Data.List.FinRange
import Batteries.Data.Array.Basic
import Batteries.Tactic.SeqFocus
import Batteries.Util.ProofWanted
Expand Down Expand Up @@ -56,7 +57,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 @@ -81,11 +82,6 @@ theorem size_set! (a : Array α) (i v) : (a.set! i v).size = a.size := by simp

/-! ### map -/

theorem mapM_empty [Monad m] (f : α → m β) : mapM f #[] = pure #[] := by
rw [mapM, mapM.map]; rfl

theorem map_empty (f : α → β) : map f #[] = #[] := mapM_empty f

/-! ### mem -/

theorem mem_singleton : a ∈ #[b] ↔ a = b := by simp
Expand Down
19 changes: 10 additions & 9 deletions Batteries/Data/Array/Monadic.lean
Original file line number Diff line number Diff line change
Expand Up @@ -125,32 +125,33 @@ 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])
(as.mapIdxM f) :=
Expand Down
10 changes: 5 additions & 5 deletions Batteries/Data/BinaryHeap.lean
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ def heapifyUp (lt : α → α → Bool) (a : Vector α sz) (i : Fin sz) :
match i with
| ⟨0, _⟩ => a
| ⟨i'+1, hi⟩ =>
let j := i'/2, by get_elem_tactic⟩
let j := i'/2
if lt a[j] a[i] then
heapifyUp lt (a.swap i j) j
heapifyUp lt (a.swap i j) ⟨j, by get_elem_tactic⟩
else a

/-- `O(1)`. Build a new empty heap. -/
Expand Down Expand Up @@ -107,7 +107,7 @@ def popMax (self : BinaryHeap α lt) : BinaryHeap α lt :=
if h0 : self.size = 0 then self else
have hs : self.size - 1 < self.size := Nat.pred_lt h0
have h0 : 0 < self.size := Nat.zero_lt_of_ne_zero h0
let v := self.vector.swap ⟨_, h0⟩ ⟨_, hs⟩ |>.pop
let v := self.vector.swap _ _ h0 hs |>.pop
if h : 0 < self.size - 1 then
⟨heapifyDown lt v ⟨0, h⟩ |>.toArray⟩
else
Expand Down Expand Up @@ -136,7 +136,7 @@ def insertExtractMax (self : BinaryHeap α lt) (x : α) : α × BinaryHeap α lt
| none => (x, self)
| some m =>
if lt x m then
let v := self.vector.set 0, size_pos_of_max e⟩ x
let v := self.vector.set 0 x (size_pos_of_max e)
(m, ⟨heapifyDown lt v ⟨0, size_pos_of_max e⟩ |>.toArray⟩)
else (x, self)

Expand All @@ -145,7 +145,7 @@ def replaceMax (self : BinaryHeap α lt) (x : α) : Option α × BinaryHeap α l
match e : self.max with
| none => (none, ⟨self.vector.push x |>.toArray⟩)
| some m =>
let v := self.vector.set 0, size_pos_of_max e⟩ x
let v := self.vector.set 0 x (size_pos_of_max e)
(some m, ⟨heapifyDown lt v ⟨0, size_pos_of_max e⟩ |>.toArray⟩)

/-- `O(log n)`. Replace the value at index `i` by `x`. Assumes that `x ≤ self.get i`. -/
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
2 changes: 2 additions & 0 deletions Batteries/Data/Fin.lean
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
import Batteries.Data.Fin.Basic
import Batteries.Data.Fin.Fold
import Batteries.Data.Fin.Lemmas
import Batteries.Data.Fin.OfBits
9 changes: 6 additions & 3 deletions Batteries/Data/Fin/Basic.lean
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
/-
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
import Batteries.Data.List.Basic

namespace Fin

/-- `min n m` as an element of `Fin (m + 1)` -/
def clamp (n m : Nat) : Fin (m + 1) := ⟨min n m, Nat.lt_succ_of_le (Nat.min_le_right ..)⟩

/-- `enum n` is the array of all elements of `Fin n` in order -/
def enum (n) : Array (Fin n) := Array.ofFn id
@[deprecated (since := "2024-11-15")]
alias enum := Array.finRange

/-- `list n` is the list of all elements of `Fin n` in order -/
def list (n) : List (Fin n) := (enum n).toList
Loading

0 comments on commit ca1e7b1

Please sign in to comment.