interpolation / app.py
r3hab's picture
Update app.py
42d27aa verified
import streamlit as st
import pandas as pd
def divided_differences(x, y):
"""
Calculates the divided differences table for Newton's Divided Difference formula.
Args:
x (list): List of x-values.
y (list): List of y-values corresponding to x-values.
Returns:
pandas.DataFrame: Divided differences table.
"""
n = len(y)
if n == 0:
return pd.DataFrame()
dd_table = pd.DataFrame(index=range(n), columns=range(n))
dd_table[0] = pd.Series(y)
for j in range(1, n):
for i in range(n - j):
dd_table.loc[i, j] = (dd_table.loc[i+1, j-1] - dd_table.loc[i, j-1]) / (float(x[i+j]) - float(x[i]))
return dd_table
def newton_interpolation_steps_latex(x, y, x_interp):
"""
Calculates the interpolated value at x_interp using Newton's Divided Difference formula and provides step-by-step solution in LaTeX.
Args:
x (list): List of x-values.
y (list): List of y-values corresponding to x-values.
x_interp (float): The x-value to interpolate at.
Returns:
tuple: (interpolated_y, dd_table, steps_latex)
interpolated_y (float): The interpolated y-value at x_interp.
dd_table (pandas.DataFrame): The divided differences table.
steps_latex (list of str): List of LaTeX strings describing each step of the calculation.
Returns (None, None, None) if there's an error (e.g., empty input).
"""
n = len(x)
if n == 0 or len(y) != n:
return None, None, None
dd_table_df = divided_differences(x, y)
if dd_table_df.empty:
return None, None, None
dd_table = dd_table_df.values.tolist()
y_interp = dd_table[0][0]
steps_latex = []
# Initial step in LaTeX
steps_latex.append(r"Initial value: $P(x) = f[x_0] = {:.4f}$".format(y_interp))
for i in range(1, n):
term = 1.0
for j in range(i):
term *= (x_interp - float(x[j]))
current_term_value = dd_table[0][i] * term
# Construct divided difference notation in LaTeX: f[x_0, ..., x_i]
dd_notation_latex = r"f[x_0"
for k in range(1, i + 1):
dd_notation_latex += r", x_{" + str(k) + r"}"
dd_notation_latex += r"]"
# Construct polynomial term in LaTeX: (x - x_0)(x - x_1)...(x - x_{i-1})
polynomial_term_latex = ""
for j in range(i):
polynomial_term_latex += r"(x - " + str(x[j]) + r")"
if not polynomial_term_latex:
polynomial_term_latex = "1"
# Step description in LaTeX
step_latex_description = r"Add term {}: ${} \times {} = {:.4f} \times $".format(i, dd_notation_latex, polynomial_term_latex.replace('x', str(x_interp)), dd_table[0][i])
if i > 0:
term_values_latex = r" $\times$ ".join([r"({:.1f} - {})".format(x_interp, val) for val in x[:i]]) # more robust float formatting
step_latex_description += term_values_latex
else:
step_latex_description = r"Initial value: $f[x_0] = {:.4f}$".format(dd_table[0][0]) # Should not happen in loop, but for clarity
step_latex_description += r" = {:.4f}$".format(current_term_value)
steps_latex.append(step_latex_description)
steps_latex.append(r"Current $P(x) = {:.4f}$".format(y_interp + current_term_value)) # Corrected accumulation here
y_interp += current_term_value # Accumulate interpolation value here
return y_interp, dd_table_df, steps_latex
st.title("Newton's Divided Difference Interpolation")
st.write("Enter the x and y values as comma-separated lists, and the x value you want to interpolate.")
x_values_input = st.text_area("Enter x values (comma-separated):", "2000, 2005, 2010, 2015")
y_values_input = st.text_area("Enter y values (comma-separated):", "1000, 1040, 1032, 1025")
x_interpolate = st.number_input("Enter x value to interpolate:", value=2001.0)
if st.button("Calculate Interpolated Value with Steps (LaTeX)"):
try:
x_values_str = x_values_input.strip()
y_values_str = y_values_input.strip()
if not x_values_str or not y_values_str:
st.error("Please enter both x and y values.")
else:
x_values = [val.strip() for val in x_values_str.split(',')]
y_values = [val.strip() for val in y_values_str.split(',')]
if len(x_values) != len(y_values):
st.error("The number of x values and y values must be the same.")
else:
try:
x_values_float = [float(x) for x in x_values]
y_values_float = [float(y) for y in y_values]
if not all(isinstance(x, (int, float)) for x in x_values_float) or not all(isinstance(y, (int, float)) for y in y_values_float):
st.error("Please ensure all x and y values are numbers.")
else:
interpolated_y, dd_table, steps_latex = newton_interpolation_steps_latex(x_values_float, y_values_float, x_interpolate)
if interpolated_y is not None:
st.success(f"The interpolated value at x = {x_interpolate} is: **{interpolated_y:.4f}**")
st.subheader("Divided Difference Table:")
st.dataframe(dd_table.fillna(''))
st.subheader("Step-by-step Calculation:")
for step_latex in steps_latex:
st.latex(step_latex)
else:
st.error("An error occurred during interpolation. Please check your input data.")
except ValueError:
st.error("Invalid input. Please enter comma-separated numbers for x and y values.")
except Exception as e:
st.error(f"An unexpected error occurred: {e}")