-- Mathlib/.lake/packages/lean4/src/lean/Std/Tactic/BVDecide/LRAT/Internal/Formula/RatAddSound.lean
theorem existsRatHint_of_ratHintsExhaustive {n : Nat} (f : DefaultFormula n)
    (f_readyForRatAdd : ReadyForRatAdd f) (pivot : Literal (PosFin n))
    (ratHints : Array (Nat × Array Nat))
    (ratHintsExhaustive_eq_true : ratHintsExhaustive f pivot ratHints = true) (c' : DefaultClause n)
    (c'_in_f : c' ∈ toList f) (negPivot_in_c' : Literal.negate pivot ∈ Clause.toList c') :
    ∃ i : Fin ratHints.size, f.clauses[ratHints[i].1]! = some c'

Proof state:
case intro.intro
n : Nat
f : DefaultFormula n
f_readyForRatAdd : f.ReadyForRatAdd
pivot : Literal (PosFin n)
ratHints : Array (Nat × Array Nat)
ratHintsExhaustive_eq_true :
  decide
      (Array.filter
          (fun i =>
            match f.clauses[i]! with
            | none => false
            | some c => c.contains pivot.negate)
          (Array.range f.clauses.size) =
        Array.map (fun x => x.fst) ratHints) =
    true
c' : DefaultClause n
negPivot_in_c' : pivot.negate ∈ Clause.toList c'
i : Nat
hi : i < f.clauses.toList.length
c'_in_f : f.clauses.toList[i] = some c'
⊢ ∃ i, f.clauses[ratHints[i].fst]! = some c'

Tactic:
have i_in_bounds : i < Array.size (Array.range (Array.size f.clauses)) := by
  rw [Array.size_range]
  simpa using hi

Result:
case intro.intro
n : Nat
f : DefaultFormula n
f_readyForRatAdd : f.ReadyForRatAdd
pivot : Literal (PosFin n)
ratHints : Array (Nat × Array Nat)
ratHintsExhaustive_eq_true :
  decide
      (Array.filter
          (fun i =>
            match f.clauses[i]! with
            | none => false
            | some c => c.contains pivot.negate)
          (Array.range f.clauses.size) =
        Array.map (fun x => x.fst) ratHints) =
    true
c' : DefaultClause n
negPivot_in_c' : pivot.negate ∈ Clause.toList c'
i : Nat
hi : i < f.clauses.toList.length
c'_in_f : f.clauses.toList[i] = some c'
i_in_bounds : i < (Array.range f.clauses.size).size
⊢ ∃ i, f.clauses[ratHints[i].fst]! = some c'

Proof state:
case left
n : Nat
f : DefaultFormula n
f_readyForRatAdd : f.ReadyForRatAdd
pivot : Literal (PosFin n)
ratHints : Array (Nat × Array Nat)
ratHintsExhaustive_eq_true :
  decide
      (Array.filter
          (fun i =>
            match f.clauses[i]! with
            | none => false
            | some c => c.contains pivot.negate)
          (Array.range f.clauses.size) =
        Array.map (fun x => x.fst) ratHints) =
    true
c' : DefaultClause n
negPivot_in_c' : pivot.negate ∈ Clause.toList c'
i : Nat
hi : i < f.clauses.toList.length
c'_in_f : f.clauses.toList[i] = some c'
i_in_bounds : i < (Array.range f.clauses.size).size
i_lt_f_clauses_size : i < f.clauses.size
i_eq_range_i : i = (Array.range f.clauses.size)[i]
⊢ (Array.range f.clauses.size)[i] ∈ (Array.range f.clauses.size).toList

Tactic:
apply Array.getElem_mem_toList

Result:
no goals

Proof state:
case intro.intro.intro
n : Nat
f : DefaultFormula n
f_readyForRatAdd : f.ReadyForRatAdd
pivot : Literal (PosFin n)
ratHints : Array (Nat × Array Nat)
ratHintsExhaustive_eq_true :
  decide
      (Array.filter
          (fun i =>
            match f.clauses[i]! with
            | none => false
            | some c => c.contains pivot.negate)
          (Array.range f.clauses.size) =
        Array.map (fun x => x.fst) ratHints) =
    true
c' : DefaultClause n
negPivot_in_c' : pivot.negate ∈ Clause.toList c'
i : Nat
hi : i < f.clauses.toList.length
c'_in_f : f.clauses[i] = some c'
i_in_bounds : i < (Array.range f.clauses.size).size
i_lt_f_clauses_size : i < f.clauses.size
h : i ∈ (Array.map (fun x => x.fst) ratHints).toList
j : Fin (Array.map (fun x => x.fst) ratHints).toList.length
j_in_bounds : ↑j < ratHints.size
h' : ratHints[↑j].fst = i
⊢ ∃ i, f.clauses[ratHints[i].fst]! = some c'

Tactic:
exists ⟨j.1, j_in_bounds⟩

Result:
case intro.intro.intro
n : Nat
f : DefaultFormula n
f_readyForRatAdd : f.ReadyForRatAdd
pivot : Literal (PosFin n)
ratHints : Array (Nat × Array Nat)
ratHintsExhaustive_eq_true :
  decide
      (Array.filter
          (fun i =>
            match f.clauses[i]! with
            | none => false
            | some c => c.contains pivot.negate)
          (Array.range f.clauses.size) =
        Array.map (fun x => x.fst) ratHints) =
    true
c' : DefaultClause n
negPivot_in_c' : pivot.negate ∈ Clause.toList c'
i : Nat
hi : i < f.clauses.toList.length
c'_in_f : f.clauses[i] = some c'
i_in_bounds : i < (Array.range f.clauses.size).size
i_lt_f_clauses_size : i < f.clauses.size
h : i ∈ (Array.map (fun x => x.fst) ratHints).toList
j : Fin (Array.map (fun x => x.fst) ratHints).toList.length
j_in_bounds : ↑j < ratHints.size
h' : ratHints[↑j].fst = i
⊢ f.clauses[ratHints[⟨↑j, j_in_bounds⟩].fst]! = some c'

Proof state:
n : Nat
f : DefaultFormula n
f_readyForRatAdd : f.ReadyForRatAdd
pivot : Literal (PosFin n)
ratHints : Array (Nat × Array Nat)
ratHintsExhaustive_eq_true :
  decide
      (Array.filter
          (fun i =>
            match f.clauses[i]! with
            | none => false
            | some c => c.contains pivot.negate)
          (Array.range f.clauses.size) =
        Array.map (fun x => x.fst) ratHints) =
    true
c' : DefaultClause n
negPivot_in_c' : pivot.negate ∈ Clause.toList c'
i : Nat
hi : i < f.clauses.toList.length
c'_in_f : f.clauses.toList[i] = some c'
i_in_bounds : i < (Array.range f.clauses.size).size
i_lt_f_clauses_size : i < f.clauses.size
⊢ i ∈
    (Array.filter
        (fun i =>
          match f.clauses[i]! with
          | none => false
          | some c => c.contains pivot.negate)
        (Array.range f.clauses.size)).toList

Tactic:
have i_eq_range_i : i = (Array.range f.clauses.size)[i]'i_in_bounds := by
  rw [Array.getElem_range]

Result:
n : Nat
f : DefaultFormula n
f_readyForRatAdd : f.ReadyForRatAdd
pivot : Literal (PosFin n)
ratHints : Array (Nat × Array Nat)
ratHintsExhaustive_eq_true :
  decide
      (Array.filter
          (fun i =>
            match f.clauses[i]! with
            | none => false
            | some c => c.contains pivot.negate)
          (Array.range f.clauses.size) =
        Array.map (fun x => x.fst) ratHints) =
    true
c' : DefaultClause n
negPivot_in_c' : pivot.negate ∈ Clause.toList c'
i : Nat
hi : i < f.clauses.toList.length
c'_in_f : f.clauses.toList[i] = some c'
i_in_bounds : i < (Array.range f.clauses.size).size
i_lt_f_clauses_size : i < f.clauses.size
i_eq_range_i : i = (Array.range f.clauses.size)[i]
⊢ i ∈
    (Array.filter
        (fun i =>
          match f.clauses[i]! with
          | none => false
          | some c => c.contains pivot.negate)
        (Array.range f.clauses.size)).toList

Proof state:
n : Nat
f : DefaultFormula n
f_readyForRatAdd : f.ReadyForRatAdd
pivot : Literal (PosFin n)
ratHints : Array (Nat × Array Nat)
ratHintsExhaustive_eq_true :
  decide
      (Array.filter
          (fun i =>
            match f.clauses[i]! with
            | none => false
            | some c => c.contains pivot.negate)
          (Array.range f.clauses.size) =
        Array.map (fun x => x.fst) ratHints) =
    true
c' : DefaultClause n
negPivot_in_c' : pivot.negate ∈ Clause.toList c'
i : Nat
hi : i < f.clauses.toList.length
c'_in_f : f.clauses.toList[i] = some c'
i_in_bounds : i < (Array.range f.clauses.size).size
i_lt_f_clauses_size : i < f.clauses.size
⊢ i = (Array.range f.clauses.size)[i]

Tactic:
rw [Array.getElem_range]

Result:
no goals