File: Mathlib/LinearAlgebra/Lagrange.lean

full_name: Polynomial.eq_zero_of_degree_lt_of_eval_finset_eq_zero
code: theorem eq_zero_of_degree_lt_of_eval_finset_eq_zero (degree_f_lt : f.degree < s.card)
    (eval_f : ∀ x ∈ s, f.eval x = 0) : f = 0 
goal: f = 0

full_name: Polynomial.eq_of_degree_sub_lt_of_eval_finset_eq
code: theorem eq_of_degree_sub_lt_of_eval_finset_eq (degree_fg_lt : (f - g).degree < s.card)
    (eval_fg : ∀ x ∈ s, f.eval x = g.eval x) : f = g 
goal: f = g

full_name: Polynomial.eq_of_degrees_lt_of_eval_finset_eq
code: theorem eq_of_degrees_lt_of_eval_finset_eq (degree_f_lt : f.degree < s.card)
    (degree_g_lt : g.degree < s.card) (eval_fg : ∀ x ∈ s, f.eval x = g.eval x) : f = g 
goal: f = g

full_name: Polynomial.eq_of_degree_le_of_eval_finset_eq
code: /--
Two polynomials, with the same degree and leading coefficient, which have the same evaluation
on a set of distinct values with cardinality equal to the degree, are equal.
-/
theorem eq_of_degree_le_of_eval_finset_eq
    (h_deg_le : f.degree ≤ s.card)
    (h_deg_eq : f.degree = g.degree)
    (hlc : f.leadingCoeff = g.leadingCoeff)
    (h_eval : ∀ x ∈ s, f.eval x = g.eval x) :
    f = g 
goal: f = g

full_name: Polynomial.eq_zero_of_degree_lt_of_eval_index_eq_zero
code: theorem eq_zero_of_degree_lt_of_eval_index_eq_zero (hvs : Set.InjOn v s)
    (degree_f_lt : f.degree < s.card) (eval_f : ∀ i ∈ s, f.eval (v i) = 0) : f = 0 
goal: f = 0

full_name: Polynomial.eq_of_degree_sub_lt_of_eval_index_eq
code: theorem eq_of_degree_sub_lt_of_eval_index_eq (hvs : Set.InjOn v s)
    (degree_fg_lt : (f - g).degree < s.card) (eval_fg : ∀ i ∈ s, f.eval (v i) = g.eval (v i)) :
    f = g 
goal: f = g

full_name: Polynomial.eq_of_degrees_lt_of_eval_index_eq
code: theorem eq_of_degrees_lt_of_eval_index_eq (hvs : Set.InjOn v s) (degree_f_lt : f.degree < s.card)
    (degree_g_lt : g.degree < s.card) (eval_fg : ∀ i ∈ s, f.eval (v i) = g.eval (v i)) : f = g 
goal: f = g

full_name: Polynomial.eq_of_degree_le_of_eval_index_eq
code: theorem eq_of_degree_le_of_eval_index_eq (hvs : Set.InjOn v s)
    (h_deg_le : f.degree ≤ s.card)
    (h_deg_eq : f.degree = g.degree)
    (hlc : f.leadingCoeff = g.leadingCoeff)
    (h_eval : ∀ i ∈ s, f.eval (v i) = g.eval (v i)) : f = g 
goal: f = g

full_name: Lagrange.basisDivisor
code: /-- `basisDivisor x y` is the unique linear or constant polynomial such that
when evaluated at `x` it gives `1` and `y` it gives `0` (where when `x = y` it is identically `0`).
Such polynomials are the building blocks for the Lagrange interpolants. -/
def basisDivisor (x y : F) : F[X] 
goal: F[X]

full_name: Lagrange.basisDivisor_self
code: theorem basisDivisor_self : basisDivisor x x = 0 
goal: Lagrange.basisDivisor x x = 0

full_name: Lagrange.basisDivisor_inj
code: theorem basisDivisor_inj (hxy : basisDivisor x y = 0) : x = y 
goal: x = y

full_name: Lagrange.basisDivisor_eq_zero_iff
code: @[simp]
theorem basisDivisor_eq_zero_iff : basisDivisor x y = 0 ↔ x = y 
goal: Lagrange.basisDivisor x y = 0 ↔ x = y

full_name: Lagrange.basisDivisor_ne_zero_iff
code: theorem basisDivisor_ne_zero_iff : basisDivisor x y ≠ 0 ↔ x ≠ y 
goal: Lagrange.basisDivisor x y ≠ 0 ↔ x ≠ y

full_name: Lagrange.degree_basisDivisor_of_ne
code: theorem degree_basisDivisor_of_ne (hxy : x ≠ y) : (basisDivisor x y).degree = 1 
goal: (Lagrange.basisDivisor x y).degree = 1

full_name: Lagrange.degree_basisDivisor_self
code: @[simp]
theorem degree_basisDivisor_self : (basisDivisor x x).degree = ⊥ 
goal: (Lagrange.basisDivisor x x).degree = ⊥

full_name: Lagrange.natDegree_basisDivisor_self
code: theorem natDegree_basisDivisor_self : (basisDivisor x x).natDegree = 0 
goal: (Lagrange.basisDivisor x x).natDegree = 0

full_name: Lagrange.natDegree_basisDivisor_of_ne
code: theorem natDegree_basisDivisor_of_ne (hxy : x ≠ y) : (basisDivisor x y).natDegree = 1 
goal: (Lagrange.basisDivisor x y).natDegree = 1

full_name: Lagrange.eval_basisDivisor_right
code: @[simp]
theorem eval_basisDivisor_right : eval y (basisDivisor x y) = 0 
goal: Polynomial.eval y (Lagrange.basisDivisor x y) = 0

full_name: Lagrange.eval_basisDivisor_left_of_ne
code: theorem eval_basisDivisor_left_of_ne (hxy : x ≠ y) : eval x (basisDivisor x y) = 1 
goal: Polynomial.eval x (Lagrange.basisDivisor x y) = 1

full_name: Lagrange.basis
code: /-- Lagrange basis polynomials indexed by `s : Finset ι`, defined at nodes `v i` for a
map `v : ι → F`. For `i, j ∈ s`, `basis s v i` evaluates to 0 at `v j` for `i ≠ j`. When
`v` is injective on `s`, `basis s v i` evaluates to 1 at `v i`. -/
protected def basis (s : Finset ι) (v : ι → F) (i : ι) : F[X] 
goal: F[X]

full_name: Lagrange.basis_empty
code: @[simp]
theorem basis_empty : Lagrange.basis ∅ v i = 1 
goal: Lagrange.basis ∅ v i = 1

full_name: Lagrange.basis_singleton
code: @[simp]
theorem basis_singleton (i : ι) : Lagrange.basis {i} v i = 1 
goal: Lagrange.basis {i} v i = 1

full_name: Lagrange.basis_pair_left
code: @[simp]
theorem basis_pair_left (hij : i ≠ j) : Lagrange.basis {i, j} v i = basisDivisor (v i) (v j) 
goal: Lagrange.basis {i, j} v i = Lagrange.basisDivisor (v i) (v j)

full_name: Lagrange.basis_pair_right
code: @[simp]
theorem basis_pair_right (hij : i ≠ j) : Lagrange.basis {i, j} v j = basisDivisor (v j) (v i) 
goal: Lagrange.basis {i, j} v j = Lagrange.basisDivisor (v j) (v i)

full_name: Lagrange.basis_ne_zero
code: theorem basis_ne_zero (hvs : Set.InjOn v s) (hi : i ∈ s) : Lagrange.basis s v i ≠ 0 
goal: Lagrange.basis s v i ≠ 0

full_name: Lagrange.eval_basis_self
code: @[simp]
theorem eval_basis_self (hvs : Set.InjOn v s) (hi : i ∈ s) :
    (Lagrange.basis s v i).eval (v i) = 1 
goal: Polynomial.eval (v i) (Lagrange.basis s v i) = 1

full_name: Lagrange.eval_basis_of_ne
code: @[simp]
theorem eval_basis_of_ne (hij : i ≠ j) (hj : j ∈ s) : (Lagrange.basis s v i).eval (v j) = 0 
goal: Polynomial.eval (v j) (Lagrange.basis s v i) = 0

full_name: Lagrange.natDegree_basis
code: @[simp]
theorem natDegree_basis (hvs : Set.InjOn v s) (hi : i ∈ s) :
    (Lagrange.basis s v i).natDegree = s.card - 1 
goal: (Lagrange.basis s v i).natDegree = s.card - 1

full_name: Lagrange.degree_basis
code: theorem degree_basis (hvs : Set.InjOn v s) (hi : i ∈ s) :
    (Lagrange.basis s v i).degree = ↑(s.card - 1) 
goal: (Lagrange.basis s v i).degree = ↑(s.card - 1)

full_name: Lagrange.sum_basis
code: theorem sum_basis (hvs : Set.InjOn v s) (hs : s.Nonempty) :
    ∑ j ∈ s, Lagrange.basis s v j = 1 
goal: ∑ j ∈ s, Lagrange.basis s v j = 1

full_name: Lagrange.basisDivisor_add_symm
code: theorem basisDivisor_add_symm {x y : F} (hxy : x ≠ y) :
    basisDivisor x y + basisDivisor y x = 1 
goal: Lagrange.basisDivisor x y + Lagrange.basisDivisor y x = 1

full_name: Lagrange.interpolate
code: /-- Lagrange interpolation: given a finset `s : Finset ι`, a nodal map `v : ι → F` injective on
`s` and a value function `r : ι → F`, `interpolate s v r` is the unique
polynomial of degree `< s.card` that takes value `r i` on `v i` for all `i` in `s`. -/
@[simps]
def interpolate (s : Finset ι) (v : ι → F) : (ι → F) →ₗ[F] F[X] 
goal: (ι → F) →ₗ[F] F[X]

full_name: Lagrange.interpolate_apply
code: /-- Lagrange interpolation: given a finset `s : Finset ι`, a nodal map `v : ι → F` injective on
`s` and a value function `r : ι → F`, `interpolate s v r` is the unique
polynomial of degree `< s.card` that takes value `r i` on `v i` for all `i` in `s`. -/
@[simps]
def interpolate (s : Finset ι) (v : ι → F) : (ι → F) →ₗ[F] F[X] 
goal: (Lagrange.interpolate s v) r = ∑ i ∈ s, Polynomial.C (r i) * Lagrange.basis s v i

full_name: Lagrange.interpolate_empty
code: theorem interpolate_empty : interpolate ∅ v r = 0 
goal: (Lagrange.interpolate ∅ v) r = 0

full_name: Lagrange.interpolate_singleton
code: theorem interpolate_singleton : interpolate {i} v r = C (r i) 
goal: (Lagrange.interpolate {i} v) r = Polynomial.C (r i)

full_name: Lagrange.interpolate_one
code: theorem interpolate_one (hvs : Set.InjOn v s) (hs : s.Nonempty) : interpolate s v 1 = 1 
goal: (Lagrange.interpolate s v) 1 = 1

full_name: Lagrange.eval_interpolate_at_node
code: theorem eval_interpolate_at_node (hvs : Set.InjOn v s) (hi : i ∈ s) :
    eval (v i) (interpolate s v r) = r i 
goal: Polynomial.eval (v i) ((Lagrange.interpolate s v) r) = r i

full_name: Lagrange.degree_interpolate_le
code: theorem degree_interpolate_le (hvs : Set.InjOn v s) :
    (interpolate s v r).degree ≤ ↑(s.card - 1) 
goal: ((Lagrange.interpolate s v) r).degree ≤ ↑(s.card - 1)

full_name: Lagrange.degree_interpolate_lt
code: theorem degree_interpolate_lt (hvs : Set.InjOn v s) : (interpolate s v r).degree < s.card 
goal: ((Lagrange.interpolate s v) r).degree < ↑s.card

full_name: Lagrange.degree_interpolate_erase_lt
code: theorem degree_interpolate_erase_lt (hvs : Set.InjOn v s) (hi : i ∈ s) :
    (interpolate (s.erase i) v r).degree < ↑(s.card - 1) 
goal: ((Lagrange.interpolate (s.erase i) v) r).degree < ↑(s.card - 1)

full_name: Lagrange.values_eq_on_of_interpolate_eq
code: theorem values_eq_on_of_interpolate_eq (hvs : Set.InjOn v s)
    (hrr' : interpolate s v r = interpolate s v r') : ∀ i ∈ s, r i = r' i 
goal: i ∈ s → r i = r' i

full_name: Lagrange.interpolate_eq_of_values_eq_on
code: theorem interpolate_eq_of_values_eq_on (hrr' : ∀ i ∈ s, r i = r' i) :
    interpolate s v r = interpolate s v r' 
goal: (Lagrange.interpolate s v) r = (Lagrange.interpolate s v) r'

full_name: Lagrange.interpolate_eq_iff_values_eq_on
code: theorem interpolate_eq_iff_values_eq_on (hvs : Set.InjOn v s) :
    interpolate s v r = interpolate s v r' ↔ ∀ i ∈ s, r i = r' i 
goal: (Lagrange.interpolate s v) r = (Lagrange.interpolate s v) r' ↔ ∀ i ∈ s, r i = r' i

full_name: Lagrange.eq_interpolate
code: theorem eq_interpolate {f : F[X]} (hvs : Set.InjOn v s) (degree_f_lt : f.degree < s.card) :
    f = interpolate s v fun i => f.eval (v i) 
goal: f = (Lagrange.interpolate s v) fun i => Polynomial.eval (v i) f

full_name: Lagrange.eq_interpolate_of_eval_eq
code: theorem eq_interpolate_of_eval_eq {f : F[X]} (hvs : Set.InjOn v s) (degree_f_lt : f.degree < s.card)
    (eval_f : ∀ i ∈ s, f.eval (v i) = r i) : f = interpolate s v r 
goal: f = (Lagrange.interpolate s v) r

full_name: Lagrange.eq_interpolate_iff
code: /-- This is the characteristic property of the interpolation: the interpolation is the
unique polynomial of `degree < Fintype.card ι` which takes the value of the `r i` on the `v i`.
-/
theorem eq_interpolate_iff {f : F[X]} (hvs : Set.InjOn v s) :
    (f.degree < s.card ∧ ∀ i ∈ s, eval (v i) f = r i) ↔ f = interpolate s v r 
goal: (f.degree < ↑s.card ∧ ∀ i ∈ s, Polynomial.eval (v i) f = r i) ↔ f = (Lagrange.interpolate s v) r

full_name: Lagrange.funEquivDegreeLT
code: /-- Lagrange interpolation induces isomorphism between functions from `s`
and polynomials of degree less than `Fintype.card ι`. -/
def funEquivDegreeLT (hvs : Set.InjOn v s) : degreeLT F s.card ≃ₗ[F] s → F 
goal: ↥(Polynomial.degreeLT F s.card) ≃ₗ[F] { x // x ∈ s } → F

full_name: Lagrange.interpolate_eq_sum_interpolate_insert_sdiff
code: theorem interpolate_eq_sum_interpolate_insert_sdiff (hvt : Set.InjOn v t) (hs : s.Nonempty)
    (hst : s ⊆ t) :
    interpolate t v r = ∑ i ∈ s, interpolate (insert i (t \ s)) v r * Lagrange.basis s v i 
goal: (Lagrange.interpolate t v) r = ∑ i ∈ s, (Lagrange.interpolate (insert i (t \ s)) v) r * Lagrange.basis s v i

full_name: Lagrange.interpolate_eq_add_interpolate_erase
code: theorem interpolate_eq_add_interpolate_erase (hvs : Set.InjOn v s) (hi : i ∈ s) (hj : j ∈ s)
    (hij : i ≠ j) :
    interpolate s v r =
      interpolate (s.erase j) v r * basisDivisor (v i) (v j) +
        interpolate (s.erase i) v r * basisDivisor (v j) (v i) 
goal: (Lagrange.interpolate s v) r =
  (Lagrange.interpolate (s.erase j) v) r * Lagrange.basisDivisor (v i) (v j) +
    (Lagrange.interpolate (s.erase i) v) r * Lagrange.basisDivisor (v j) (v i)

full_name: Lagrange.nodal
code: /-- `nodal s v` is the unique monic polynomial whose roots are the nodes defined by `v` and `s`.

That is, the roots of `nodal s v` are exactly the image of `v` on `s`,
with appropriate multiplicity.

We can use `nodal` to define the barycentric forms of the evaluated interpolant.
-/

def nodal (s : Finset ι) (v : ι → R) : R[X] 
goal: R[X]

full_name: Lagrange.nodal_eq
code: theorem nodal_eq (s : Finset ι) (v : ι → R) : nodal s v = ∏ i ∈ s, (X - C (v i)) 
goal: Lagrange.nodal s v = ∏ i ∈ s, (Polynomial.X - Polynomial.C (v i))

full_name: Lagrange.nodal_empty
code: @[simp]
theorem nodal_empty : nodal ∅ v = 1 
goal: Lagrange.nodal ∅ v = 1

full_name: Lagrange.natDegree_nodal
code: @[simp]
theorem natDegree_nodal [Nontrivial R] : (nodal s v).natDegree = s.card 
goal: (Lagrange.nodal s v).natDegree = s.card

full_name: Lagrange.nodal_ne_zero
code: theorem nodal_ne_zero [Nontrivial R] : nodal s v ≠ 0 
goal: Lagrange.nodal s v ≠ 0

full_name: Lagrange.degree_nodal
code: @[simp]
theorem degree_nodal [Nontrivial R] : (nodal s v).degree = s.card 
goal: (Lagrange.nodal s v).degree = ↑s.card

full_name: Lagrange.nodal_monic
code: theorem nodal_monic : (nodal s v).Monic 
goal: (Lagrange.nodal s v).Monic

full_name: Lagrange.eval_nodal
code: theorem eval_nodal {x : R} : (nodal s v).eval x = ∏ i ∈ s, (x - v i) 
goal: Polynomial.eval x (Lagrange.nodal s v) = ∏ i ∈ s, (x - v i)

full_name: Lagrange.eval_nodal_at_node
code: theorem eval_nodal_at_node {i : ι} (hi : i ∈ s) : eval (v i) (nodal s v) = 0 
goal: Polynomial.eval (v i) (Lagrange.nodal s v) = 0

full_name: Lagrange.eval_nodal_not_at_node
code: theorem eval_nodal_not_at_node [Nontrivial R] [NoZeroDivisors R] {x : R}
    (hx : ∀ i ∈ s, x ≠ v i) : eval x (nodal s v) ≠ 0 
goal: Polynomial.eval x (Lagrange.nodal s v) ≠ 0

full_name: Lagrange.nodal_eq_mul_nodal_erase
code: theorem nodal_eq_mul_nodal_erase [DecidableEq ι] {i : ι} (hi : i ∈ s) :
    nodal s v = (X - C (v i)) * nodal (s.erase i) v 
goal: Lagrange.nodal s v = (Polynomial.X - Polynomial.C (v i)) * Lagrange.nodal (s.erase i) v

full_name: Lagrange.X_sub_C_dvd_nodal
code: theorem X_sub_C_dvd_nodal (v : ι → R) {i : ι} (hi : i ∈ s) : X - C (v i) ∣ nodal s v 
goal: Polynomial.X - Polynomial.C (v i) ∣ Lagrange.nodal s v

full_name: Lagrange.nodal_insert_eq_nodal
code: theorem nodal_insert_eq_nodal [DecidableEq ι] {i : ι} (hi : i ∉ s) :
    nodal (insert i s) v = (X - C (v i)) * nodal s v 
goal: Lagrange.nodal (insert i s) v = (Polynomial.X - Polynomial.C (v i)) * Lagrange.nodal s v

full_name: Lagrange.derivative_nodal
code: theorem derivative_nodal [DecidableEq ι] :
    derivative (nodal s v) = ∑ i ∈ s, nodal (s.erase i) v 
goal: Polynomial.derivative (Lagrange.nodal s v) = ∑ i ∈ s, Lagrange.nodal (s.erase i) v

full_name: Lagrange.eval_nodal_derivative_eval_node_eq
code: theorem eval_nodal_derivative_eval_node_eq [DecidableEq ι] {i : ι} (hi : i ∈ s) :
    eval (v i) (derivative (nodal s v)) = eval (v i) (nodal (s.erase i) v) 
goal: Polynomial.eval (v i) (Polynomial.derivative (Lagrange.nodal s v)) =
  Polynomial.eval (v i) (Lagrange.nodal (s.erase i) v)

full_name: Lagrange.nodal_subgroup_eq_X_pow_card_sub_one
code: /-- The vanishing polynomial on a multiplicative subgroup is of the form X ^ n - 1. -/
@[simp] theorem nodal_subgroup_eq_X_pow_card_sub_one [IsDomain R]
  (G : Subgroup Rˣ) [Fintype G] :
  nodal (G : Set Rˣ).toFinset ((↑) : Rˣ → R) = X ^ (Fintype.card G) - 1 
goal: Lagrange.nodal (↑G).toFinset Units.val = Polynomial.X ^ Fintype.card ↥G - 1

full_name: Lagrange.nodalWeight
code: /-- This defines the nodal weight for a given set of node indexes and node mapping function `v`. -/
def nodalWeight (s : Finset ι) (v : ι → F) (i : ι) 
goal: F

full_name: Lagrange.nodalWeight_eq_eval_nodal_erase_inv
code: theorem nodalWeight_eq_eval_nodal_erase_inv :
    nodalWeight s v i = (eval (v i) (nodal (s.erase i) v))⁻¹ 
goal: Lagrange.nodalWeight s v i = (Polynomial.eval (v i) (Lagrange.nodal (s.erase i) v))⁻¹

full_name: Lagrange.nodal_erase_eq_nodal_div
code: theorem nodal_erase_eq_nodal_div (hi : i ∈ s) :
    nodal (s.erase i) v = nodal s v / (X - C (v i)) 
goal: Lagrange.nodal (s.erase i) v = Lagrange.nodal s v / (Polynomial.X - Polynomial.C (v i))

full_name: Lagrange.nodalWeight_eq_eval_nodal_derative
code: theorem nodalWeight_eq_eval_nodal_derative (hi : i ∈ s) :
    nodalWeight s v i = (eval (v i) (Polynomial.derivative (nodal s v)))⁻¹ 
goal: Lagrange.nodalWeight s v i = (Polynomial.eval (v i) (Polynomial.derivative (Lagrange.nodal s v)))⁻¹

full_name: Lagrange.nodalWeight_ne_zero
code: theorem nodalWeight_ne_zero (hvs : Set.InjOn v s) (hi : i ∈ s) : nodalWeight s v i ≠ 0 
goal: Lagrange.nodalWeight s v i ≠ 0

full_name: Lagrange.basis_eq_prod_sub_inv_mul_nodal_div
code: theorem basis_eq_prod_sub_inv_mul_nodal_div (hi : i ∈ s) :
    Lagrange.basis s v i = C (nodalWeight s v i) * (nodal s v / (X - C (v i))) 
goal: Lagrange.basis s v i =
  Polynomial.C (Lagrange.nodalWeight s v i) * (Lagrange.nodal s v / (Polynomial.X - Polynomial.C (v i)))

full_name: Lagrange.eval_basis_not_at_node
code: theorem eval_basis_not_at_node (hi : i ∈ s) (hxi : x ≠ v i) :
    eval x (Lagrange.basis s v i) = eval x (nodal s v) * (nodalWeight s v i * (x - v i)⁻¹) 
goal: Polynomial.eval x (Lagrange.basis s v i) =
  Polynomial.eval x (Lagrange.nodal s v) * (Lagrange.nodalWeight s v i * (x - v i)⁻¹)

full_name: Lagrange.interpolate_eq_nodalWeight_mul_nodal_div_X_sub_C
code: theorem interpolate_eq_nodalWeight_mul_nodal_div_X_sub_C :
    interpolate s v r = ∑ i ∈ s, C (nodalWeight s v i) * (nodal s v / (X - C (v i))) * C (r i) 
goal: (Lagrange.interpolate s v) r =
  ∑ i ∈ s,
    Polynomial.C (Lagrange.nodalWeight s v i) * (Lagrange.nodal s v / (Polynomial.X - Polynomial.C (v i))) *
      Polynomial.C (r i)

full_name: Lagrange.eval_interpolate_not_at_node
code: /-- This is the first barycentric form of the Lagrange interpolant. -/
theorem eval_interpolate_not_at_node (hx : ∀ i ∈ s, x ≠ v i) :
    eval x (interpolate s v r) =
      eval x (nodal s v) * ∑ i ∈ s, nodalWeight s v i * (x - v i)⁻¹ * r i 
goal: Polynomial.eval x ((Lagrange.interpolate s v) r) =
  Polynomial.eval x (Lagrange.nodal s v) * ∑ i ∈ s, Lagrange.nodalWeight s v i * (x - v i)⁻¹ * r i

full_name: Lagrange.sum_nodalWeight_mul_inv_sub_ne_zero
code: theorem sum_nodalWeight_mul_inv_sub_ne_zero (hvs : Set.InjOn v s) (hx : ∀ i ∈ s, x ≠ v i)
    (hs : s.Nonempty) : (∑ i ∈ s, nodalWeight s v i * (x - v i)⁻¹) ≠ 0 
goal: ∑ i ∈ s, Lagrange.nodalWeight s v i * (x - v i)⁻¹ ≠ 0

full_name: Lagrange.eval_interpolate_not_at_node'
code: /-- This is the second barycentric form of the Lagrange interpolant. -/
theorem eval_interpolate_not_at_node' (hvs : Set.InjOn v s) (hs : s.Nonempty)
    (hx : ∀ i ∈ s, x ≠ v i) :
    eval x (interpolate s v r) =
      (∑ i ∈ s, nodalWeight s v i * (x - v i)⁻¹ * r i) /
        ∑ i ∈ s, nodalWeight s v i * (x - v i)⁻¹ 
goal: Polynomial.eval x ((Lagrange.interpolate s v) r) =
  (∑ i ∈ s, Lagrange.nodalWeight s v i * (x - v i)⁻¹ * r i) / ∑ i ∈ s, Lagrange.nodalWeight s v i * (x - v i)⁻¹