From 00c18edb63798269a77cfb7024a170802638261d Mon Sep 17 00:00:00 2001 From: Mashrur Safir Shabab Date: Fri, 18 Nov 2022 21:32:29 +0600 Subject: [PATCH] Add files via upload --- Polynomial_Interpolation.ipynb | 799 +++++++++++++++++++++++++++++++++ 1 file changed, 799 insertions(+) create mode 100644 Polynomial_Interpolation.ipynb diff --git a/Polynomial_Interpolation.ipynb b/Polynomial_Interpolation.ipynb new file mode 100644 index 0000000..c1df4b5 --- /dev/null +++ b/Polynomial_Interpolation.ipynb @@ -0,0 +1,799 @@ +{ + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.4" + }, + "colab": { + "provenance": [] + } + }, + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "ix8UYABygxwV" + }, + "source": [ + "Make sure you remove `raise NotImplementedError()` and fill in any place that says `# YOUR CODE HERE`, as well as your `NAME`, `ID`, and `LAB_SECTION` below:" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "yRMG6NyDgxwa" + }, + "source": [ + "NAME = \"Mashrur Safir Shabab\"\n", + "ID = \"20241037\"\n", + "SECTION = \"07\"" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "\"\"\"import numpy as np\n", + "x = [1,2,3,4]\n", + "x = np.array([1,2,3,4])\n", + "print(x)\"\"\"" + ], + "metadata": { + "id": "4_rvCuZLf1qV", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 35 + }, + "outputId": "d1155cf6-4ed1-4f78-8f01-fd1449088f6a" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "'import numpy as np\\nx = [1,2,3,4]\\nx = np.array([1,2,3,4])\\nprint(x)'" + ], + "application/vnd.google.colaboratory.intrinsic+json": { + "type": "string" + } + }, + "metadata": {}, + "execution_count": 38 + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "YO3vu3cQgxwc" + }, + "source": [ + "---" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "markdown", + "checksum": "a1a4b82e1290e7fe207981d775116189", + "grade": false, + "grade_id": "part1_intro", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + }, + "id": "6D4EuqaHgxwc" + }, + "source": [ + "# Part 1: Representing a Polynomial\n", + "\n", + "Polynomials are function of the following format\n", + "\n", + "$$p(x) = a_0 + a_1 x ^ 1 + a_2 x ^ 2 + ... + a_n x ^ n,$$\n", + "\n", + "where, $[a_0, a_1, \\cdots a_n]$ are called coefficients and $n$ (called the degree or order) is a non-negative integer.\n", + "\n", + "\n", + "This can also be written as:\n", + "\n", + "$$y = f(x) = a_0 x^0 + a_1 x ^ 1 + a_2 x ^ 2 + ... + a_n x ^ n.$$\n", + "\n", + "**Example**\n", + "$$ y = 1 + 2x^2 + 5x^4 $$ is a polynomial of order 4 ($ = n$) with $n+1$ coeffecients $a_0 = 1, a_1 = 0, a_2 = 2, a_3 = 0, a_4 = 5$" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "markdown", + "checksum": "4768b3ef2708eeb7d4e7834f6871c77b", + "grade": false, + "grade_id": "header_list", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + }, + "id": "uUKAl1BBgxwd" + }, + "source": [ + "**Method 1**: Using List\n", + "\n", + "---" + ] + }, + { + "cell_type": "code", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "a5e0eb4e8aa8fa601c4d5b1f8bb7518a", + "grade": false, + "grade_id": "import", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + }, + "id": "6TTFQ7HEgxwd" + }, + "source": [ + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "\n", + "\n", + "# numpy is used for efficient array (vector or matrix) operations\n", + "# pyplot is used for plotting \n", + "# Must read: [https://www.tutorialspoint.com/numpy/numpy_matplotlib.htm]" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "a8ec21a0babc1a6a8e9ce264a80fb7a9", + "grade": false, + "grade_id": "poly_list", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + }, + "id": "GkHghXVjgxwe", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "outputId": "ba8d9a5c-081d-487c-a3d5-bdc2ad301d16" + }, + "source": [ + "arr = [1, 0, 2, 0, 5] # coeffecients of the polynomial\n", + "n = len(arr) - 1 # degree. Remember: number of coeff = degree + 1\n", + "\n", + "'''\n", + "For a single value of x, finding p(x)\n", + "\n", + "Note that this is an example of block comment in python. A block comment \n", + "starts with three ' and ends with three '.\n", + "'''\n", + "\n", + "x = 5.0\n", + "p_x = 0.0\n", + "\n", + "for i in range(n + 1):\n", + " '''\n", + " p_x = arr[i] * x # WRONG, because no power\n", + " p_x = arr[i] * (x ** i) # WRONG, have to add the terms\n", + " '''\n", + " p_x += arr[i] * (x ** i) # a ** b means pow(a, b) or a^b\n", + "\n", + "'''\n", + "For an array of x, finding p(x) for each element\n", + "'''\n", + "\n", + "x_arr = [1.0, 2.0, 3.0, 4.0, 5.0]\n", + "p_x_arr = []\n", + "\n", + "'''\n", + "# naive way:\n", + "for i in range(len(x_arr)):\n", + " print(x_arr[i])\n", + "'''\n", + "\n", + "# better way: array traversing\n", + "for x in x_arr:\n", + " temp = 0.0\n", + " for i in range(n + 1):\n", + " temp += arr[i] * (x ** i)\n", + " \n", + " p_x_arr.append(temp) # insert the element at the end of the array\n", + " \n", + "\n", + "print(f\"p({x_arr}) = \", p_x_arr)\n", + "# note how we formatted the string. A formatted string starts with 'f'." + ], + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "p([1.0, 2.0, 3.0, 4.0, 5.0]) = [8.0, 89.0, 424.0, 1313.0, 3176.0]\n" + ] + } + ] + }, + { + "cell_type": "code", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "46c4652eda2f70244cbd7406dfbbb71d", + "grade": false, + "grade_id": "poly_numpy", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + }, + "id": "luEU7icygxwf", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "outputId": "682a088e-c2cb-4f49-b0e1-065470d0e233" + }, + "source": [ + "# Using numpy array for vectorization\n", + "import numpy as np \n", + "# numpy is used for efficient array (vector or matrix) operations\n", + "# Must read: [https://www.tutorialspoint.com/numpy/numpy_matplotlib.htm]\n", + "\n", + "\n", + "array = np.array([1, 0, 2, 0, 5])\n", + "x_arr = np.array([1, 2, 3, 4, 5])\n", + "p_x_arr = 0.0\n", + "\n", + "# vectorized version. requires only one loop\n", + "for i in range(n + 1):\n", + " p_x_arr += array[i] * (x_arr ** i) # a ** b means pow(a, b) or a^b\n", + " \n", + "print(f\"p({x_arr}) = \", p_x_arr)" + ], + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "p([1 2 3 4 5]) = [ 8. 89. 424. 1313. 3176.]\n" + ] + } + ] + }, + { + "cell_type": "code", + "source": [], + "metadata": { + "id": "U3PYGd0VZHcV" + }, + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "markdown", + "checksum": "ebd48410397a242a7c85eae3bef2090e", + "grade": false, + "grade_id": "header_class", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + }, + "id": "0-q5-L16gxwg" + }, + "source": [ + "**Method 2 (Better)**: Using a Class\n", + "\n", + "---\n", + "Complete the implementation of the polynomial class as showed in the lecture" + ] + }, + { + "cell_type": "code", + "metadata": { + "deletable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "8bc8bdbd42af74922557a6c7c1004dc3", + "grade": false, + "grade_id": "part01_ans", + "locked": false, + "schema_version": 3, + "solution": true, + "task": false + }, + "id": "cz0rAEdUgxwg" + }, + "source": [ + "'''\n", + "Lab task 1\n", + "Here we implement a Polynomial class with three methods: the constructor\n", + "__init__(), the toString method __repr__(), and a method to make the objects\n", + "of the class callable, __call__() method\n", + "'''\n", + "\n", + "# Polynomial Class\n", + "\n", + "class Polynomial:\n", + " # Constructor, note that it starts and ends with two underscores\n", + " def __init__(self, coeff):\n", + " '''\n", + " Every internal variable of the object must be saved and initialized\n", + " in this method: self.variable = value\n", + " '''\n", + " self.coeff = coeff #a\n", + " self.degree = len(coeff) - 1 #n\n", + "\n", + " # Constructor to make the object callable \n", + " def __call__(self, x_arr):\n", + " '''\n", + " Here we assumed x_arr is a numpy array. Remember that a numpy array acts \n", + " like a vector (1D matrix). So an operation x + 1 would add 1 to each element\n", + " of the matrix (unlike python's defaule list). Simlarly, x ** 2 would return\n", + " element wise square of the array. \n", + "\n", + " Hence, this method would return an array, where the i'th element is the \n", + " (polynomial) interpolated value of x[i], given the coeffecients a[i].\n", + " '''\n", + " p_x_arr = 0\n", + " # --------------------------------------------\n", + " # HINT: Should look like\n", + " # for i in range(self.degree + 1):\n", + " # ????\n", + " # --------------------------------------------\n", + "\n", + " # remember 1: length = degree + 1 for a polynomial\n", + " # remember 2: range(0, a) is same as range(a)\n", + " # remember 3: range(a, b) means a is inclusive, b is exclusive\n", + " \n", + " # --------------------------------------------\n", + " # YOUR CODE HERE\n", + " for i in range(self.degree+1):\n", + " p_x_arr += self.coeff[i] * x_arr**i\n", + " return p_x_arr\n", + " # --------------------------------------------\n", + "\n", + " # String representation method of the object (similar to toString() of java)\n", + " def __repr__(self):\n", + " # remember: a formatted string must start with f.\n", + " \n", + " str_ret = f'Polynomial of degree {self.degree}\\np(x) = '\n", + " for i in range(self.degree + 1):\n", + " a_val = self.coeff[i]\n", + " if i != 0:\n", + " if a_val >= 0:\n", + " str_ret += f'+ {a_val}x^{i} '\n", + " else:\n", + " str_ret += f'- {-a_val}x^{i} '\n", + " else:\n", + " str_ret += f'{a_val}x^{i} '\n", + " \n", + " return str_ret\n", + "\n", + " # custom method 1: to get the degree of the polynomial\n", + " def get_degree(self):\n", + " # --------------------------------------------\n", + " # YOUR CODE HERE\n", + " return self.degree\n", + " # --------------------------------------------\n", + "\n", + " # custom method 2: to get the coefficients of the polynomial\n", + " def get_coeffs(self):\n", + " # --------------------------------------------\n", + " return self.coeff\n", + " #raise NotImplementedError()\n", + " # --------------------------------------------\n", + "\n" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "a7f2fe5f2eedf93d2e3a5ce5ba099e5b", + "grade": true, + "grade_id": "part01_test", + "locked": true, + "points": 10, + "schema_version": 3, + "solution": false, + "task": false + }, + "id": "jnHrzHXygxwi" + }, + "source": [ + "# test cases for your answer\n", + "x_arr = np.array([1, 2, 3, 4, 5])\n", + "\n", + "coeff = np.array([1.0, 0.0, 2.0, 0.0, 5.0])\n", + "p = Polynomial(coeff)\n", + "\n", + "results = [8, 89, 424, 1313, 3176]\n", + "test = p(x_arr)\n", + "\n", + "np.testing.assert_array_equal(results, test)" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "arr = [1,2,3]\n", + "print(arr * 3)" + ], + "metadata": { + "id": "1PmZq9hz7-hF", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "outputId": "1064e216-592a-4370-84fc-a2ca2cde3196" + }, + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "[1, 2, 3, 1, 2, 3, 1, 2, 3]\n" + ] + } + ] + }, + { + "cell_type": "code", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "09a4a08e433abc426afdb8aa66175a41", + "grade": false, + "grade_id": "sample_output", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + }, + "id": "UgcNqaKFgxwi", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "outputId": "5f49faac-c800-4501-8fc5-7651bf08a573" + }, + "source": [ + ",# an example to see if our implementation works\n", + "coeff = np.array([1.0, 0.0, 2.0, 0.0, 5.0])\n", + "p = Polynomial(coeff)\n", + "print(p) # check if printable\n", + "x_arr = np.array([1, 2, 3, 4, 5])\n", + "print()\n", + "print(f\"p({x_arr}) =\", p(x_arr)) # check if the object is callable\n", + "# should print p([1 2 3 4 5]) = [ 8. 89. 424. 1313. 3176.]" + ], + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Polynomial of degree 4\n", + "p(x) = 1.0x^0 + 0.0x^1 + 2.0x^2 + 0.0x^3 + 5.0x^4 \n", + "\n", + "p([1 2 3 4 5]) = [ 8. 89. 424. 1313. 3176.]\n" + ] + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "vuYkYozxgxwi" + }, + "source": [ + "# Part 2: Polynomial Interpolation (Matrix Method)\n", + "\n", + "If we have $n+1$ nodes, that is, $\\{(x_0, y_0), (x_1, y_1), (x_2, y_2), (x_{n}, y_{n})\\}$ that satisfies a polynomial of order $n$, it can be written as:\n", + "\n", + "\\begin{align}\n", + "&a_0 + a_1 x_0 + a_2 x_0^2 + \\cdots a_n + x_0^n = y_0\\\\\n", + "&a_0 + a_1 x_1 + a_2 x_1^2 + \\cdots a_n + x_1^n = y_1\\\\\n", + "&a_0 + a_1 x_2 + a_2 x_2^2 + \\cdots a_n + x_2^n = y_2\\\\\n", + "&\\cdots\\\\\n", + "&a_0 + a_1 x_{n-1} + a_2 x_{n}^2 + \\cdots + a_n x_{n}^n = y_{n}\\\\\n", + "\\end{align}\n", + "\n", + "Here, $p(x) = a_0 + a_1x^1 + a_2x^2 + \\cdots a_nx^n$ is called the fitted polynomial of the given data points (nodes). Using this polynomial to find the $y_k$ corresponding to an $x_k$ with the range of the given nodes is called polynomial interpolation.\n", + "\n", + "In matrix form, the equations can be written as $$\\mathbf{Xa = y},$$\n", + "\n", + "where $\\mathbf{X} = $\n", + "\n", + "\\begin{bmatrix}\n", + "x_0^0 & x_0^1 & x_0^2 & \\cdots & x_0^n\\\\\n", + "x_1^0 & x_1^1 & x_1^2 & \\cdots & x_1^n\\\\\n", + "\\vdots & \\vdots & \\vdots & \\ddots & \\vdots\\\\\n", + "x_n^0 & x_{n}^1 & x_n^2 & \\cdots & x_n^n\\\\\n", + "\\end{bmatrix}\n", + "\n", + "$\\mathbf{a} = $\n", + "\\begin{bmatrix}\n", + "a_0\\\\\n", + "a_1\\\\\n", + "\\vdots\\\\\n", + "a_n\n", + "\\end{bmatrix}\n", + "\n", + "and $\\mathbf{y} = $\n", + "\\begin{bmatrix}\n", + "y_0\\\\\n", + "y_1\\\\\n", + "\\vdots\\\\\n", + "y_n\n", + "\\end{bmatrix}\n", + "\n", + "From this, we can solve for $\\mathbf{a}$ using\n", + "$$\\mathbf{a = X^{-1}y}.$$\n", + "\n" + ] + }, + { + "cell_type": "code", + "metadata": { + "deletable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "51d07e5c4f10a9f3567c856d29392422", + "grade": false, + "grade_id": "task02_ans", + "locked": false, + "schema_version": 3, + "solution": true, + "task": false + }, + "id": "mgS2AYrxgxwj" + }, + "source": [ + "'''\n", + "Lab task 2\n", + "Here we implement a function which takes a discrete x and y array, and returns\n", + "a Polynomial object (the one we just implemented). This polynomial object can \n", + "be used to calculate y for any other value of x (not in that list) within the\n", + "range\n", + "'''\n", + "def get_poly(data_x, data_y):\n", + " n_nodes = len(data_x)\n", + " # np.zeors((a, b)) returns a (a x b) matrix, i.e., a rows and b columns \n", + " X = np.zeros((n_nodes, n_nodes))\n", + " \n", + " # Populate the X matrix with appropriate values\n", + " # See the lecture video how the matrix is formed\n", + " # --------------------------------------------\n", + " # Hint: The code will like like this:\n", + " # for i in range(n_nodes):\n", + " # for j in range(n_nodes):\n", + " # X[i, j] = ????\n", + " # --------------------------------------------\n", + " # YOUR CODE HERE\n", + " for i in range(n_nodes):\n", + " for j in range(n_nodes):\n", + " X[i,j] = data_x[i] ** j\n", + " print(X)\n", + " # --------------------------------------------\n", + " # We could have also used np.linalg.inv to find the inverse\n", + " # but pinv is more efficient\n", + " X_inv = np.linalg.pinv(X) # pseudo inverse\n", + " a = np.dot(X_inv, data_y)\n", + " p = Polynomial(a)\n", + "\n", + " return p" + ], + "execution_count": null, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "dbd631bf10d397f213423b5fd70a82d7", + "grade": true, + "grade_id": "task02_test", + "locked": true, + "points": 10, + "schema_version": 3, + "solution": false, + "task": false + }, + "id": "Jq7J4X7kgxwj", + "colab": { + "base_uri": "https://localhost:8080/" + }, + "outputId": "e9e0a827-5606-492e-d07f-b323be27a026" + }, + "source": [ + "# test cases for your answer\n", + "data_x = np.array([-3., -2., -1., 0., 1., 3.])\n", + "data_y = np.array([-80., -13., 6., 1., 5., 16.])\n", + "p = get_poly(data_x, data_y)\n", + "\n", + "results = np.array([-80, -74.60997689, -69.36169492, -64.26436346, -59.32622134,\n", + " -54.55456417, -49.95577177, -45.53533558, -41.297886, -37.24721982,\n", + " -33.38632762, -29.71742112, -26.24196062, -22.96068235, -19.87362589,\n", + " -16.98016156, -14.2790178, -11.76830857, -9.44556072, -7.30774144,\n", + " -5.35128559, -3.57212312, -1.96570645, -0.52703788, 0.74930302,\n", + " 1.86913203, 2.83863291, 3.66432993, 4.35306058, 4.9119481,\n", + " 5.34837412, 5.66995126, 5.88449574, 6, 6.02460529,\n", + " 5.96657428, 5.83426368, 5.63609684, 5.38053634, 5.07605665,\n", + " 4.73111668, 4.35413242, 3.95344953, 3.53731597, 3.1138546,\n", + " 2.69103576, 2.27664993, 1.87828029, 1.50327536, 1.15872159,\n", + " 0.85141596, 0.58783863, 0.3741255, 0.21604084, 0.1189499,\n", + " 0.0877915, 0.12705066, 0.2407312, 0.43232834, 0.70480134,\n", + " 1.06054604, 1.50136754, 2.02845277, 2.64234311, 3.34290699,\n", + " 4.1293125, 5, 5.95265474, 6.98417944, 8.09066693,\n", + " 9.26737272, 10.50868766, 11.80811047, 13.15822045, 14.55065,\n", + " 15.97605727, 17.42409876, 18.88340192, 20.34153777, 21.78499351,\n", + " 23.19914511, 24.56822994, 25.87531935, 27.1022913, 28.22980298,\n", + " 29.23726338, 30.10280593, 30.80326108, 31.31412894, 31.60955188,\n", + " 31.6622871, 31.4436793, 30.92363323, 30.07058634, 28.85148136,\n", + " 27.23173894, 25.17523021, 22.64424943, 19.59948659, 16])\n", + "\n", + "x_arr = np.linspace(-3, 3, 100)\n", + "test = p(x_arr)\n", + "\n", + "np.testing.assert_array_almost_equal(test, results)" + ], + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "[[ 1. -3. 9. -27. 81. -243.]\n", + " [ 1. -2. 4. -8. 16. -32.]\n", + " [ 1. -1. 1. -1. 1. -1.]\n", + " [ 1. 0. 0. 0. 0. 0.]\n", + " [ 1. 1. 1. 1. 1. 1.]\n", + " [ 1. 3. 9. 27. 81. 243.]]\n" + ] + } + ] + }, + { + "cell_type": "code", + "metadata": { + "deletable": false, + "editable": false, + "nbgrader": { + "cell_type": "code", + "checksum": "277c42ed406022472573b16fb698714a", + "grade": false, + "grade_id": "plot", + "locked": true, + "schema_version": 3, + "solution": false, + "task": false + }, + "id": "iCGAl18agxwk", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 383 + }, + "outputId": "fd4a2caf-a110-4e65-d4bc-e632e5aa64ce" + }, + "source": [ + "data_x = np.array([-3., -2., -1., 0., 1., 3.])\n", + "data_y = np.array([-80., -13., 6., 1., 5., 16.])\n", + "p = get_poly(data_x, data_y)\n", + "'''\n", + "np.linspace(a, b, n) returns a numpy array of n points equally \n", + "spaced from a to b\n", + "'''\n", + "x_arr = np.linspace(-3, 3, 100)\n", + "# interpolated values\n", + "y_interp = p(x_arr)\n", + "\n", + "# pyplot is used for plotting \n", + "# Must read: [https://www.tutorialspoint.com/numpy/numpy_matplotlib.htm]\n", + "\n", + "plt.plot(x_arr, y_interp, 'y')\n", + "plt.plot(data_x, data_y, 'go')\n", + "plt.xlabel('x - axis')\n", + "plt.ylabel('y - axis')\n", + " \n", + "\n", + "plt.show()" + ], + "execution_count": null, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "[[ 1. -3. 9. -27. 81. -243.]\n", + " [ 1. -2. 4. -8. 16. -32.]\n", + " [ 1. -1. 1. -1. 1. -1.]\n", + " [ 1. 0. 0. 0. 0. 0.]\n", + " [ 1. 1. 1. 1. 1. 1.]\n", + " [ 1. 3. 9. 27. 81. 243.]]\n" + ] + }, + { + "output_type": "display_data", + "data": { + "text/plain": [ + "
" + ], + "image/png": "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\n" + }, + "metadata": { + "needs_background": "light" + } + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "hJXjy663gxwk" + }, + "source": [], + "execution_count": null, + "outputs": [] + } + ] +} \ No newline at end of file