File size: 5,937 Bytes
a715df3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42d27aa
a715df3
 
 
 
 
 
 
 
42d27aa
a715df3
42d27aa
 
a715df3
 
 
 
42d27aa
a715df3
42d27aa
a715df3
 
42d27aa
a715df3
42d27aa
a715df3
 
42d27aa
a715df3
42d27aa
a715df3
 
42d27aa
 
a715df3
 
 
 
 
 
 
42d27aa
 
 
a715df3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
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}")