3

Consider the complex mathematical function on the line [1, 15]: f(x) = sin(x / 5) * exp(x / 10) + 5 * exp(-x / 2)

enter image description here

polynomial of degree n (w_0 + w_1 x + w_2 x^2 + ... + w_n x^n) is uniquely defined by any n + 1 different points through which it passes. This means that its coefficients w_0, ... w_n can be determined from the following system of linear equations:

enter image description here

Where x_1, ..., x_n, x_ {n + 1} are the points through which the polynomial passes, and by f (x_1), ..., f (x_n), f (x_ {n + 1}) - values that it must take at these points.

I'm trying to form a system of linear equations (that is, specify the coefficient matrix A and the free vector b) for the polynomial of the third degree, which must coincide with the function f at points 1, 4, 10, and 15. Solve this system using the scipy.linalg.solve function.

A = numpy.array([[1., 1., 1., 1.], [1., 4., 8., 64.], [1., 10., 100., 1000.], [1., 15., 225., 3375.]])

V = numpy.array([3.25, 1.74, 2.50, 0.63])

numpy.linalg.solve(A, V)

I got the wrong answer, which isenter image description here

So the question is: is the matrix correct?

1
  • For points 1, 4, 10 and 15 (Sorry I don't know how to edit the comm so it display in a col) w0 + w1 * 1 + w2*1^2 + w3*1^3 = sin(1 / 5) * exp(1 / 10) + 5 * exp(-1 / 2) w0 + w1 * 4 + w2*4^2 + w3*4^3 = sin(4 / 5) * exp(4 / 10) + 5 * exp(-4 / 2) w0 + w1 * 10 + w2*10^2 + w3*10^3 = sin(10 / 5) * exp(10 / 10) + 5 * exp(-10 / 2) w0 + w1 * 15 + w2*15^2 + w3*15^3 = sin(15 / 5) * exp(15 / 10) + 5 * exp(-15 / 2) System of equations: w0 + w1*1 + w2*1^2 +w3*1^3 = 3.25 w0 + w1*4 + w2*4^2 + w3*4^3 = 1.74 w0 + w1*10 + w2*10^2 + w3*10^3 = 2.50 w0 + w1*15 + w2*15^2 + w3*15^3 = 0.63 Commented May 29, 2017 at 19:12

3 Answers 3

3

No, your matrix is not correct.

The biggest mistake is your second sub-matrix for A. The third entry should be 4**2 which is 16 but you have 8. Less important, you have only two decimal places for your constants array V but you really should have more precision than that. Systems of linear equations are sometimes very sensitive to the provided values, so make them as precise as possible. Also, the rounding in your final three entries is bad: you rounded down but you should have rounded up. If you really want two decimal places (which I do not recommend) the values should be

V = numpy.array([3.25, 1.75, 2.51, 0.64])

But better would be

V = numpy.array([3.252216865271419, 1.7468459495903677,
                 2.5054164070002463, 0.6352214195786656])

With those changes to A and V I get the result

array([ 4.36264154, -1.29552587,  0.19333685, -0.00823565])

I get these two sympy plots, the first showing your original function and the second using the approximated cubic polynomial.

enter image description here

enter image description here

They look close to me! When I calculate the function values at 1, 4, 10, and 15, the largest absolute error is for 15, namely -4.57042132584462e-6. That is somewhat larger than I would have expected but probably is good enough.

Sign up to request clarification or add additional context in comments.

3 Comments

Roy, thank you so much! I do really appreciate your help! How you did it so quickly? :)
@plywoods: You are welcome. I saw your question less than a minute after you posted it, and I had my copy of Python (in Spyder) up and running. Also, I am now learning sympy through the book Doing Math with Python so sympy's plotting mechanism is fresh in my mind.
Thank you! Appreciate your help!
0

Is it from data science course? :) Here is an almost generic solution I did:

%matplotlib inline

import numpy as np;
import math;
import matplotlib.pyplot as plt;

def f(x):
    return np.sin(x / 5) * np.exp(x / 10) + 5 * np.exp(-x / 2)

# approximate at the given points (feel free to experiment: change/add/remove)
points = np.array([1, 4, 10, 15])
n = points.size

# fill A-matrix, each row is 1 or xi^0, xi^1, xi^2, xi^3 .. xi^n
A = np.zeros((n, n))
for index in range(0, n):
    A[index] = np.power(np.full(n, points[index]), np.arange(0, n, 1))

# fill b-matrix, i.e. function value at the given points
b = f(points)

# solve to get approximation polynomial coefficents
solve = np.linalg.solve(A,b)

# define the polynome approximation of the function
def polinom(x): 
    # Yi = solve * Xi where Xi = x^i
    tiles = np.tile(x, (n, 1))
    tiles[0] = np.ones(x.size)
    for index in range(1, n):
        tiles[index] = tiles[index]**index
    return solve.dot(tiles)

# plot the graphs of original function and its approximation
x = np.linspace(1, 15, 100)
plt.plot(x, f(x))
plt.plot(x, polinom(x))

# print out the coefficients of polynome approximating our function
print(solve)

3 Comments

If anyone knows how to improve the python code, please let me know, I will update the answer. I don't like much how A and polinom(x) are defined but I haven't found something better.
To construct the matrix A, you can use the Vandermonde matrix - np.vander(points, increasing=True). To calculate a polynomial, np.polyval()
Hi Vadim, do you remember why the coefficient matrix starts from 1 always? Like [[ 1. 1. 1.] [ 1. 4. 16.] [ 1. 15. 225.]] for polynom of third grade with x points in 1,4,15? Is it because the first value of linear space for x is 1 or it is some constant for linalg.solve specifically?
0

Based on the previous answer, I solved it like this
This is a abstract solution. To obtain an approximation by the necessary degrees, list them in the degrees array.

import numpy as np
import matplotlib.pyplot as plt

degrees = [1, 2]

def f(x):
    return np.sin(x / 5) * np.exp(x / (2 * 5)) + 5 * np.exp(-x / 2)

def main():
    a, b = 1, 15
    num_points = 100
    coeffs_list = []

    X = np.linspace(a, b, num_points)
    y_original = f(X)
    plt.plot(X, y_original, label='f(x)')

    for degree in degrees:
        points = np.linspace(a, b, degree + 1)
        A = np.vander(points, increasing=True)
        b_vec = f(points)

        print(f"Степень многочлена: {degree}")
        print("Матрица системы:")
        print(A)
        print("Вектор правой части:")
        print(b_vec)

        coeffs_list.append(np.linalg.solve(A, b_vec))

    for coeffs in coeffs_list:
        plt.plot(X, np.polyval(coeffs[::-1], X), label=f'g(x), степень {coeffs.size - 1}')

    plt.xlabel('x')
    plt.ylabel('y')
    plt.legend()
    plt.grid()
    plt.show()

if __name__ == '__main__':
    main()

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.