@@ -3,11 +3,10 @@ Copyright (c) 2025 Rémy Degenne. All rights reserved.
33Released under Apache 2.0 license as described in the file LICENSE.
44Authors: Rémy Degenne, Paulo Rauber
55-/
6- import LeanBandits.Bandit.Bandit
76import LeanBandits.SequentialLearning.FiniteActions
87
98/-!
10- # Regret
9+ # Regret, gap, best arm
1110
1211-/
1312
@@ -17,17 +16,12 @@ open scoped ENNReal NNReal
1716
1817namespace Bandits
1918
20- variable {α : Type *} [DecidableEq α] {mα : MeasurableSpace α} {ν : Kernel α ℝ}
21- {h : ℕ → α × ℝ} {m n t : ℕ} {a : α}
19+ variable {α Ω : Type *} [DecidableEq α] {mα : MeasurableSpace α} {mΩ : MeasurableSpace Ω}
20+ {ν : Kernel α ℝ}
21+ {A : ℕ → Ω → α} {R : ℕ → Ω → ℝ}
22+ {ω : Ω} {m n t : ℕ} {a : α}
2223
23- /-! ### Definitions of regret, gaps, pull counts -/
24-
25- /-- Regret of a sequence of pulls `k : ℕ → α` at time `t` for the reward kernel `ν ; Kernel α ℝ`. -/
26- noncomputable
27- def regret (ν : Kernel α ℝ) (t : ℕ) (h : ℕ → α × ℝ) : ℝ :=
28- t * (⨆ a, (ν a)[id]) - ∑ s ∈ range t, (ν (arm s h))[id]
29-
30- /-- Gap of an arm `a`: difference between the highest mean of the arms and the mean of `a`. -/
24+ /-- Gap of an action `a`: difference between the highest mean of the actions and the mean of `a`. -/
3125noncomputable
3226def gap (ν : Kernel α ℝ) (a : α) : ℝ := (⨆ i, (ν i)[id]) - (ν a)[id]
3327
@@ -36,28 +30,35 @@ lemma gap_nonneg [Fintype α] : 0 ≤ gap ν a := by
3630 rw [gap, sub_nonneg]
3731 exact le_ciSup (f := fun i ↦ (ν i)[id]) (by simp) a
3832
39- lemma arm_stepsUntil (hm : m ≠ 0 ) (h_exists : ∃ s, pullCount a (s + 1 ) h = m) :
40- arm (stepsUntil a m h).toNat h = a := by
41- exact action_stepsUntil hm h_exists
33+ /-- Regret of a sequence of pulls `k : ℕ → α` at time `t` for the reward kernel `ν ; Kernel α ℝ`. -/
34+ noncomputable
35+ def regret (ν : Kernel α ℝ) (A : ℕ → Ω → α) (t : ℕ) (ω : Ω) : ℝ :=
36+ t * (⨆ a, (ν a)[id]) - ∑ s ∈ range t, (ν (A s ω))[id]
37+
38+ omit [DecidableEq α] in
39+ lemma regret_eq_sum_gap : regret ν A t ω = ∑ s ∈ range t, gap ν (A s ω) := by
40+ simp [regret, gap]
4241
43- lemma arm_eq_of_stepsUntil_eq_coe {ω : ℕ → α × ℝ} (hm : m ≠ 0 )
44- (h : stepsUntil a m ω = n) :
45- arm n ω = a := by
46- exact action_eq_of_stepsUntil_eq_coe hm h
42+ omit [DecidableEq α] in
43+ lemma regret_nonneg [Fintype α] : 0 ≤ regret ν A t ω := by
44+ rw [regret_eq_sum_gap]
45+ exact sum_nonneg ( fun _ _ ↦ gap_nonneg)
4746
48- section RewardByCount
47+ omit [DecidableEq α] in
48+ lemma gap_eq_zero_of_regret_eq_zero [Fintype α] (hr : regret ν A t ω = 0 ) {s : ℕ} (hs : s < t) :
49+ gap ν (A s ω) = 0 := by
50+ rw [regret_eq_sum_gap] at hr
51+ exact (sum_eq_zero_iff_of_nonneg fun _ _ ↦ gap_nonneg).1 hr s (mem_range.2 hs)
4952
5053lemma regret_eq_sum_pullCount_mul_gap [Fintype α] :
51- regret ν t h = ∑ a, pullCount a t h * gap ν a := by
52- simp [sum_pullCount_mul, regret, gap, sum_sub_distrib, arm, action ]
54+ regret ν A t ω = ∑ a, pullCount A a t ω * gap ν a := by
55+ simp_rw [regret_eq_sum_gap, sum_pullCount_mul ]
5356
54- end RewardByCount
55-
56- section BestArm
57+ section bestArm
5758
5859variable [Fintype α] [Nonempty α]
5960
60- /-- Arm with the highest mean. -/
61+ /-- action with the highest mean. -/
6162noncomputable def bestArm (ν : Kernel α ℝ) : α :=
6263 (exists_max_image univ (fun a ↦ (ν a)[id]) (univ_nonempty_iff.mpr inferInstance)).choose
6364
@@ -78,6 +79,47 @@ omit [DecidableEq α] in
7879lemma gap_bestArm : gap ν (bestArm ν) = 0 := by
7980 rw [gap_eq_bestArm_sub, sub_self]
8081
81- end BestArm
82+ omit [DecidableEq α] in
83+ lemma integral_eq_of_gap_eq_zero (hg : gap ν a = 0 ) : (ν (bestArm ν))[id] = (ν a)[id] := by
84+ rwa [← sub_eq_zero, ← gap_eq_bestArm_sub]
85+
86+ end bestArm
87+
88+ section Asymptotics
89+
90+ omit [DecidableEq α] in
91+ /-- If the regret is sublinear, the average mean reward tends to the highest mean of the arms. -/
92+ lemma avg_mean_reward_tendsto_of_sublinear_regret
93+ (hr : (regret ν A · ω) =o[atTop] fun t ↦ (t : ℝ)) :
94+ Tendsto (fun t ↦ (∑ s ∈ range t, (ν (A s ω))[id]) / (t : ℝ))
95+ atTop (nhds (⨆ a, (ν a)[id])) := by
96+ have ht : Tendsto (fun t ↦ (⨆ a, (ν a)[id]) - regret ν A t ω / t)
97+ atTop (nhds (⨆ a, (ν a)[id])) := by
98+ simpa using tendsto_const_nhds.sub hr.tendsto_div_nhds_zero
99+ apply ht.congr'
100+ filter_upwards [eventually_ne_atTop 0 ] with t ht
101+ rw [regret]
102+ field_simp
103+ ring
104+
105+ /-- If the regret is sublinear, the rate of suboptimal arm pulls tends to zero. -/
106+ lemma pullCount_rate_tendsto_of_sublinear_regret [Fintype α]
107+ (hr : (regret ν A · ω) =o[atTop] fun t ↦ (t : ℝ)) (hg : 0 < gap ν a) :
108+ Tendsto (fun t ↦ (pullCount A a t ω : ℝ) / t) atTop (nhds 0 ) := by
109+ have hb (t : ℕ) : (pullCount A a t ω : ℝ) * gap ν a ≤ regret ν A t ω := by
110+ rw [regret_eq_sum_pullCount_mul_gap]
111+ exact single_le_sum (f := fun a ↦ pullCount A a t ω * gap ν a)
112+ (fun _ _ ↦ mul_nonneg (Nat.cast_nonneg _) gap_nonneg) (mem_univ a)
113+ have hb' (t : ℕ) : (pullCount A a t ω : ℝ) / t ≤ regret ν A t ω / t / gap ν a := by
114+ obtain ht | ht := eq_or_ne t 0
115+ · simp [ht]
116+ · calc (pullCount A a t ω : ℝ) / t
117+ = pullCount A a t ω * gap ν a / gap ν a / t := by field_simp
118+ _ ≤ regret ν A t ω / gap ν a / t := by gcongr; exact hb t
119+ _ = regret ν A t ω / t / gap ν a := by ring
120+ apply squeeze_zero' (Eventually.of_forall fun _ ↦ by positivity) (Eventually.of_forall hb')
121+ simpa using hr.tendsto_div_nhds_zero.div_const (gap ν a)
122+
123+ end Asymptotics
82124
83125end Bandits
0 commit comments