← Visual paper

HardnessBilevel/Hardness/Reduction.lean

d1032f4c70da9b037605c2f444ce2450900e5a76 · GitHub

  1. import HardnessBilevel.Hardness.Analysis
  2. /-!
  3. # The reduction SSI → bilevel instances (blueprint §4.I.1, §4.I.2: `s3.reduce_correct`,
  4. `s3.degree`, `s3.integer_coeff`)
  5. `BilevelInstance` is the instance type of Theorem 3.2: integer polynomials `P Q` of total degree
  6. `≤ 5` in `n` upper and `m` lower variables, a bounded box `∏ [lo i, hi i]` with integer endpoints,
  7. and an integer threshold `c`. The real evaluation of `P, Q` is `MvPolynomial.aeval (Sum.elim x y)`
  8. (the same encoding as in `Hardness/Construction.lean`). `Yes` means `optVal < c` (cast through `ℝ`).
  9. `reduce` maps an SSI instance to `(n, m, P, Q, lo, hi, c) = (r, k+1, Pp, Qp, 0, 1, 0)`;
  10. `reduce_correct : (reduce I).Yes ↔ I.Yes`. Σ₂ᵖ-hardness itself (`s3.thm32`) is not formalized
  11. (no complexity theory in Mathlib). `s3.integer_coeff` holds by construction (`Pp Qp` are
  12. `MvPolynomial _ ℤ`). The optional `s3.coeff_bound` is not formalized.
  13. -/
  14. namespace Bilevel
  15. open MvPolynomial
  16. /-! ### s3.degree -/
  17. namespace SSI
  18. section degree
  19. variable {σ : Type*}
  20. private theorem td_add {a b : MvPolynomial σ ℤ} {n : ℕ} (ha : a.totalDegree ≤ n)
  21. (hb : b.totalDegree ≤ n) : (a + b).totalDegree ≤ n :=
  22. (totalDegree_add a b).trans (max_le ha hb)
  23. private theorem td_sub {a b : MvPolynomial σ ℤ} {n : ℕ} (ha : a.totalDegree ≤ n)
  24. (hb : b.totalDegree ≤ n) : (a - b).totalDegree ≤ n :=
  25. (totalDegree_sub a b).trans (max_le ha hb)
  26. private theorem td_mul {a b : MvPolynomial σ ℤ} {n m : ℕ} (ha : a.totalDegree ≤ n)
  27. (hb : b.totalDegree ≤ m) : (a * b).totalDegree ≤ n + m :=
  28. (totalDegree_mul a b).trans (Nat.add_le_add ha hb)
  29. private theorem td_sq {a : MvPolynomial σ ℤ} {n : ℕ} (ha : a.totalDegree ≤ n) :
  30. (a ^ 2).totalDegree ≤ 2 * n :=
  31. (totalDegree_pow a 2).trans (Nat.mul_le_mul_left 2 ha)
  32. private theorem td_sum {ι : Type*} (s : Finset ι) {f : ι → MvPolynomial σ ℤ} {n : ℕ}
  33. (hf : ∀ i, (f i).totalDegree ≤ n) : (∑ i ∈ s, f i).totalDegree ≤ n :=
  34. (totalDegree_finsetSum s f).trans (Finset.sup_le fun i _ => hf i)
  35. private theorem td_C (c : ℤ) {n : ℕ} : (C c : MvPolynomial σ ℤ).totalDegree ≤ n := by
  36. rw [totalDegree_C]; exact Nat.zero_le _
  37. private theorem td_one {n : ℕ} : (1 : MvPolynomial σ ℤ).totalDegree ≤ n := by
  38. rw [totalDegree_one]; exact Nat.zero_le _
  39. private theorem td_X (s : σ) : (X s : MvPolynomial σ ℤ).totalDegree ≤ 1 := by
  40. rw [totalDegree_X]
  41. theorem totalDegree_Fp (I : SSI) : I.Fp.totalDegree ≤ 1 :=
  42. td_add (td_C _) (td_sum _ fun _ => (td_mul (n := 0) (td_C _) (td_X _)).trans_eq (zero_add 1))
  43. theorem totalDegree_Gp (I : SSI) : I.Gp.totalDegree ≤ 1 :=
  44. td_sum _ fun _ => td_mul (m := 0) (td_X _) (td_C _)
  45. theorem totalDegree_Hp (I : SSI) : I.Hp.totalDegree ≤ 4 :=
  46. td_add (td_sum _ fun i => td_sq (td_mul (td_X _) (td_sub td_one (td_X _))))
  47. ((td_sq (td_sub I.totalDegree_Fp I.totalDegree_Gp)).trans (by norm_num))
  48. theorem totalDegree_Lp (I : SSI) : I.Lp.totalDegree ≤ 5 := by
  49. have h1 : ((X (Sum.inr 0) - 1 : MvPolynomial I.Var ℤ) ^ 2).totalDegree ≤ 4 :=
  50. (td_sq (td_sub (td_X _) td_one)).trans (by norm_num)
  51. have h2 := td_sum (Finset.univ : Finset (Fin I.r))
  52. (f := fun j => ((1 - X (Sum.inl j) : MvPolynomial I.Var ℤ) * X (Sum.inl j)) ^ 2)
  53. fun j => td_sq (td_mul (td_sub td_one (td_X _)) (td_X _))
  54. exact td_mul (td_X _) (td_add h1 h2)
  55. /-- `s3.degree`: `deg Q ≤ 5`. (Only `≤`; `= 5` is false for `r = 0`, blueprint E-28.) -/
  56. theorem totalDegree_Qp (I : SSI) : I.Qp.totalDegree ≤ 5 :=
  57. td_add I.totalDegree_Lp (I.totalDegree_Hp.trans (by norm_num))
  58. /-- `s3.degree`: `deg P ≤ 5`. (Only `≤`; `= 5` is false for `k = 0`, blueprint E-28.) -/
  59. theorem totalDegree_Pp (I : SSI) : I.Pp.totalDegree ≤ 5 :=
  60. td_sub td_one (td_mul (td_X _) (td_add I.totalDegree_Hp td_one))
  61. end degree
  62. end SSI
  63. /-! ### The instance type of Theorem 3.2 -/
  64. /-- An instance of the decision problem of Theorem 3.2 (`BILEVEL₅`). -/
  65. structure BilevelInstance where
  66. /-- number of upper-level variables -/
  67. n : ℕ
  68. /-- number of lower-level variables -/
  69. m : ℕ
  70. /-- upper-level objective -/
  71. P : MvPolynomial (Fin n ⊕ Fin m) ℤ
  72. /-- lower-level objective -/
  73. Q : MvPolynomial (Fin n ⊕ Fin m) ℤ
  74. degP : P.totalDegree ≤ 5
  75. degQ : Q.totalDegree ≤ 5
  76. /-- lower box endpoints (`lo i > hi i` gives an empty box: harmless) -/
  77. lo : Fin m → ℤ
  78. /-- upper box endpoints -/
  79. hi : Fin m → ℤ
  80. /-- threshold -/
  81. c : ℤ
  82. namespace BilevelInstance
  83. variable (I : BilevelInstance)
  84. /-- The bounded box `∏ [lo i, hi i]`. -/
  85. def box : Set (Fin I.m → ℝ) :=
  86. Set.pi Set.univ fun i => Set.Icc ((I.lo i : ℤ) : ℝ) ((I.hi i : ℤ) : ℝ)
  87. /-- Real evaluation of `P`. -/
  88. noncomputable def Pfun (x : Fin I.n → ℝ) (y : Fin I.m → ℝ) : ℝ := aeval (Sum.elim x y) I.P
  89. /-- Real evaluation of `Q`. -/
  90. noncomputable def Qfun (x : Fin I.n → ℝ) (y : Fin I.m → ℝ) : ℝ := aeval (Sum.elim x y) I.Q
  91. /-- Optimal value of the optimistic bilevel problem (upper-level set `ℝⁿ`). -/
  92. noncomputable def optVal : EReal := ⨅ x : Fin I.n → ℝ, valueFun I.Pfun I.Qfun I.box x
  93. /-- YES-instance: optimal value strictly below `c` (cast `ℤ → ℝ → EReal`). -/
  94. def Yes : Prop := I.optVal < ((I.c : ℝ) : EReal)
  95. theorem isPolyFun_Pfun : IsPolyFun I.Pfun :=
  96. ⟨map (algebraMap ℤ ℝ) I.P, fun _ _ => SSI.aeval_eq_eval_map _ _⟩
  97. theorem isPolyFun_Qfun : IsPolyFun I.Qfun :=
  98. ⟨map (algebraMap ℤ ℝ) I.Q, fun _ _ => SSI.aeval_eq_eval_map _ _⟩
  99. end BilevelInstance
  100. /-- The reduction of Lemma 3.3: `(n, m, P, Q, lo, hi, c) = (r, k+1, Pp, Qp, 0, 1, 0)`. -/
  101. noncomputable def reduce (I : SSI) : BilevelInstance where
  102. n := I.r
  103. m := I.k + 1
  104. P := I.Pp
  105. Q := I.Qp
  106. degP := I.totalDegree_Pp
  107. degQ := I.totalDegree_Qp
  108. lo := fun _ => 0
  109. hi := fun _ => 1
  110. c := 0
  111. theorem reduce_box (I : SSI) : (reduce I).box = I.box := by
  112. simp [BilevelInstance.box, reduce, SSI.box]
  113. theorem reduce_optVal (I : SSI) : (reduce I).optVal = optVal I.Pfun I.Qfun I.box := by
  114. have hP : (reduce I).Pfun = I.Pfun := by
  115. funext x y; exact (I.Pfun_eq_aeval x y).symm
  116. have hQ : (reduce I).Qfun = I.Qfun := by
  117. funext x y; exact (I.Qfun_eq_aeval x y).symm
  118. unfold BilevelInstance.optVal optVal
  119. rw [hP, hQ, reduce_box]
  120. rfl
  121. /-- `s3.reduce_correct` -/
  122. theorem reduce_correct (I : SSI) : (reduce I).Yes ↔ I.Yes := by
  123. rw [BilevelInstance.Yes, reduce_optVal, ← SSI.lemma33]
  124. simp [reduce]
  125. end Bilevel