2719 lines
128 KiB
Text
2719 lines
128 KiB
Text
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "skip"
|
|
}
|
|
},
|
|
"source": [
|
|
"**Note**: Click on \"*Kernel*\" > \"*Restart Kernel and Clear All Outputs*\" in [JupyterLab](https://jupyterlab.readthedocs.io/en/stable/) *before* reading this notebook to reset its output. If you cannot run this file on your machine, you may want to open it [in the cloud <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_mb.png\">](https://mybinder.org/v2/gh/webartifex/intro-to-python/develop?urlpath=lab/tree/11_classes/04_content.ipynb)."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
}
|
|
},
|
|
"source": [
|
|
"# Chapter 11: Classes & Instances (continued)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "skip"
|
|
}
|
|
},
|
|
"source": [
|
|
"In this fourth part of the chapter, we finalize our `Vector` and `Matrix` classes. As both `class` definitions have become rather lengthy, we learn how we to organize them into a Python package and import them in this Jupyter notebook. "
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Packages vs. Modules"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"In [Chapter 2 <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_nb.png\">](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/02_functions/02_content.ipynb#Local-Modules-and-Packages), we introduce the concept of a Python module that is imported with the `import` statement. Essentially, a **module** is a single plain text \\*.py file on disk that contains Python code (e.g., [*sample_module.py* <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_gh.png\">](https://github.com/webartifex/intro-to-python/blob/develop/02_functions/sample_module.py) in [Chapter 2's folder <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_gh.png\">](https://github.com/webartifex/intro-to-python/tree/develop/02_functions)).\n",
|
|
"\n",
|
|
"Conceptually, a **package** is a generalization of a module whose code is split across several \\*.py to achieve a better organization of the individual parts. The \\*.py files are stored within a folder (e.g., [*sample_package* <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_gh.png\">](https://github.com/webartifex/intro-to-python/tree/develop/11_classes/sample_package) in [Chapter 11's folder <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_gh.png\">](https://github.com/webartifex/intro-to-python/tree/develop/11_classes)). In addition to that, a \"*\\_\\_init\\_\\_.py*\" file that may be empty must be put inside the folder. The latter is what the Python interpreter looks for to decide if a folder is a package or not.\n",
|
|
"\n",
|
|
"Let's look at an example with the final version of our `Vector` and `Matrix` classes.\n",
|
|
"\n",
|
|
"`!pwd` shows the location of this Jupyter notebook on the computer you are running [JupyterLab](https://jupyterlab.readthedocs.io/en/stable/) on: It is the local equivalent of [Chapter 11's folder <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_gh.png\">](https://github.com/webartifex/intro-to-python/tree/develop/11_classes) in this book's [GitHub repository <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_gh.png\">](https://github.com/webartifex/intro-to-python)."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 1,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"/home/webartifex/repos/intro-to-python/11_classes\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"!pwd"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"`!ls` lists all the files and folders in the current location: These are Chapter 11's Jupyter notebooks (i.e., the \\*.ipynb files) and the [*sample_package* <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_gh.png\">](https://github.com/webartifex/intro-to-python/tree/develop/11_classes/sample_package) folder. "
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 2,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"00_content.ipynb 02_content.ipynb 04_content.ipynb\n",
|
|
"01_exercises.ipynb 03_content.ipynb sample_package\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"!ls"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"If we run `!ls` with the `sample_package` folder as the argument, we see the folder's contents: Four \\*.py files. Alternatively, you can use [JupyterLab' File Browser](https://jupyterlab.readthedocs.io/en/stable/user/interface.html?highlight=file%20browser#left-sidebar) on the left to navigate into the package."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 3,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"__init__.py matrix.py\tutils.py vector.py\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"!ls sample_package"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"The package is organized such that the [*matrix.py* <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_gh.png\">](https://github.com/webartifex/intro-to-python/blob/develop/11_classes/sample_package/matrix.py) and [*vector.py* <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_gh.png\">](https://github.com/webartifex/intro-to-python/blob/develop/11_classes/sample_package/vector.py) modules each define just one class, `Matrix` and `Vector`. That is intentional as both classes consist of several hundred lines of code and comments.\n",
|
|
"\n",
|
|
"The [*utils.py* <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_gh.png\">](https://github.com/webartifex/intro-to-python/blob/develop/11_classes/sample_package/utils.py) module contains code that is shared by both classes. Such code snippets are commonly called \"utilities\" or \"helpers,\" which explains the module's name.\n",
|
|
"\n",
|
|
"Finally, the [*\\_\\_init\\_\\_.py* <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_gh.png\">](https://github.com/webartifex/intro-to-python/blob/develop/11_classes/sample_package/__init__.py) file contains mostly meta information and defines what objects should be importable from the package's top level.\n",
|
|
"\n",
|
|
"With the `import` statement, we can import the entire package just as we would import a module from the [standard library <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_py.png\">](https://docs.python.org/3/library/index.html)."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 4,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import sample_package as pkg"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"The above cell runs the code in the [*\\_\\_init\\_\\_.py* <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_gh.png\">](https://github.com/webartifex/intro-to-python/blob/develop/11_classes/sample_package/__init__.py) file from top to bottom, which in turn runs the [*matrix.py* <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_gh.png\">](https://github.com/webartifex/intro-to-python/blob/develop/11_classes/sample_package/matrix.py), [*utils.py* <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_gh.png\">](https://github.com/webartifex/intro-to-python/blob/develop/11_classes/sample_package/utils.py), and [*vector.py* <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_gh.png\">](https://github.com/webartifex/intro-to-python/blob/develop/11_classes/sample_package/vector.py) modules (cf., look at the `import` statements in the four \\*.py files to get the idea). As both [*matrix.py* <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_gh.png\">](https://github.com/webartifex/intro-to-python/blob/develop/11_classes/sample_package/matrix.py) and [*vector.py* <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_gh.png\">](https://github.com/webartifex/intro-to-python/blob/develop/11_classes/sample_package/vector.py) depend on each other (i.e., the `Matrix` class needs the `Vector` class to work and vice versa), understanding the order in that the modules are executed is not trivial. Without going into detail, we mention that Python guarantees that each \\*.py file is run only once and figures out the order on its own. If Python is unable to do that, for example, due to unresolvable cirular imports, it aborts with an `ImportError`.\n",
|
|
"\n",
|
|
"Below, `pkg` is an object of type `module` ..."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 5,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"<module 'sample_package' from '/home/webartifex/repos/intro-to-python/11_classes/sample_package/__init__.py'>"
|
|
]
|
|
},
|
|
"execution_count": 5,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"pkg"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 6,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"module"
|
|
]
|
|
},
|
|
"execution_count": 6,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"type(pkg)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"... and we use the built-in [dir() <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_py.png\">](https://docs.python.org/3/library/functions.html#dir) function to check what attributes `pkg` comes with."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 7,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"['Matrix',\n",
|
|
" 'Vector',\n",
|
|
" '__all__',\n",
|
|
" '__author__',\n",
|
|
" '__builtins__',\n",
|
|
" '__cached__',\n",
|
|
" '__doc__',\n",
|
|
" '__file__',\n",
|
|
" '__loader__',\n",
|
|
" '__name__',\n",
|
|
" '__package__',\n",
|
|
" '__path__',\n",
|
|
" '__spec__',\n",
|
|
" '__version__',\n",
|
|
" 'matrix',\n",
|
|
" 'utils',\n",
|
|
" 'vector']"
|
|
]
|
|
},
|
|
"execution_count": 7,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"dir(pkg)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"The package's meta information and documentation are automatically parsed from the [*\\_\\_init\\_\\_.py* <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_gh.png\">](https://github.com/webartifex/intro-to-python/blob/develop/11_classes/sample_package/__init__.py) file."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 8,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Help on package linear_algebra_tools:\n",
|
|
"\n",
|
|
"NAME\n",
|
|
" linear_algebra_tools - This package provides linear algebra functionalities.\n",
|
|
"\n",
|
|
"DESCRIPTION\n",
|
|
" The package is split into three modules:\n",
|
|
" - matrix: defines the Matrix class\n",
|
|
" - vector: defines the Vector class\n",
|
|
" - utils: defines the norm() function that is shared by Matrix and Vector\n",
|
|
" and package-wide constants\n",
|
|
" \n",
|
|
" The classes implement arithmetic operations involving vectors and matrices.\n",
|
|
" \n",
|
|
" See the docstrings in the modules and classes for further info.\n",
|
|
"\n",
|
|
"PACKAGE CONTENTS\n",
|
|
" matrix\n",
|
|
" utils\n",
|
|
" vector\n",
|
|
"\n",
|
|
"CLASSES\n",
|
|
" builtins.object\n",
|
|
" sample_package.matrix.Matrix\n",
|
|
" sample_package.vector.Vector\n",
|
|
" \n",
|
|
" class Matrix(builtins.object)\n",
|
|
" | Matrix(data)\n",
|
|
" | \n",
|
|
" | An m-by-n-dimensional matrix from linear algebra.\n",
|
|
" | \n",
|
|
" | All entries are converted to floats, or whatever is set in the typing attribute.\n",
|
|
" | \n",
|
|
" | Attributes:\n",
|
|
" | storage (callable): data type used to store the entries internally;\n",
|
|
" | defaults to tuple\n",
|
|
" | typing (callable): type casting applied to all entries upon creation;\n",
|
|
" | defaults to float\n",
|
|
" | vector_cls (vector.Vector): a reference to the Vector class to work with\n",
|
|
" | zero_threshold (float): max. tolerance when comparing an entry to zero;\n",
|
|
" | defaults to 1e-12\n",
|
|
" | \n",
|
|
" | Methods defined here:\n",
|
|
" | \n",
|
|
" | __abs__(self)\n",
|
|
" | The Frobenius norm of a Matrix.\n",
|
|
" | \n",
|
|
" | __add__(self, other)\n",
|
|
" | Handle `self + other` and `other + self`.\n",
|
|
" | \n",
|
|
" | This may be either matrix addition or broadcasting addition.\n",
|
|
" | \n",
|
|
" | Example Usage:\n",
|
|
" | >>> Matrix([(1, 2), (3, 4)]) + Matrix([(2, 3), (4, 5)])\n",
|
|
" | Matrix(((3.000, 5.000,), (7.000, 9.000,)))\n",
|
|
" | \n",
|
|
" | >>> Matrix([(1, 2), (3, 4)]) + 5\n",
|
|
" | Matrix(((6.000, 7.000,), (8.000, 9.000,)))\n",
|
|
" | \n",
|
|
" | >>> 10 + Matrix([(1, 2), (3, 4)])\n",
|
|
" | Matrix(((11.000, 12.000,), (13.000, 14.000,)))\n",
|
|
" | \n",
|
|
" | __bool__(self)\n",
|
|
" | A Matrix is truthy if its Frobenius norm is strictly positive.\n",
|
|
" | \n",
|
|
" | __eq__(self, other)\n",
|
|
" | Handle `self == other`.\n",
|
|
" | \n",
|
|
" | Compare two Matrix instances for equality.\n",
|
|
" | \n",
|
|
" | Example Usage:\n",
|
|
" | >>> Matrix([(1, 2), (3, 4)]) == Matrix([(1, 2), (3, 4)])\n",
|
|
" | True\n",
|
|
" | \n",
|
|
" | >>> Matrix([(1, 2), (3, 4)]) == Matrix([(5, 6), (7, 8)])\n",
|
|
" | False\n",
|
|
" | \n",
|
|
" | __float__(self)\n",
|
|
" | Cast a Matrix as a scalar.\n",
|
|
" | \n",
|
|
" | Returns:\n",
|
|
" | scalar (float)\n",
|
|
" | \n",
|
|
" | Raises:\n",
|
|
" | RuntimeError: if the Matrix has more than one entry\n",
|
|
" | \n",
|
|
" | __getitem__(self, index)\n",
|
|
" | Obtain an individual entry of a Matrix.\n",
|
|
" | \n",
|
|
" | Args:\n",
|
|
" | index (int / tuple of int's): if index is an integer,\n",
|
|
" | the Matrix is viewed as a sequence in row-major order;\n",
|
|
" | if index is a tuple of integers, the first one refers to\n",
|
|
" | the row and the second one to the column of the entry\n",
|
|
" | \n",
|
|
" | Returns:\n",
|
|
" | entry (Matrix.typing)\n",
|
|
" | \n",
|
|
" | Example Usage:\n",
|
|
" | >>> m = Matrix([(1, 2), (3, 4)])\n",
|
|
" | >>> m[0]\n",
|
|
" | 1.0\n",
|
|
" | >>> m[-1]\n",
|
|
" | 4.0\n",
|
|
" | >>> m[0, 1]\n",
|
|
" | 2.0\n",
|
|
" | \n",
|
|
" | __init__(self, data)\n",
|
|
" | Create a new matrix.\n",
|
|
" | \n",
|
|
" | Args:\n",
|
|
" | data (sequence of sequences): the matrix's entries;\n",
|
|
" | viewed as a sequence of the matrix's rows (i.e., row-major order);\n",
|
|
" | use the .from_columns() class method if the data come as a sequence\n",
|
|
" | of the matrix's columns (i.e., column-major order)\n",
|
|
" | \n",
|
|
" | Raises:\n",
|
|
" | ValueError:\n",
|
|
" | - if no entries are provided\n",
|
|
" | - if the number of columns is inconsistent across the rows\n",
|
|
" | \n",
|
|
" | Example Usage:\n",
|
|
" | >>> Matrix([(1, 2), (3, 4)])\n",
|
|
" | Matrix(((1.000, 2.000,), (3.000, 4.000,)))\n",
|
|
" | \n",
|
|
" | __iter__(self)\n",
|
|
" | Loop over a Matrix's entries.\n",
|
|
" | \n",
|
|
" | See .entries() for more customization options.\n",
|
|
" | \n",
|
|
" | __len__(self)\n",
|
|
" | Number of entries in a Matrix.\n",
|
|
" | \n",
|
|
" | __mul__(self, other)\n",
|
|
" | Handle `self * other` and `other * self`.\n",
|
|
" | \n",
|
|
" | This may be either scalar multiplication, matrix-vector multiplication,\n",
|
|
" | vector-matrix multiplication, or matrix-matrix multiplication.\n",
|
|
" | \n",
|
|
" | Example Usage:\n",
|
|
" | >>> Matrix([(1, 2), (3, 4)]) * Matrix([(1, 2), (3, 4)])\n",
|
|
" | Matrix(((7.000, 10.000,), (15.000, 22.000,)))\n",
|
|
" | \n",
|
|
" | >>> 2 * Matrix([(1, 2), (3, 4)])\n",
|
|
" | Matrix(((2.000, 4.000,), (6.000, 8.000,)))\n",
|
|
" | \n",
|
|
" | >>> Matrix([(1, 2), (3, 4)]) * 3\n",
|
|
" | Matrix(((3.000, 6.000,), (9.000, 12.000,)))\n",
|
|
" | \n",
|
|
" | Matrix-vector and vector-matrix multiplication are not commutative.\n",
|
|
" | \n",
|
|
" | >>> Matrix([(1, 2), (3, 4)]) * Vector([5, 6])\n",
|
|
" | Vector((17.000, 39.000))\n",
|
|
" | \n",
|
|
" | >>> Vector([5, 6]) * Matrix([(1, 2), (3, 4)])\n",
|
|
" | Vector((23.000, 34.000))\n",
|
|
" | \n",
|
|
" | __neg__(self)\n",
|
|
" | Handle `-self`.\n",
|
|
" | \n",
|
|
" | Negate all entries of a Matrix.\n",
|
|
" | \n",
|
|
" | __pos__(self)\n",
|
|
" | Handle `+self`.\n",
|
|
" | \n",
|
|
" | This is simply an identity operator returning the Matrix itself.\n",
|
|
" | \n",
|
|
" | __radd__(self, other)\n",
|
|
" | See docstring for .__add__().\n",
|
|
" | \n",
|
|
" | __repr__(self)\n",
|
|
" | Text representation of a Matrix.\n",
|
|
" | \n",
|
|
" | __reversed__(self)\n",
|
|
" | Loop over a Matrix's entries in reverse order.\n",
|
|
" | \n",
|
|
" | See .entries() for more customization options.\n",
|
|
" | \n",
|
|
" | __rmul__(self, other)\n",
|
|
" | See docstring for .__mul__().\n",
|
|
" | \n",
|
|
" | __rsub__(self, other)\n",
|
|
" | See docstring for .__sub__().\n",
|
|
" | \n",
|
|
" | __str__(self)\n",
|
|
" | Human-readable text representation of a Matrix.\n",
|
|
" | \n",
|
|
" | __sub__(self, other)\n",
|
|
" | Handle `self - other` and `other - self`.\n",
|
|
" | \n",
|
|
" | This may be either matrix subtraction or broadcasting subtraction.\n",
|
|
" | \n",
|
|
" | Example Usage:\n",
|
|
" | >>> Matrix([(2, 3), (4, 5)]) - Matrix([(1, 2), (3, 4)])\n",
|
|
" | Matrix(((1.000, 1.000,), (1.000, 1.000,)))\n",
|
|
" | \n",
|
|
" | >>> Matrix([(1, 2), (3, 4)]) - 1\n",
|
|
" | Matrix(((0.000, 1.000,), (2.000, 3.000,)))\n",
|
|
" | \n",
|
|
" | >>> 10 - Matrix([(1, 2), (3, 4)])\n",
|
|
" | Matrix(((9.000, 8.000,), (7.000, 6.000,)))\n",
|
|
" | \n",
|
|
" | __truediv__(self, other)\n",
|
|
" | Handle `self / other`.\n",
|
|
" | \n",
|
|
" | Divide a Matrix by a scalar.\n",
|
|
" | \n",
|
|
" | Example Usage:\n",
|
|
" | >>> Matrix([(1, 2), (3, 4)]) / 4\n",
|
|
" | Matrix(((0.250, 0.500,), (0.750, 1.000,)))\n",
|
|
" | \n",
|
|
" | as_vector(self)\n",
|
|
" | Get a Vector representation of a Matrix.\n",
|
|
" | \n",
|
|
" | Returns:\n",
|
|
" | vector (vector.Vector)\n",
|
|
" | \n",
|
|
" | Raises:\n",
|
|
" | RuntimeError: if one of the two dimensions, .n_rows or .n_cols, is not 1\n",
|
|
" | \n",
|
|
" | Example Usage:\n",
|
|
" | >>> Matrix([(1, 2, 3)]).as_vector()\n",
|
|
" | Vector((1.000, 2.000, 3.000))\n",
|
|
" | \n",
|
|
" | cols(self)\n",
|
|
" | Loop over a Matrix's columns.\n",
|
|
" | \n",
|
|
" | Returns:\n",
|
|
" | columns (generator): produces a Matrix's columns as Vectors\n",
|
|
" | \n",
|
|
" | entries(self, *, reverse=False, row_major=True)\n",
|
|
" | Loop over a Matrix's entries.\n",
|
|
" | \n",
|
|
" | Args:\n",
|
|
" | reverse (bool): flag to loop backwards; defaults to False\n",
|
|
" | row_major (bool): flag to loop in row-major order; defaults to True\n",
|
|
" | \n",
|
|
" | Returns:\n",
|
|
" | entries (generator): produces a Matrix's entries\n",
|
|
" | \n",
|
|
" | rows(self)\n",
|
|
" | Loop over a Matrix's rows.\n",
|
|
" | \n",
|
|
" | Returns:\n",
|
|
" | rows (generator): produces a Matrix's rows as Vectors\n",
|
|
" | \n",
|
|
" | transpose(self)\n",
|
|
" | Switch the rows and columns of a Matrix.\n",
|
|
" | \n",
|
|
" | Returns:\n",
|
|
" | matrix (Matrix)\n",
|
|
" | \n",
|
|
" | Example Usage:\n",
|
|
" | >>> m = Matrix([(1, 2), (3, 4)])\n",
|
|
" | >>> m\n",
|
|
" | Matrix(((1.000, 2.000,), (3.000, 4.000,)))\n",
|
|
" | >>> m.transpose()\n",
|
|
" | Matrix(((1.000, 3.000,), (2.000, 4.000,)))\n",
|
|
" | \n",
|
|
" | ----------------------------------------------------------------------\n",
|
|
" | Class methods defined here:\n",
|
|
" | \n",
|
|
" | from_columns(data) from builtins.type\n",
|
|
" | Create a new matrix.\n",
|
|
" | \n",
|
|
" | This is an alternative constructor for data provided in column-major order.\n",
|
|
" | \n",
|
|
" | Args:\n",
|
|
" | data (sequence of sequences): the matrix's entries;\n",
|
|
" | viewed as a sequence of the matrix's columns (i.e., column-major order);\n",
|
|
" | use the normal constructor method if the data come as a sequence\n",
|
|
" | of the matrix's rows (i.e., row-major order)\n",
|
|
" | \n",
|
|
" | Raises:\n",
|
|
" | ValueError:\n",
|
|
" | - if no entries are provided\n",
|
|
" | - if the number of rows is inconsistent across the columns\n",
|
|
" | \n",
|
|
" | Example Usage:\n",
|
|
" | >>> Matrix.from_columns([(1, 2), (3, 4)])\n",
|
|
" | Matrix(((1.000, 3.000,), (2.000, 4.000,)))\n",
|
|
" | \n",
|
|
" | from_rows(data) from builtins.type\n",
|
|
" | See docstring for .__init__().\n",
|
|
" | \n",
|
|
" | ----------------------------------------------------------------------\n",
|
|
" | Readonly properties defined here:\n",
|
|
" | \n",
|
|
" | n_cols\n",
|
|
" | Number of columns in a Matrix.\n",
|
|
" | \n",
|
|
" | n_rows\n",
|
|
" | Number of rows in a Matrix.\n",
|
|
" | \n",
|
|
" | ----------------------------------------------------------------------\n",
|
|
" | Data descriptors defined here:\n",
|
|
" | \n",
|
|
" | __dict__\n",
|
|
" | dictionary for instance variables (if defined)\n",
|
|
" | \n",
|
|
" | __weakref__\n",
|
|
" | list of weak references to the object (if defined)\n",
|
|
" | \n",
|
|
" | ----------------------------------------------------------------------\n",
|
|
" | Data and other attributes defined here:\n",
|
|
" | \n",
|
|
" | __hash__ = None\n",
|
|
" | \n",
|
|
" | storage = <class 'tuple'>\n",
|
|
" | Built-in immutable sequence.\n",
|
|
" | \n",
|
|
" | If no argument is given, the constructor returns an empty tuple.\n",
|
|
" | If iterable is specified the tuple is initialized from iterable's items.\n",
|
|
" | \n",
|
|
" | If the argument is a tuple, the return value is the same object.\n",
|
|
" | \n",
|
|
" | typing = <class 'float'>\n",
|
|
" | Convert a string or number to a floating point number, if possible.\n",
|
|
" | \n",
|
|
" | vector_cls = <class 'sample_package.vector.Vector'>\n",
|
|
" | A one-dimensional vector from linear algebra.\n",
|
|
" | \n",
|
|
" | All entries are converted to floats, or whatever is set in the typing attribute.\n",
|
|
" | \n",
|
|
" | Attributes:\n",
|
|
" | matrix_cls (matrix.Matrix): a reference to the Matrix class to work with\n",
|
|
" | storage (callable): data type used to store the entries internally;\n",
|
|
" | defaults to tuple\n",
|
|
" | typing (callable): type casting applied to all entries upon creation;\n",
|
|
" | defaults to float\n",
|
|
" | zero_threshold (float): max. tolerance when comparing an entry to zero;\n",
|
|
" | defaults to 1e-12\n",
|
|
" | \n",
|
|
" | zero_threshold = 1e-12\n",
|
|
" \n",
|
|
" class Vector(builtins.object)\n",
|
|
" | Vector(data)\n",
|
|
" | \n",
|
|
" | A one-dimensional vector from linear algebra.\n",
|
|
" | \n",
|
|
" | All entries are converted to floats, or whatever is set in the typing attribute.\n",
|
|
" | \n",
|
|
" | Attributes:\n",
|
|
" | matrix_cls (matrix.Matrix): a reference to the Matrix class to work with\n",
|
|
" | storage (callable): data type used to store the entries internally;\n",
|
|
" | defaults to tuple\n",
|
|
" | typing (callable): type casting applied to all entries upon creation;\n",
|
|
" | defaults to float\n",
|
|
" | zero_threshold (float): max. tolerance when comparing an entry to zero;\n",
|
|
" | defaults to 1e-12\n",
|
|
" | \n",
|
|
" | Methods defined here:\n",
|
|
" | \n",
|
|
" | __abs__(self)\n",
|
|
" | The Euclidean norm of a vector.\n",
|
|
" | \n",
|
|
" | __add__(self, other)\n",
|
|
" | Handle `self + other` and `other + self`.\n",
|
|
" | \n",
|
|
" | This may be either vector addition or broadcasting addition.\n",
|
|
" | \n",
|
|
" | Example Usage:\n",
|
|
" | >>> Vector([1, 2, 3]) + Vector([2, 3, 4])\n",
|
|
" | Vector((3.000, 5.000, 7.000))\n",
|
|
" | \n",
|
|
" | >>> Vector([1, 2, 3]) + 4\n",
|
|
" | Vector((5.000, 6.000, 7.000))\n",
|
|
" | \n",
|
|
" | >>> 10 + Vector([1, 2, 3])\n",
|
|
" | Vector((11.000, 12.000, 13.000))\n",
|
|
" | \n",
|
|
" | __bool__(self)\n",
|
|
" | A Vector is truthy if its Euclidean norm is strictly positive.\n",
|
|
" | \n",
|
|
" | __eq__(self, other)\n",
|
|
" | Handle `self == other`.\n",
|
|
" | \n",
|
|
" | Compare two Vectors for equality.\n",
|
|
" | \n",
|
|
" | Example Usage:\n",
|
|
" | >>> Vector([1, 2, 3]) == Vector([1, 2, 3])\n",
|
|
" | True\n",
|
|
" | \n",
|
|
" | >>> Vector([1, 2, 3]) == Vector([4, 5, 6])\n",
|
|
" | False\n",
|
|
" | \n",
|
|
" | __float__(self)\n",
|
|
" | Cast a Vector as a scalar.\n",
|
|
" | \n",
|
|
" | Returns:\n",
|
|
" | scalar (float)\n",
|
|
" | \n",
|
|
" | Raises:\n",
|
|
" | RuntimeError: if the Vector has more than one entry\n",
|
|
" | \n",
|
|
" | __getitem__(self, index)\n",
|
|
" | Obtain an individual entry of a Vector.\n",
|
|
" | \n",
|
|
" | __init__(self, data)\n",
|
|
" | Create a new vector.\n",
|
|
" | \n",
|
|
" | Args:\n",
|
|
" | data (sequence): the vector's entries\n",
|
|
" | \n",
|
|
" | Raises:\n",
|
|
" | ValueError: if no entries are provided\n",
|
|
" | \n",
|
|
" | Example Usage:\n",
|
|
" | >>> Vector([1, 2, 3])\n",
|
|
" | Vector((1.000, 2.000, 3.000))\n",
|
|
" | \n",
|
|
" | >>> Vector(range(3))\n",
|
|
" | Vector((0.000, 1.000, 2.000))\n",
|
|
" | \n",
|
|
" | __iter__(self)\n",
|
|
" | Loop over a Vector's entries.\n",
|
|
" | \n",
|
|
" | __len__(self)\n",
|
|
" | Number of entries in a Vector.\n",
|
|
" | \n",
|
|
" | __mul__(self, other)\n",
|
|
" | Handle `self * other` and `other * self`.\n",
|
|
" | \n",
|
|
" | This may be either the dot product of two vectors or scalar multiplication.\n",
|
|
" | \n",
|
|
" | Example Usage:\n",
|
|
" | >>> Vector([1, 2, 3]) * Vector([2, 3, 4])\n",
|
|
" | 20.0\n",
|
|
" | \n",
|
|
" | >>> 2 * Vector([1, 2, 3])\n",
|
|
" | Vector((2.000, 4.000, 6.000))\n",
|
|
" | \n",
|
|
" | >>> Vector([1, 2, 3]) * 3\n",
|
|
" | Vector((3.000, 6.000, 9.000))\n",
|
|
" | \n",
|
|
" | __neg__(self)\n",
|
|
" | Handle `-self`.\n",
|
|
" | \n",
|
|
" | Negate all entries of a Vector.\n",
|
|
" | \n",
|
|
" | __pos__(self)\n",
|
|
" | Handle `+self`.\n",
|
|
" | \n",
|
|
" | This is simply an identity operator returning the Vector itself.\n",
|
|
" | \n",
|
|
" | __radd__(self, other)\n",
|
|
" | See docstring for .__add__().\n",
|
|
" | \n",
|
|
" | __repr__(self)\n",
|
|
" | Text representation of a Vector.\n",
|
|
" | \n",
|
|
" | __reversed__(self)\n",
|
|
" | Loop over a Vector's entries in reverse order.\n",
|
|
" | \n",
|
|
" | __rmul__(self, other)\n",
|
|
" | See docstring for .__mul__().\n",
|
|
" | \n",
|
|
" | __rsub__(self, other)\n",
|
|
" | See docstring for .__sub__().\n",
|
|
" | \n",
|
|
" | __str__(self)\n",
|
|
" | Human-readable text representation of a Vector.\n",
|
|
" | \n",
|
|
" | __sub__(self, other)\n",
|
|
" | Handle `self - other` and `other - self`.\n",
|
|
" | \n",
|
|
" | This may be either vector subtraction or broadcasting subtraction.\n",
|
|
" | \n",
|
|
" | Example Usage:\n",
|
|
" | >>> Vector([7, 8, 9]) - Vector([1, 2, 3])\n",
|
|
" | Vector((6.000, 6.000, 6.000))\n",
|
|
" | \n",
|
|
" | >>> Vector([1, 2, 3]) - 1\n",
|
|
" | Vector((0.000, 1.000, 2.000))\n",
|
|
" | \n",
|
|
" | >>> 10 - Vector([1, 2, 3])\n",
|
|
" | Vector((9.000, 8.000, 7.000))\n",
|
|
" | \n",
|
|
" | __truediv__(self, other)\n",
|
|
" | Handle `self / other`.\n",
|
|
" | \n",
|
|
" | Divide a Vector by a scalar.\n",
|
|
" | \n",
|
|
" | Example Usage:\n",
|
|
" | >>> Vector([9, 6, 12]) / 3\n",
|
|
" | Vector((3.000, 2.000, 4.000))\n",
|
|
" | \n",
|
|
" | as_matrix(self, *, column=True)\n",
|
|
" | Get a Matrix representation of a Vector.\n",
|
|
" | \n",
|
|
" | Args:\n",
|
|
" | column (bool): if the vector is interpreted as a\n",
|
|
" | column vector or a row vector; defaults to True\n",
|
|
" | \n",
|
|
" | Returns:\n",
|
|
" | matrix (matrix.Matrix)\n",
|
|
" | \n",
|
|
" | Example Usage:\n",
|
|
" | >>> v = Vector([1, 2, 3])\n",
|
|
" | >>> v.as_matrix()\n",
|
|
" | Matrix(((1.000,), (2.000,), (3.000,)))\n",
|
|
" | >>> v.as_matrix(column=False)\n",
|
|
" | Matrix(((1.000, 2.000, 3.000,)))\n",
|
|
" | \n",
|
|
" | ----------------------------------------------------------------------\n",
|
|
" | Data descriptors defined here:\n",
|
|
" | \n",
|
|
" | __dict__\n",
|
|
" | dictionary for instance variables (if defined)\n",
|
|
" | \n",
|
|
" | __weakref__\n",
|
|
" | list of weak references to the object (if defined)\n",
|
|
" | \n",
|
|
" | ----------------------------------------------------------------------\n",
|
|
" | Data and other attributes defined here:\n",
|
|
" | \n",
|
|
" | __hash__ = None\n",
|
|
" | \n",
|
|
" | matrix_cls = <class 'sample_package.matrix.Matrix'>\n",
|
|
" | An m-by-n-dimensional matrix from linear algebra.\n",
|
|
" | \n",
|
|
" | All entries are converted to floats, or whatever is set in the typing attribute.\n",
|
|
" | \n",
|
|
" | Attributes:\n",
|
|
" | storage (callable): data type used to store the entries internally;\n",
|
|
" | defaults to tuple\n",
|
|
" | typing (callable): type casting applied to all entries upon creation;\n",
|
|
" | defaults to float\n",
|
|
" | vector_cls (vector.Vector): a reference to the Vector class to work with\n",
|
|
" | zero_threshold (float): max. tolerance when comparing an entry to zero;\n",
|
|
" | defaults to 1e-12\n",
|
|
" | \n",
|
|
" | storage = <class 'tuple'>\n",
|
|
" | Built-in immutable sequence.\n",
|
|
" | \n",
|
|
" | If no argument is given, the constructor returns an empty tuple.\n",
|
|
" | If iterable is specified the tuple is initialized from iterable's items.\n",
|
|
" | \n",
|
|
" | If the argument is a tuple, the return value is the same object.\n",
|
|
" | \n",
|
|
" | typing = <class 'float'>\n",
|
|
" | Convert a string or number to a floating point number, if possible.\n",
|
|
" | \n",
|
|
" | zero_threshold = 1e-12\n",
|
|
"\n",
|
|
"DATA\n",
|
|
" __all__ = ['Matrix', 'Vector']\n",
|
|
"\n",
|
|
"VERSION\n",
|
|
" 0.1.0\n",
|
|
"\n",
|
|
"AUTHOR\n",
|
|
" Alexander Hess\n",
|
|
"\n",
|
|
"FILE\n",
|
|
" /home/webartifex/repos/intro-to-python/11_classes/sample_package/__init__.py\n",
|
|
"\n",
|
|
"\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"help(pkg)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"The meta information could also be accessed separately and individually."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 9,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"'linear_algebra_tools'"
|
|
]
|
|
},
|
|
"execution_count": 9,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"pkg.__name__"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 10,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"'0.1.0'"
|
|
]
|
|
},
|
|
"execution_count": 10,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"pkg.__version__ # follows the semantic versioning format"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"We create `Vector` and `Matrix` instances in the usual way by calling the `Vector` and `Matrix` classes from the package's top level."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 11,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"Vector((1.000, 2.000, 3.000))"
|
|
]
|
|
},
|
|
"execution_count": 11,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"pkg.Vector([1, 2, 3])"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 12,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"Matrix(((1.000, 2.000, 3.000,), (4.000, 5.000, 6.000,), (7.000, 8.000, 9.000,)))"
|
|
]
|
|
},
|
|
"execution_count": 12,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"pkg.Matrix([(1, 2, 3), (4, 5, 6), (7, 8, 9)])"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"A common practice by package authors is to put all the objects on the package's top level that they want the package users to work with directly. That is achieved via the `import` statements in the [*\\_\\_init\\_\\_.py* <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_gh.png\">](https://github.com/webartifex/intro-to-python/blob/develop/11_classes/sample_package/__init__.py) file.\n",
|
|
"\n",
|
|
"However, users can always reach into a package and work with its internals.\n",
|
|
"\n",
|
|
"For example, the `Vector` and `Matrix` classes are also available via their **qualified name** (cf., [PEP 3155 <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_py.png\">](https://www.python.org/dev/peps/pep-3155/)): First, we access the `vector` and `matrix` modules on `pkg`, and then the `Vector` and `Matrix` classes on the modules."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 13,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"sample_package.vector.Vector"
|
|
]
|
|
},
|
|
"execution_count": 13,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"pkg.vector.Vector"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 14,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"sample_package.matrix.Matrix"
|
|
]
|
|
},
|
|
"execution_count": 14,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"pkg.matrix.Matrix"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Also, let's import the [*utils.py* <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_gh.png\">](https://github.com/webartifex/intro-to-python/blob/develop/11_classes/sample_package/utils.py) module with the `norm()` function into the global scope. As this function is integrated into the `Vector.__abs__()` and `Matrix.__abs__()` methods, there is actually no need to work with it explicitly."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 15,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from sample_package import utils"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 16,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Help on function norm in module sample_package.utils:\n",
|
|
"\n",
|
|
"norm(vec_or_mat)\n",
|
|
" Calculate the Frobenius or Euclidean norm of a matrix or vector.\n",
|
|
" \n",
|
|
" Find more infos here: https://en.wikipedia.org/wiki/Matrix_norm#Frobenius_norm\n",
|
|
" \n",
|
|
" Args:\n",
|
|
" vec_or_mat (Vector / Matrix): object whose entries are squared and summed up\n",
|
|
" \n",
|
|
" Returns:\n",
|
|
" norm (float)\n",
|
|
" \n",
|
|
" Example Usage:\n",
|
|
" As Vector and Matrix objects are by design non-empty sequences,\n",
|
|
" norm() may be called, for example, with `[3, 4]` as the argument:\n",
|
|
" >>> norm([3, 4])\n",
|
|
" 5.0\n",
|
|
"\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"help(utils.norm)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Many tutorials on the internet begin by importing \"everything\" from a package into the global scope with `from ... import *`.\n",
|
|
"\n",
|
|
"That is commonly considered a *bad* practice as it may overwrite already existing variables. However, if the package's [*\\_\\_init\\_\\_.py* <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_gh.png\">](https://github.com/webartifex/intro-to-python/blob/develop/11_classes/sample_package/__init__.py) file defines an `__all__` attribute, a `list` with all the names to be \"exported,\" the **star import** is safe to be used, in particular, in *interactive* sessions like Jupyter notebooks. We emphasize that the star import should *not* be used *within* packages and modules as then it is not directly evident from a name where the corresponding object is defined.\n",
|
|
"\n",
|
|
"For more best practices regarding importing we refer to, among others, [Google's Python Style Guide](https://google.github.io/styleguide/pyguide.html#22-imports).\n",
|
|
"\n",
|
|
"The following `import` statement makes the `Vector` and `Matrix` classes available in the global scope."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 17,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from sample_package import *"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 18,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"sample_package.vector.Vector"
|
|
]
|
|
},
|
|
"execution_count": 18,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"Vector"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 19,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"sample_package.matrix.Matrix"
|
|
]
|
|
},
|
|
"execution_count": 19,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"Matrix"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"For further information on modules and packages, we refer to the [official tutorial <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_py.png\">](https://docs.python.org/3/tutorial/modules.html)."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
}
|
|
},
|
|
"source": [
|
|
"## The final `Vector` and `Matrix` Classes"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"The final implementations of the `Vector` and `Matrix` classes are in the [*matrix.py* <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_gh.png\">](https://github.com/webartifex/intro-to-python/blob/develop/11_classes/sample_package/matrix.py) and [*vector.py* <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_gh.png\">](https://github.com/webartifex/intro-to-python/blob/develop/11_classes/sample_package/vector.py) files: They integrate all of the functionalities introduced in this chapter. In addition, the code is cleaned up and fully documented, including examples of common usages.\n",
|
|
"\n",
|
|
"We strongly suggest the eager student go over the files in the [*sample_package* <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_gh.png\">](https://github.com/webartifex/intro-to-python/tree/develop/11_classes/sample_package) in detail at some point to understand what well-written and (re-)usable code looks like."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 20,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"v = Vector([1, 2, 3])"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 21,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"Vector((1.000, 2.000, 3.000))"
|
|
]
|
|
},
|
|
"execution_count": 21,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"v"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 22,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"sample_package.vector.Vector"
|
|
]
|
|
},
|
|
"execution_count": 22,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"type(v)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 23,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"m = Matrix([(1, 2, 3), (4, 5, 6), (7, 8, 9)])"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 24,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"Matrix(((1.000, 2.000, 3.000,), (4.000, 5.000, 6.000,), (7.000, 8.000, 9.000,)))"
|
|
]
|
|
},
|
|
"execution_count": 24,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"m"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 25,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"sample_package.matrix.Matrix"
|
|
]
|
|
},
|
|
"execution_count": 25,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"type(m)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "skip"
|
|
}
|
|
},
|
|
"source": [
|
|
"Furthermore, the classes are designed for easier maintenence in the long-run.\n",
|
|
"\n",
|
|
"For example, the `Matrix/Vector.storage` and `Matrix/Vector.typing` class attributes replace the \"hard coded\" [tuple() <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_py.png\">](https://docs.python.org/3/library/functions.html#func-tuple) and [float() <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_py.png\">](https://docs.python.org/3/library/functions.html#float) built-ins in the `.__init__()` methods: As `self.storage` and `self.typing` are not defined on the *instances*, Python automatically looks them up on the *classes*."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 26,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"tuple"
|
|
]
|
|
},
|
|
"execution_count": 26,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"Vector.storage"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 27,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"float"
|
|
]
|
|
},
|
|
"execution_count": 27,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"Vector.typing"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 28,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"\u001b[0;31mSignature:\u001b[0m \u001b[0mVector\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__init__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdata\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
|
|
"\u001b[0;31mSource:\u001b[0m \n",
|
|
" \u001b[0;32mdef\u001b[0m \u001b[0m__init__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdata\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
|
|
"\u001b[0;34m\u001b[0m \u001b[0;34m\"\"\"Create a new vector.\u001b[0m\n",
|
|
"\u001b[0;34m\u001b[0m\n",
|
|
"\u001b[0;34m Args:\u001b[0m\n",
|
|
"\u001b[0;34m data (sequence): the vector's entries\u001b[0m\n",
|
|
"\u001b[0;34m\u001b[0m\n",
|
|
"\u001b[0;34m Raises:\u001b[0m\n",
|
|
"\u001b[0;34m ValueError: if no entries are provided\u001b[0m\n",
|
|
"\u001b[0;34m\u001b[0m\n",
|
|
"\u001b[0;34m Example Usage:\u001b[0m\n",
|
|
"\u001b[0;34m >>> Vector([1, 2, 3])\u001b[0m\n",
|
|
"\u001b[0;34m Vector((1.000, 2.000, 3.000))\u001b[0m\n",
|
|
"\u001b[0;34m\u001b[0m\n",
|
|
"\u001b[0;34m >>> Vector(range(3))\u001b[0m\n",
|
|
"\u001b[0;34m Vector((0.000, 1.000, 2.000))\u001b[0m\n",
|
|
"\u001b[0;34m \"\"\"\u001b[0m\u001b[0;34m\u001b[0m\n",
|
|
"\u001b[0;34m\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_entries\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstorage\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtyping\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mx\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mdata\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
|
|
"\u001b[0;34m\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
|
|
"\u001b[0;34m\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"a vector must have at least one entry\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
|
|
"\u001b[0;31mFile:\u001b[0m ~/repos/intro-to-python/11_classes/sample_package/vector.py\n",
|
|
"\u001b[0;31mType:\u001b[0m function\n"
|
|
]
|
|
},
|
|
"metadata": {},
|
|
"output_type": "display_data"
|
|
}
|
|
],
|
|
"source": [
|
|
"Vector.__init__??"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Both `Matrix/Vector.storage` and `Matrix/Vector.typing` themselves reference the `DEFAULT_ENTRIES_STORAGE` and `DEFAULT_ENTRY_TYPE` constants in the [*utils.py* <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_gh.png\">](https://github.com/webartifex/intro-to-python/blob/develop/11_classes/sample_package/utils.py) module. This way, we could, for example, change only the constants and thereby also change how the `._entries` are stored internally in both classes. Also, this single **[single source of truth <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_wiki.png\">](https://en.wikipedia.org/wiki/Single_source_of_truth)** ensures that both classes are consistent with each other at all times."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 29,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"tuple"
|
|
]
|
|
},
|
|
"execution_count": 29,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"utils.DEFAULT_ENTRIES_STORAGE"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 30,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"float"
|
|
]
|
|
},
|
|
"execution_count": 30,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"utils.DEFAULT_ENTRY_TYPE"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"For the same reasons, we also replace the \"hard coded\" references to the `Vector` and `Matrix` classes within the various methods.\n",
|
|
"\n",
|
|
"Every instance object has an automatically set `.__class__` attribute referencing its class."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 31,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"sample_package.matrix.Matrix"
|
|
]
|
|
},
|
|
"execution_count": 31,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"m.__class__"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Of course, we could also use the [type() <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_py.png\">](https://docs.python.org/3/library/functions.html#type) built-in instead."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 32,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"sample_package.matrix.Matrix"
|
|
]
|
|
},
|
|
"execution_count": 32,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"type(m)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"So, for example, the `Matrix.transpose()` method makes a `self.__class__(...)` instead of a `Matrix(...)` call."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 33,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"\u001b[0;31mSignature:\u001b[0m \u001b[0mMatrix\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtranspose\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
|
|
"\u001b[0;31mSource:\u001b[0m \n",
|
|
" \u001b[0;32mdef\u001b[0m \u001b[0mtranspose\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
|
|
"\u001b[0;34m\u001b[0m \u001b[0;34m\"\"\"Switch the rows and columns of a Matrix.\u001b[0m\n",
|
|
"\u001b[0;34m\u001b[0m\n",
|
|
"\u001b[0;34m Returns:\u001b[0m\n",
|
|
"\u001b[0;34m matrix (Matrix)\u001b[0m\n",
|
|
"\u001b[0;34m\u001b[0m\n",
|
|
"\u001b[0;34m Example Usage:\u001b[0m\n",
|
|
"\u001b[0;34m >>> m = Matrix([(1, 2), (3, 4)])\u001b[0m\n",
|
|
"\u001b[0;34m >>> m\u001b[0m\n",
|
|
"\u001b[0;34m Matrix(((1.000, 2.000,), (3.000, 4.000,)))\u001b[0m\n",
|
|
"\u001b[0;34m >>> m.transpose()\u001b[0m\n",
|
|
"\u001b[0;34m Matrix(((1.000, 3.000,), (2.000, 4.000,)))\u001b[0m\n",
|
|
"\u001b[0;34m \"\"\"\u001b[0m\u001b[0;34m\u001b[0m\n",
|
|
"\u001b[0;34m\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__class__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mzip\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_entries\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
|
|
"\u001b[0;31mFile:\u001b[0m ~/repos/intro-to-python/11_classes/sample_package/matrix.py\n",
|
|
"\u001b[0;31mType:\u001b[0m function\n"
|
|
]
|
|
},
|
|
"metadata": {},
|
|
"output_type": "display_data"
|
|
}
|
|
],
|
|
"source": [
|
|
"Matrix.transpose??"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Whenever we need a `str` representation of a class's name, we use the `.__name__` attribute on the class, ..."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 34,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"'Matrix'"
|
|
]
|
|
},
|
|
"execution_count": 34,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"Matrix.__name__"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"... or access it via the `.__class__` attribute on an instance."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 35,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"'Matrix'"
|
|
]
|
|
},
|
|
"execution_count": 35,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"m.__class__.__name__"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"For example, the `.__repr__()` and `.__str__()` methods make use of that."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 36,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"\u001b[0;31mSignature:\u001b[0m \u001b[0mMatrix\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__repr__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
|
|
"\u001b[0;31mSource:\u001b[0m \n",
|
|
" \u001b[0;32mdef\u001b[0m \u001b[0m__repr__\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
|
|
"\u001b[0;34m\u001b[0m \u001b[0;34m\"\"\"Text representation of a Matrix.\"\"\"\u001b[0m\u001b[0;34m\u001b[0m\n",
|
|
"\u001b[0;34m\u001b[0m \u001b[0mname\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__class__\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m__name__\u001b[0m\u001b[0;34m\u001b[0m\n",
|
|
"\u001b[0;34m\u001b[0m \u001b[0margs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m\", \"\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\u001b[0m\n",
|
|
"\u001b[0;34m\u001b[0m \u001b[0;34m\"(\"\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0;34m\", \"\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mjoin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34mf\"{c:.3f}\"\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mc\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mr\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0;34m\",)\"\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mr\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_entries\u001b[0m\u001b[0;34m\u001b[0m\n",
|
|
"\u001b[0;34m\u001b[0m \u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
|
|
"\u001b[0;34m\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0;34mf\"{name}(({args}))\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
|
|
"\u001b[0;31mFile:\u001b[0m ~/repos/intro-to-python/11_classes/sample_package/matrix.py\n",
|
|
"\u001b[0;31mType:\u001b[0m function\n"
|
|
]
|
|
},
|
|
"metadata": {},
|
|
"output_type": "display_data"
|
|
}
|
|
],
|
|
"source": [
|
|
"Matrix.__repr__??"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"In order to not have to \"hard code\" the name of *another* class (e.g., the `Vector.as_matrix()` method references the `Matrix` class), we apply the following \"hack:\" First, we store a reference to the other class as a class attribute (e.g., `Matrix.vector_cls` and `Vector.matrix_cls`), and then reference that attribute within the methods, just like `.storage` and `.typing` above."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 37,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"sample_package.vector.Vector"
|
|
]
|
|
},
|
|
"execution_count": 37,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"Matrix.vector_cls"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 38,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"sample_package.matrix.Matrix"
|
|
]
|
|
},
|
|
"execution_count": 38,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"Vector.matrix_cls"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"As an example, the `Vector.as_matrix()` method makes a `self.matrix_cls(...)` instead of a `Matrix(...)` call."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 39,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"\u001b[0;31mSignature:\u001b[0m \u001b[0mVector\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mas_matrix\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcolumn\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
|
|
"\u001b[0;31mSource:\u001b[0m \n",
|
|
" \u001b[0;32mdef\u001b[0m \u001b[0mas_matrix\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcolumn\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
|
|
"\u001b[0;34m\u001b[0m \u001b[0;34m\"\"\"Get a Matrix representation of a Vector.\u001b[0m\n",
|
|
"\u001b[0;34m\u001b[0m\n",
|
|
"\u001b[0;34m Args:\u001b[0m\n",
|
|
"\u001b[0;34m column (bool): if the vector is interpreted as a\u001b[0m\n",
|
|
"\u001b[0;34m column vector or a row vector; defaults to True\u001b[0m\n",
|
|
"\u001b[0;34m\u001b[0m\n",
|
|
"\u001b[0;34m Returns:\u001b[0m\n",
|
|
"\u001b[0;34m matrix (matrix.Matrix)\u001b[0m\n",
|
|
"\u001b[0;34m\u001b[0m\n",
|
|
"\u001b[0;34m Example Usage:\u001b[0m\n",
|
|
"\u001b[0;34m >>> v = Vector([1, 2, 3])\u001b[0m\n",
|
|
"\u001b[0;34m >>> v.as_matrix()\u001b[0m\n",
|
|
"\u001b[0;34m Matrix(((1.000,), (2.000,), (3.000,)))\u001b[0m\n",
|
|
"\u001b[0;34m >>> v.as_matrix(column=False)\u001b[0m\n",
|
|
"\u001b[0;34m Matrix(((1.000, 2.000, 3.000,)))\u001b[0m\n",
|
|
"\u001b[0;34m \"\"\"\u001b[0m\u001b[0;34m\u001b[0m\n",
|
|
"\u001b[0;34m\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mcolumn\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\n",
|
|
"\u001b[0;34m\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmatrix_cls\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mx\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\n",
|
|
"\u001b[0;34m\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmatrix_cls\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mx\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
|
|
"\u001b[0;31mFile:\u001b[0m ~/repos/intro-to-python/11_classes/sample_package/vector.py\n",
|
|
"\u001b[0;31mType:\u001b[0m function\n"
|
|
]
|
|
},
|
|
"metadata": {},
|
|
"output_type": "display_data"
|
|
}
|
|
],
|
|
"source": [
|
|
"Vector.as_matrix??"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "skip"
|
|
}
|
|
},
|
|
"source": [
|
|
"For completeness sake, we mention that in the final `Vector` and `Matrix` classes, the `.__sub__()` and `.__rsub__()` methods use the negation operator implemented in `.__neg__()` and then dispatch to `.__add__()` instead of implementing the subtraction logic themselves."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## \"Real-life\" Experiment"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "skip"
|
|
}
|
|
},
|
|
"source": [
|
|
"Let's do some math with bigger `Matrix` and `Vector` instances."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 40,
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"import random"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 41,
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "skip"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"random.seed(42)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "skip"
|
|
}
|
|
},
|
|
"source": [
|
|
"We initialize `m` as a $100x50$ dimensional `Matrix` with random numbers in the range between `0` and `1_000`."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 42,
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "fragment"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"m = Matrix((1_000 * random.random() for _ in range(50)) for _ in range(100))"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "skip"
|
|
}
|
|
},
|
|
"source": [
|
|
"We quickly lose track with all the numbers in the `Matrix`, which is why we implemented the `__str__()` method as a summary representation."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 43,
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "skip"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"Matrix(((639.427, 25.011, 275.029, 223.211, 736.471, 676.699, 892.180, 86.939, 421.922, 29.797, 218.638, 505.355, 26.536, 198.838, 649.884, 544.941, 220.441, 589.266, 809.430, 6.499, 805.819, 698.139, 340.251, 155.479, 957.213, 336.595, 92.746, 96.716, 847.494, 603.726, 807.128, 729.732, 536.228, 973.116, 378.534, 552.041, 829.405, 618.520, 861.707, 577.352, 704.572, 45.824, 227.898, 289.388, 79.792, 232.791, 101.001, 277.974, 635.684, 364.832,), (370.181, 209.507, 266.978, 936.655, 648.035, 609.131, 171.139, 729.127, 163.402, 379.455, 989.523, 640.000, 556.950, 684.614, 842.852, 776.000, 229.048, 32.100, 315.453, 267.741, 210.983, 942.910, 876.368, 314.678, 655.439, 395.632, 914.548, 458.852, 264.880, 246.628, 561.368, 262.742, 584.586, 897.823, 399.401, 219.321, 997.538, 509.526, 90.909, 47.116, 109.649, 627.446, 792.079, 422.160, 63.528, 381.619, 996.121, 529.114, 971.078, 860.780,), (11.481, 720.722, 681.710, 536.970, 266.825, 640.962, 111.552, 434.765, 453.724, 953.816, 875.853, 263.389, 500.586, 178.652, 912.628, 870.519, 298.445, 638.949, 608.970, 152.839, 762.511, 539.379, 778.626, 530.354, 0.572, 324.156, 19.477, 929.099, 878.722, 831.666, 307.514, 57.925, 878.010, 946.949, 85.653, 485.990, 69.213, 760.602, 765.834, 128.391, 475.282, 549.804, 265.057, 872.433, 423.138, 211.798, 539.296, 729.931, 201.151, 311.716,), (995.149, 649.878, 438.100, 517.576, 121.004, 224.697, 338.086, 588.309, 230.115, 220.217, 70.993, 631.103, 228.942, 905.420, 859.635, 70.857, 238.005, 668.978, 214.237, 132.312, 935.514, 571.043, 472.671, 784.619, 807.497, 190.410, 96.931, 431.051, 423.579, 467.025, 729.076, 673.365, 984.165, 98.418, 402.621, 339.303, 861.673, 248.656, 190.209, 448.614, 421.882, 278.545, 249.806, 923.266, 443.131, 861.349, 550.325, 50.588, 999.282, 836.028,), (968.996, 926.367, 848.696, 166.311, 485.641, 213.747, 401.040, 58.635, 378.973, 985.309, 265.203, 784.071, 455.008, 423.007, 957.318, 995.423, 555.768, 718.408, 154.797, 296.708, 968.709, 579.180, 542.195, 747.976, 57.165, 584.178, 502.850, 852.720, 157.433, 960.779, 80.111, 185.825, 595.035, 675.213, 235.204, 119.887, 890.287, 246.215, 594.519, 619.382, 419.225, 583.672, 522.783, 934.706, 204.259, 716.192, 238.686, 395.786, 671.690, 299.997,), (316.177, 751.864, 72.543, 458.286, 998.454, 996.096, 73.261, 213.154, 265.200, 933.259, 880.864, 879.270, 369.527, 157.747, 833.745, 703.540, 611.678, 987.233, 653.976, 7.823, 817.104, 299.379, 663.389, 938.930, 134.291, 115.429, 107.036, 553.224, 272.348, 604.830, 717.612, 203.597, 634.238, 263.984, 488.532, 905.336, 846.104, 92.298, 423.576, 276.680, 3.546, 771.119, 637.113, 261.955, 741.231, 551.680, 427.687, 9.670, 75.244, 883.106,), (903.929, 545.590, 834.595, 582.510, 148.094, 127.446, 308.258, 898.981, 796.122, 860.703, 898.925, 210.077, 249.530, 102.794, 780.116, 884.135, 406.377, 620.662, 154.553, 929.881, 864.606, 976.206, 810.772, 881.416, 24.786, 736.564, 332.185, 930.816, 802.235, 864.064, 810.749, 266.806, 787.375, 108.096, 872.167, 858.593, 222.434, 816.587, 460.303, 305.191, 795.345, 227.595, 23.664, 193.130, 328.262, 864.353, 966.889, 279.125, 641.482, 399.678,), (981.150, 536.216, 939.237, 115.342, 970.401, 178.568, 962.534, 265.466, 108.403, 434.564, 728.545, 313.677, 606.209, 511.423, 385.195, 576.588, 254.723, 708.785, 1.691, 925.575, 538.452, 719.430, 741.950, 670.629, 364.221, 69.974, 664.238, 330.200, 313.916, 848.015, 719.754, 300.322, 309.285, 408.393, 402.400, 295.655, 127.288, 420.446, 940.364, 677.318, 902.806, 615.515, 300.950, 547.937, 0.406, 286.914, 429.888, 579.985, 654.706, 464.988,), (442.160, 213.701, 473.186, 901.181, 796.025, 169.691, 84.796, 515.452, 632.941, 335.188, 818.423, 751.138, 672.796, 224.641, 199.130, 24.425, 244.843, 475.136, 849.738, 72.828, 414.441, 629.765, 194.435, 696.354, 494.377, 243.984, 656.058, 5.545, 750.964, 770.046, 106.587, 425.146, 175.887, 957.966, 517.958, 50.218, 249.198, 848.336, 456.462, 801.417, 667.578, 987.892, 595.452, 950.040, 891.426, 612.652, 719.274, 504.778, 830.569, 547.872,), (897.208, 743.655, 474.674, 259.192, 247.240, 637.661, 765.814, 521.300, 626.748, 274.597, 77.483, 285.728, 271.715, 319.710, 540.152, 138.374, 231.261, 693.950, 706.419, 64.229, 407.599, 542.611, 415.774, 206.834, 420.144, 904.838, 584.079, 695.523, 856.732, 765.595, 380.381, 5.896, 351.759, 753.475, 853.448, 953.430, 419.021, 747.516, 546.132, 603.253, 220.539, 219.422, 435.836, 29.025, 336.130, 679.142, 404.317, 165.045, 467.390, 127.628,), (622.257, 26.966, 394.020, 564.392, 27.102, 642.750, 135.699, 461.698, 50.285, 379.104, 211.660, 326.846, 761.230, 379.126, 752.010, 831.924, 252.272, 81.906, 19.383, 539.419, 999.908, 349.960, 650.144, 781.233, 651.755, 754.233, 949.612, 199.361, 20.380, 152.382, 126.221, 669.459, 563.970, 217.965, 699.465, 766.898, 167.789, 607.247, 747.926, 114.533, 819.301, 964.721, 108.099, 25.678, 311.957, 677.347, 958.173, 396.654, 715.015, 75.996,), (690.614, 627.242, 101.901, 772.481, 850.293, 600.412, 121.055, 983.844, 782.635, 347.204, 428.378, 370.571, 505.961, 341.231, 849.576, 822.331, 105.539, 960.788, 635.585, 828.707, 707.309, 435.487, 733.795, 965.474, 270.082, 808.199, 538.173, 483.498, 435.574, 731.026, 268.396, 851.713, 830.731, 86.663, 881.631, 243.863, 464.708, 610.332, 378.989, 28.700, 850.953, 181.840, 212.120, 797.832, 340.339, 880.320, 701.184, 276.269, 10.151, 948.063,), (85.613, 720.075, 488.578, 758.165, 690.609, 645.903, 490.821, 792.933, 93.053, 221.596, 691.787, 306.206, 581.556, 473.260, 530.922, 425.504, 745.935, 330.791, 702.855, 270.916, 251.404, 120.656, 192.584, 119.555, 535.864, 762.190, 185.150, 216.385, 484.199, 724.585, 976.607, 524.637, 282.999, 100.526, 194.118, 227.483, 179.442, 14.148, 534.135, 274.311, 974.295, 553.359, 697.417, 126.279, 868.461, 490.879, 872.720, 574.064, 469.397, 440.469,), (184.364, 51.377, 941.064, 477.729, 822.116, 400.707, 74.082, 629.446, 53.609, 149.198, 562.840, 303.836, 993.918, 118.452, 764.443, 606.318, 790.741, 225.687, 522.573, 450.514, 442.721, 860.167, 990.031, 305.380, 621.027, 609.631, 740.089, 947.590, 207.788, 211.025, 660.428, 157.057, 173.814, 75.065, 2.676, 450.504, 593.811, 291.259, 231.476, 706.956, 702.988, 454.031, 687.385, 923.911, 787.828, 625.058, 661.183, 933.668, 425.139, 544.562,), (647.635, 908.411, 826.631, 71.410, 165.923, 307.612, 748.958, 569.207, 288.611, 124.354, 688.678, 699.734, 942.676, 500.472, 493.795, 80.442, 39.861, 432.029, 322.322, 250.368, 91.327, 961.911, 835.959, 575.199, 950.786, 999.572, 672.282, 269.511, 40.232, 756.269, 470.501, 651.509, 916.073, 181.489, 585.330, 634.785, 491.726, 91.242, 347.961, 333.308, 670.134, 857.733, 329.804, 693.674, 288.218, 945.194, 813.566, 550.097, 454.826, 314.517,), (323.274, 970.185, 404.175, 514.596, 988.119, 657.660, 542.594, 413.248, 187.583, 361.779, 756.443, 625.409, 759.991, 203.558, 549.220, 927.673, 438.116, 698.250, 121.426, 973.147, 608.872, 239.297, 158.378, 550.839, 552.251, 93.209, 992.257, 912.930, 461.448, 117.466, 832.143, 498.376, 716.603, 508.872, 273.425, 834.724, 980.245, 243.731, 551.265, 383.586, 921.868, 508.241, 879.326, 864.027, 276.247, 790.006, 414.942, 934.248, 507.738, 820.549,), (282.839, 298.556, 586.938, 998.902, 489.640, 148.595, 538.581, 345.124, 551.917, 543.430, 455.345, 321.777, 188.652, 697.498, 571.798, 233.562, 775.544, 43.647, 744.705, 705.228, 811.409, 386.079, 663.689, 820.748, 980.818, 495.329, 37.020, 502.291, 590.180, 869.700, 874.190, 440.306, 525.951, 456.928, 722.444, 409.979, 654.781, 154.361, 469.491, 969.204, 338.561, 692.705, 649.837, 851.765, 852.341, 859.342, 380.009, 316.661, 718.717, 759.402,), (872.383, 35.899, 68.421, 631.161, 920.929, 997.426, 746.766, 433.971, 98.443, 633.748, 872.579, 443.679, 694.001, 903.424, 45.991, 796.143, 293.368, 374.841, 145.570, 531.166, 565.928, 792.519, 169.984, 78.968, 870.840, 619.710, 240.830, 912.829, 143.118, 461.150, 253.977, 255.327, 9.397, 804.633, 901.209, 677.611, 157.976, 441.730, 345.566, 587.572, 638.939, 424.309, 250.098, 845.304, 199.217, 384.693, 483.208, 237.206, 571.923, 574.812,), (992.692, 295.231, 977.944, 658.230, 274.480, 565.929, 685.799, 744.669, 49.044, 606.406, 496.727, 904.155, 286.194, 798.860, 607.065, 352.321, 636.618, 620.891, 677.764, 720.928, 659.182, 838.337, 628.248, 903.404, 646.341, 308.933, 440.823, 579.574, 732.360, 90.133, 295.110, 747.481, 175.640, 132.160, 539.408, 971.490, 530.852, 913.487, 830.473, 256.970, 824.690, 481.848, 806.488, 746.559, 338.715, 115.170, 962.893, 140.757, 966.500, 860.141,), (724.217, 979.942, 967.270, 804.588, 365.775, 790.682, 13.919, 536.572, 454.786, 672.828, 672.341, 584.560, 822.417, 940.292, 108.346, 233.822, 25.025, 884.235, 561.407, 915.256, 221.367, 63.217, 823.855, 909.388, 302.190, 408.296, 139.777, 946.262, 304.365, 492.625, 97.192, 887.259, 135.664, 453.644, 670.486, 743.140, 945.974, 419.127, 742.269, 154.523, 414.885, 99.022, 489.347, 408.116, 951.522, 32.716, 370.530, 443.383, 950.555, 855.450,), (99.355, 685.680, 544.466, 977.843, 358.674, 398.140, 189.809, 122.160, 848.033, 454.717, 662.769, 641.704, 597.146, 21.357, 786.795, 243.569, 125.924, 564.578, 68.610, 765.157, 207.157, 215.951, 869.695, 328.560, 147.554, 900.531, 2.836, 858.406, 144.688, 129.992, 250.654, 174.497, 661.058, 25.780, 14.860, 789.985, 237.932, 323.771, 174.246, 52.399, 741.718, 526.086, 745.665, 476.246, 778.017, 513.238, 109.054, 503.839, 945.416, 43.365,), (783.227, 866.981, 521.451, 458.043, 964.026, 60.825, 478.982, 401.617, 686.097, 490.269, 909.701, 73.491, 80.790, 608.297, 65.682, 275.016, 633.077, 548.356, 325.185, 994.628, 530.557, 453.715, 605.427, 99.178, 701.779, 852.793, 650.917, 768.963, 720.840, 215.023, 451.555, 228.494, 338.932, 453.499, 415.990, 95.086, 426.764, 665.108, 374.301, 152.639, 922.985, 67.133, 831.772, 93.230, 96.564, 738.796, 811.769, 556.371, 586.465, 561.586,), (329.646, 122.231, 353.598, 665.341, 750.284, 868.092, 721.061, 968.399, 600.410, 351.646, 577.919, 212.739, 656.736, 224.245, 108.218, 845.373, 367.561, 762.606, 574.100, 807.221, 845.155, 974.547, 818.427, 613.573, 642.699, 26.254, 929.084, 829.461, 267.448, 180.416, 702.699, 308.985, 339.825, 6.106, 869.863, 566.321, 400.784, 141.875, 633.172, 30.657, 746.112, 215.133, 419.832, 340.896, 370.053, 721.596, 776.836, 567.594, 84.957, 52.609,), (157.410, 617.838, 673.969, 272.103, 661.939, 485.662, 442.044, 273.167, 754.943, 113.818, 429.914, 283.246, 678.486, 486.633, 667.133, 45.417, 395.263, 599.325, 7.687, 301.419, 211.234, 137.235, 255.520, 328.122, 7.730, 747.014, 175.695, 380.207, 703.671, 500.262, 833.354, 806.200, 72.075, 861.764, 42.302, 18.742, 921.162, 862.110, 575.759, 573.400, 709.499, 417.694, 115.173, 20.857, 324.768, 801.322, 618.125, 832.026, 919.770, 88.130,), (844.484, 243.316, 588.871, 523.963, 395.767, 310.275, 339.513, 333.069, 168.133, 510.483, 114.027, 509.952, 905.923, 349.375, 727.379, 818.949, 815.037, 236.269, 146.444, 197.272, 602.399, 760.215, 655.509, 177.146, 772.848, 494.117, 754.446, 759.877, 448.905, 924.154, 564.492, 635.298, 624.522, 864.247, 627.217, 150.957, 68.286, 442.208, 302.820, 274.674, 56.172, 507.337, 310.408, 451.914, 56.890, 831.697, 76.731, 864.250, 855.293, 615.008,), (507.068, 462.712, 554.316, 791.818, 895.877, 449.734, 809.816, 651.837, 321.527, 475.629, 150.861, 61.874, 103.502, 899.127, 343.438, 714.316, 504.549, 172.559, 247.744, 437.758, 439.422, 522.748, 158.746, 372.852, 282.894, 408.769, 338.367, 597.886, 789.227, 647.305, 65.912, 94.506, 678.379, 284.147, 723.734, 656.564, 906.343, 873.280, 333.362, 582.740, 141.428, 349.821, 967.697, 698.480, 391.958, 595.041, 938.002, 309.582, 376.679, 791.662,), (813.185, 670.116, 828.959, 738.775, 685.414, 526.393, 646.025, 423.406, 361.828, 362.598, 180.263, 214.193, 947.668, 486.271, 226.543, 137.565, 77.165, 844.428, 101.141, 770.875, 835.120, 883.682, 37.747, 336.764, 766.308, 131.049, 376.720, 162.247, 831.345, 771.098, 809.044, 165.539, 437.673, 410.859, 676.363, 237.530, 444.199, 284.928, 748.537, 448.928, 534.011, 309.468, 808.624, 469.016, 835.113, 367.841, 947.130, 984.440, 461.680, 281.772,), (381.872, 527.460, 966.268, 816.891, 801.259, 138.399, 250.003, 641.179, 874.117, 554.541, 102.590, 845.892, 851.166, 285.063, 763.117, 272.791, 905.306, 147.349, 437.473, 946.413, 222.038, 451.128, 349.585, 26.670, 53.257, 502.007, 235.778, 994.525, 374.913, 28.188, 930.826, 839.176, 649.961, 791.381, 137.600, 286.879, 829.762, 696.072, 138.793, 705.536, 448.601, 5.251, 79.226, 255.924, 834.963, 548.804, 727.235, 527.772, 111.187, 288.102,), (301.151, 47.749, 419.826, 793.899, 457.114, 110.858, 905.147, 596.739, 16.435, 515.376, 241.938, 143.577, 429.239, 614.810, 240.564, 416.568, 664.371, 85.614, 974.654, 67.679, 526.059, 507.328, 988.331, 554.152, 390.454, 470.135, 635.671, 981.039, 253.650, 16.242, 788.520, 344.802, 732.941, 628.257, 771.501, 735.187, 332.519, 44.336, 546.014, 813.509, 175.089, 779.143, 464.623, 695.389, 631.736, 811.498, 63.101, 776.190, 457.680, 293.443,), (43.806, 199.470, 41.906, 933.371, 515.384, 989.123, 543.031, 253.314, 753.291, 191.103, 356.974, 780.842, 865.798, 331.925, 124.475, 368.019, 889.487, 743.308, 894.637, 386.645, 973.724, 496.203, 497.523, 924.310, 519.276, 801.148, 727.081, 78.927, 602.453, 822.341, 545.474, 321.211, 80.069, 660.919, 306.496, 602.622, 426.116, 689.765, 351.547, 42.355, 870.037, 352.559, 998.151, 274.555, 980.027, 947.904, 75.041, 637.513, 363.311, 801.096,), (679.411, 952.789, 142.779, 607.573, 781.312, 34.799, 67.233, 778.515, 366.328, 382.854, 567.245, 605.095, 679.062, 948.824, 372.013, 763.084, 573.922, 529.460, 398.034, 649.561, 249.612, 113.449, 735.675, 499.044, 386.987, 561.673, 261.777, 260.290, 446.273, 996.365, 285.577, 916.479, 491.200, 122.637, 852.826, 452.043, 898.679, 445.111, 87.791, 681.929, 845.521, 319.588, 347.425, 64.939, 542.171, 891.332, 851.362, 711.809, 927.324, 637.700,), (793.696, 508.756, 121.362, 200.980, 138.877, 790.373, 26.284, 554.021, 368.911, 803.662, 551.647, 611.948, 86.215, 309.291, 999.595, 718.870, 525.696, 769.165, 823.339, 73.751, 972.380, 642.339, 449.974, 680.109, 344.515, 877.960, 780.263, 639.794, 181.963, 966.265, 432.618, 910.712, 55.413, 124.161, 153.015, 164.657, 322.661, 709.332, 346.023, 940.904, 894.926, 845.934, 250.605, 635.057, 550.841, 125.170, 302.825, 533.478, 502.573, 168.636,), (941.607, 154.194, 658.733, 720.633, 605.139, 842.530, 563.618, 825.236, 28.373, 45.462, 641.454, 576.771, 651.130, 766.959, 416.587, 638.991, 498.038, 627.164, 289.672, 956.650, 482.945, 804.688, 684.991, 297.434, 72.973, 59.913, 439.605, 484.251, 204.023, 606.660, 312.582, 718.363, 734.200, 860.777, 975.374, 130.766, 370.540, 561.651, 319.116, 466.473, 267.472, 247.919, 96.812, 290.212, 384.150, 615.377, 248.270, 865.308, 159.700, 327.436,), (577.687, 312.715, 763.121, 498.266, 514.725, 498.760, 308.540, 23.176, 945.233, 505.444, 966.687, 215.144, 352.895, 50.540, 494.894, 882.339, 654.260, 470.587, 536.691, 847.172, 430.928, 882.456, 727.508, 763.857, 365.937, 400.582, 570.282, 194.655, 553.223, 73.532, 504.256, 764.404, 279.721, 989.091, 680.399, 118.811, 975.083, 393.904, 794.897, 339.085, 938.949, 754.965, 199.058, 509.123, 500.078, 45.303, 137.036, 333.041, 473.744, 456.989,), (606.261, 515.506, 327.966, 613.068, 162.502, 990.616, 739.319, 299.234, 336.373, 828.289, 532.340, 708.740, 299.791, 815.749, 368.358, 673.806, 979.898, 583.702, 796.755, 725.324, 688.044, 26.647, 474.590, 967.071, 782.904, 776.162, 577.634, 721.400, 583.523, 170.512, 629.025, 619.736, 841.167, 147.776, 680.727, 31.571, 948.205, 109.896, 18.937, 313.692, 151.431, 690.500, 410.377, 774.972, 920.521, 872.818, 735.837, 62.281, 138.082, 207.342,), (325.050, 662.227, 525.477, 313.753, 173.182, 912.124, 342.327, 354.287, 771.990, 720.925, 643.309, 693.313, 610.077, 192.264, 246.519, 558.087, 224.867, 972.911, 297.615, 289.004, 207.278, 704.988, 317.041, 348.803, 933.700, 795.405, 273.458, 121.874, 676.622, 379.694, 980.161, 818.377, 954.609, 804.616, 290.453, 287.630, 714.141, 346.364, 442.376, 256.444, 479.079, 202.068, 538.578, 933.024, 696.171, 137.273, 615.677, 586.830, 242.458, 669.834,), (531.041, 637.945, 52.491, 413.301, 717.358, 100.545, 770.766, 5.181, 550.353, 929.100, 406.907, 935.032, 878.400, 477.449, 199.456, 963.914, 321.168, 645.898, 907.937, 89.461, 574.133, 535.152, 723.118, 936.669, 913.230, 175.065, 882.245, 175.789, 919.635, 997.172, 396.995, 495.384, 936.609, 962.131, 926.040, 876.743, 9.267, 567.962, 107.301, 982.994, 284.562, 989.099, 543.300, 493.912, 938.561, 851.060, 468.021, 192.811, 112.647, 162.494,), (458.914, 257.265, 186.199, 736.618, 790.768, 567.781, 757.283, 175.495, 856.147, 897.043, 826.990, 515.281, 86.738, 669.256, 184.781, 140.612, 323.602, 248.047, 260.785, 235.521, 753.757, 954.035, 301.946, 722.883, 11.436, 653.683, 692.769, 62.124, 118.225, 306.806, 405.417, 502.520, 895.118, 703.557, 310.978, 117.416, 916.130, 295.038, 614.625, 219.129, 133.569, 153.186, 747.735, 605.739, 415.846, 549.235, 470.828, 537.518, 664.094, 218.412,), (247.465, 754.740, 873.135, 81.870, 446.748, 703.766, 78.103, 564.169, 61.758, 547.649, 505.487, 572.702, 149.852, 328.118, 520.342, 116.240, 205.401, 583.148, 90.942, 510.375, 808.692, 453.432, 513.248, 456.798, 57.737, 462.378, 806.915, 723.280, 395.949, 816.453, 745.804, 578.311, 45.290, 344.529, 63.760, 994.124, 934.583, 69.019, 933.776, 31.735, 408.867, 768.972, 765.828, 978.333, 645.881, 420.362, 992.857, 382.480, 869.620, 906.767,), (375.646, 682.730, 661.793, 539.300, 653.534, 347.770, 178.474, 537.258, 528.843, 727.858, 222.690, 3.473, 22.735, 298.363, 673.500, 544.445, 531.934, 823.360, 247.512, 346.160, 275.650, 937.410, 725.024, 112.845, 809.478, 419.241, 766.053, 883.757, 15.646, 206.082, 100.897, 33.576, 597.785, 703.286, 48.676, 740.541, 402.265, 234.339, 217.269, 863.730, 56.444, 503.896, 289.263, 815.786, 731.517, 318.904, 597.918, 672.532, 320.665, 301.764,), (143.260, 660.212, 221.043, 300.501, 60.958, 948.520, 879.714, 911.578, 625.993, 427.201, 495.621, 972.290, 941.586, 671.343, 785.805, 318.734, 416.325, 149.218, 376.460, 754.416, 473.519, 849.341, 300.736, 707.577, 805.776, 914.741, 562.386, 967.786, 557.287, 134.093, 242.859, 203.337, 646.706, 922.226, 847.133, 92.464, 724.585, 190.482, 268.462, 673.672, 602.922, 873.620, 188.163, 761.696, 724.305, 558.850, 479.394, 869.474, 332.964, 957.020,), (15.334, 937.160, 962.078, 117.316, 999.572, 478.921, 242.593, 604.402, 204.513, 915.126, 552.079, 775.514, 380.662, 533.650, 359.260, 261.562, 512.817, 497.277, 98.608, 981.318, 469.490, 839.731, 914.330, 370.705, 413.930, 562.525, 221.274, 145.923, 260.774, 934.758, 579.143, 417.578, 152.411, 329.865, 379.840, 833.363, 499.301, 654.608, 684.847, 257.327, 821.592, 966.508, 641.694, 490.596, 168.234, 794.976, 169.266, 720.314, 488.316, 916.899,), (542.137, 641.809, 58.732, 33.824, 846.697, 945.188, 668.216, 764.339, 412.392, 842.545, 231.433, 707.170, 9.141, 505.733, 373.201, 617.835, 666.755, 616.519, 483.204, 487.854, 6.612, 551.644, 11.851, 529.418, 274.741, 977.479, 17.143, 813.157, 674.033, 806.168, 909.773, 107.016, 96.314, 148.897, 191.932, 526.456, 815.214, 267.325, 396.896, 373.052, 406.027, 565.002, 990.233, 225.857, 684.042, 847.867, 653.736, 858.219, 759.586, 93.501,), (379.264, 552.701, 56.115, 9.450, 171.384, 499.858, 433.910, 784.376, 565.857, 857.960, 95.362, 528.159, 42.552, 211.417, 868.117, 887.554, 475.500, 46.562, 74.348, 925.585, 899.312, 563.510, 32.902, 928.766, 314.485, 961.469, 587.036, 752.254, 712.711, 398.296, 76.937, 162.450, 240.472, 834.651, 389.157, 896.526, 331.730, 755.609, 139.951, 988.478, 724.164, 500.793, 974.323, 53.696, 437.088, 838.675, 340.593, 769.006, 954.858, 396.703,), (773.555, 29.626, 273.327, 992.586, 490.603, 355.811, 941.143, 431.848, 679.695, 660.672, 85.694, 618.616, 798.055, 713.109, 82.038, 154.221, 711.677, 633.901, 739.655, 316.678, 106.551, 5.195, 308.267, 359.917, 269.766, 132.507, 187.392, 448.844, 554.740, 408.044, 26.262, 353.914, 93.064, 598.044, 324.430, 385.238, 291.847, 387.800, 84.700, 901.136, 905.208, 978.173, 571.960, 169.583, 380.732, 138.840, 301.131, 493.124, 63.267, 434.676,), (421.102, 484.231, 76.921, 251.700, 246.590, 625.034, 593.806, 195.548, 106.972, 304.658, 948.823, 332.217, 620.192, 804.076, 329.542, 334.736, 815.475, 859.508, 974.225, 136.124, 320.665, 947.279, 200.851, 314.183, 964.575, 968.725, 291.448, 694.958, 491.007, 575.879, 242.424, 376.055, 816.495, 392.935, 113.888, 563.851, 592.227, 545.629, 681.713, 550.099, 953.005, 461.622, 708.367, 438.455, 291.331, 692.835, 818.966, 795.657, 409.142, 499.303,), (633.336, 242.021, 658.663, 715.236, 789.077, 73.965, 990.701, 479.235, 400.805, 506.613, 920.392, 691.709, 543.645, 790.721, 359.529, 895.502, 536.906, 638.180, 84.982, 768.954, 657.602, 355.009, 647.000, 44.297, 983.608, 677.472, 399.618, 752.683, 965.717, 430.456, 10.548, 258.738, 510.676, 518.798, 580.518, 575.235, 445.779, 391.134, 772.342, 588.590, 500.466, 344.967, 24.563, 104.549, 415.975, 961.728, 116.069, 940.676, 141.675, 311.890,), (455.333, 206.867, 482.926, 476.163, 438.166, 696.763, 318.909, 300.264, 810.186, 115.085, 849.180, 647.970, 677.139, 164.354, 983.900, 243.913, 174.453, 160.136, 559.849, 958.463, 231.856, 405.047, 184.452, 640.479, 432.134, 29.192, 614.107, 197.324, 592.203, 388.836, 704.736, 205.784, 752.325, 808.730, 62.564, 101.752, 871.979, 186.960, 325.985, 457.550, 262.353, 862.637, 527.715, 639.109, 596.971, 611.308, 587.005, 347.925, 845.518, 617.363,), (813.738, 705.988, 297.445, 614.485, 84.752, 133.948, 117.862, 305.380, 183.045, 693.437, 510.825, 418.239, 137.867, 383.710, 185.754, 635.502, 693.433, 645.260, 999.900, 554.913, 489.642, 140.297, 314.580, 451.001, 53.611, 359.039, 9.583, 136.535, 815.216, 963.829, 505.438, 494.970, 684.697, 415.630, 839.892, 488.700, 82.671, 30.861, 761.057, 292.090, 274.853, 537.609, 168.209, 457.321, 742.518, 765.920, 549.726, 113.211, 114.207, 775.113,), (823.283, 366.862, 822.611, 41.611, 718.980, 546.353, 989.776, 102.416, 830.071, 751.345, 297.709, 999.313, 449.732, 348.577, 816.729, 439.070, 993.958, 775.632, 236.946, 810.703, 587.924, 350.631, 710.754, 632.771, 165.982, 139.235, 206.620, 206.943, 59.358, 350.815, 281.085, 538.769, 323.654, 704.054, 289.333, 267.343, 858.017, 985.488, 679.299, 95.225, 962.772, 785.691, 918.769, 992.486, 867.048, 126.888, 866.079, 249.677, 711.395, 828.482,), (761.474, 676.235, 489.459, 577.426, 268.717, 414.225, 451.992, 633.628, 880.125, 93.095, 515.613, 278.226, 936.336, 369.071, 950.254, 327.289, 2.473, 774.135, 732.724, 730.932, 458.449, 664.144, 358.223, 63.331, 534.424, 217.830, 429.643, 211.851, 268.537, 828.344, 337.755, 577.934, 566.142, 485.338, 343.740, 682.552, 48.409, 99.575, 783.890, 459.582, 124.237, 857.652, 441.286, 0.676, 958.032, 202.318, 688.592, 131.913, 649.997, 158.977,), (932.726, 274.019, 654.588, 250.389, 371.844, 903.800, 165.525, 396.342, 305.509, 699.441, 234.144, 655.485, 703.698, 1.086, 476.807, 132.700, 226.191, 679.983, 9.287, 695.597, 817.109, 988.155, 422.314, 132.175, 70.828, 383.070, 730.763, 102.427, 313.351, 880.989, 137.129, 773.460, 753.158, 133.146, 992.940, 142.853, 530.508, 8.475, 650.020, 440.099, 722.432, 628.080, 151.374, 411.710, 686.566, 859.963, 86.688, 100.465, 752.446, 589.574,), (384.032, 963.249, 314.504, 139.830, 276.968, 84.249, 553.397, 600.008, 607.593, 778.970, 690.476, 847.892, 658.405, 301.649, 517.749, 509.523, 747.844, 295.542, 54.569, 897.913, 954.672, 494.888, 112.744, 499.583, 593.930, 528.287, 977.697, 986.883, 933.924, 131.983, 860.814, 568.380, 365.412, 682.942, 762.726, 954.453, 770.367, 16.689, 67.533, 262.185, 39.827, 60.469, 789.290, 506.611, 628.571, 501.049, 415.432, 701.811, 82.428, 536.565,), (616.047, 277.468, 309.907, 511.305, 203.197, 808.060, 536.390, 390.732, 634.294, 834.526, 681.056, 66.115, 698.676, 729.958, 846.468, 57.906, 86.213, 434.484, 453.372, 608.832, 309.290, 741.694, 740.658, 119.443, 707.901, 701.500, 163.833, 953.016, 523.005, 782.987, 720.766, 166.963, 126.931, 781.124, 268.764, 886.415, 771.430, 29.356, 807.108, 271.981, 63.872, 712.323, 576.652, 77.070, 455.198, 360.124, 499.610, 566.886, 367.688, 255.116,), (102.905, 573.912, 722.778, 228.404, 508.825, 44.038, 862.928, 244.551, 471.765, 382.979, 150.085, 931.160, 857.485, 552.865, 913.948, 740.666, 419.369, 321.802, 416.257, 720.288, 271.258, 77.887, 372.808, 502.041, 901.941, 179.344, 804.338, 981.414, 954.079, 68.926, 465.094, 282.307, 844.847, 327.301, 553.091, 7.969, 200.671, 563.807, 303.909, 622.718, 463.927, 591.691, 493.361, 772.613, 195.422, 900.443, 760.482, 245.127, 6.378, 410.036,), (232.998, 346.424, 839.574, 877.199, 950.990, 1.462, 657.304, 849.006, 727.215, 103.949, 529.814, 238.168, 492.029, 59.895, 996.959, 711.652, 93.027, 921.274, 897.287, 519.759, 700.847, 372.492, 974.555, 84.902, 95.577, 133.514, 819.963, 74.830, 567.821, 434.983, 964.218, 236.772, 260.991, 315.009, 800.817, 700.726, 735.353, 318.058, 271.956, 74.687, 202.713, 779.937, 584.708, 155.411, 164.375, 466.055, 406.513, 535.925, 964.635, 207.636,), (308.308, 265.008, 119.914, 157.615, 686.055, 826.387, 696.878, 40.330, 835.925, 327.794, 91.213, 248.219, 355.743, 513.460, 677.183, 260.167, 990.677, 31.082, 404.392, 452.201, 748.078, 249.853, 462.043, 803.897, 139.793, 11.957, 830.372, 982.567, 130.715, 823.673, 372.240, 630.298, 644.685, 582.324, 258.821, 812.747, 21.800, 64.472, 902.496, 443.431, 128.792, 905.078, 829.356, 331.550, 42.696, 460.995, 167.989, 573.884, 821.685, 394.999,), (29.482, 683.213, 172.807, 214.716, 187.151, 279.855, 883.424, 34.649, 619.177, 245.785, 295.105, 411.992, 550.689, 60.979, 279.776, 137.236, 199.458, 884.653, 525.814, 630.754, 802.168, 794.846, 989.404, 781.916, 359.112, 544.518, 484.679, 912.677, 502.393, 388.381, 179.816, 318.878, 219.020, 895.765, 778.538, 58.591, 991.531, 529.432, 766.842, 999.606, 973.980, 100.134, 656.864, 266.527, 816.285, 917.259, 55.909, 996.392, 219.412, 846.505,), (797.391, 354.805, 839.222, 845.221, 176.100, 592.520, 806.210, 697.627, 913.980, 28.207, 700.561, 947.559, 563.606, 563.109, 188.234, 988.006, 881.626, 492.227, 309.053, 490.436, 90.257, 232.623, 218.809, 526.449, 0.683, 917.896, 201.464, 130.490, 716.938, 918.781, 844.284, 323.589, 21.913, 586.609, 917.224, 774.366, 846.481, 860.669, 960.559, 373.591, 941.923, 395.596, 101.032, 301.765, 136.452, 157.504, 948.694, 791.843, 960.662, 649.180,), (174.203, 968.743, 693.560, 928.845, 786.992, 223.237, 588.950, 175.352, 306.823, 688.498, 127.348, 728.831, 948.788, 948.698, 391.601, 994.283, 965.184, 32.383, 602.389, 921.038, 967.532, 220.895, 565.550, 936.688, 140.643, 745.343, 237.996, 982.380, 167.887, 885.320, 88.726, 708.966, 639.103, 886.654, 446.630, 265.212, 249.541, 67.795, 256.658, 108.035, 1.281, 385.937, 732.584, 969.102, 884.552, 493.082, 378.713, 546.024, 101.429, 479.489,), (864.051, 650.970, 687.160, 162.657, 73.709, 845.762, 294.909, 318.717, 951.662, 74.200, 170.105, 375.458, 731.985, 547.046, 898.124, 93.105, 594.031, 613.645, 482.737, 30.993, 942.442, 164.997, 889.753, 157.104, 101.258, 205.550, 189.984, 697.197, 722.038, 729.974, 265.265, 281.523, 237.548, 49.635, 571.770, 839.855, 153.590, 360.829, 427.606, 294.549, 662.020, 600.216, 199.675, 25.736, 170.832, 291.811, 81.936, 843.769, 308.353, 397.467,), (489.097, 661.040, 91.137, 544.126, 184.881, 885.493, 369.402, 445.775, 263.296, 465.058, 226.242, 268.562, 61.639, 752.235, 667.468, 85.707, 343.791, 541.449, 970.706, 589.726, 553.602, 840.797, 818.405, 418.632, 535.514, 866.894, 474.824, 881.654, 476.262, 78.955, 902.777, 714.306, 502.101, 900.455, 800.450, 677.535, 620.273, 120.282, 757.189, 172.879, 984.368, 972.165, 808.461, 126.186, 423.375, 988.280, 435.393, 997.269, 627.226, 834.108,), (257.886, 910.804, 914.174, 67.012, 388.099, 397.355, 326.127, 276.201, 458.157, 873.466, 786.551, 623.058, 522.562, 419.594, 414.442, 148.200, 587.934, 758.377, 939.650, 924.928, 562.684, 100.990, 286.093, 535.633, 343.869, 410.890, 383.043, 485.585, 608.962, 37.466, 275.414, 143.853, 608.655, 693.661, 38.783, 889.574, 331.494, 237.579, 745.750, 920.835, 897.031, 20.233, 817.386, 303.055, 280.347, 491.619, 696.183, 98.217, 868.900, 134.386,), (974.219, 443.111, 825.823, 269.420, 416.773, 645.555, 187.936, 211.391, 823.969, 740.945, 759.493, 867.189, 821.017, 515.270, 158.972, 311.123, 506.795, 135.650, 851.295, 879.333, 28.948, 192.763, 832.930, 836.977, 249.490, 456.449, 918.031, 704.634, 273.977, 823.506, 505.126, 635.410, 123.873, 30.563, 372.467, 594.044, 177.584, 870.481, 586.880, 349.760, 163.514, 894.492, 748.961, 688.851, 285.069, 386.566, 162.907, 572.258, 964.918, 857.111,), (647.380, 677.695, 269.084, 409.507, 20.052, 780.304, 767.573, 8.898, 911.515, 647.372, 601.142, 8.464, 252.390, 805.086, 305.460, 967.024, 642.740, 423.807, 376.475, 348.709, 251.999, 466.698, 677.196, 824.311, 397.153, 102.312, 511.514, 662.355, 843.284, 374.230, 647.342, 609.050, 298.476, 108.105, 63.837, 988.361, 640.595, 861.492, 261.147, 711.094, 892.374, 298.791, 149.929, 765.474, 899.687, 805.430, 802.364, 600.033, 660.530, 680.756,), (721.283, 655.401, 997.469, 259.426, 418.566, 388.275, 35.319, 708.069, 572.042, 189.915, 726.550, 222.363, 534.635, 784.897, 906.527, 671.868, 507.315, 845.419, 840.639, 876.495, 181.136, 97.603, 127.944, 258.652, 808.344, 762.918, 183.068, 679.712, 335.632, 89.300, 355.283, 744.210, 307.085, 788.090, 331.317, 260.559, 294.051, 851.214, 470.537, 866.393, 583.575, 944.301, 71.216, 889.426, 500.477, 867.498, 381.669, 298.356, 54.062, 854.240,), (137.365, 200.297, 409.192, 569.404, 906.621, 457.571, 316.383, 715.668, 778.941, 487.581, 631.033, 176.824, 634.499, 4.714, 273.528, 761.193, 168.606, 764.484, 489.577, 763.569, 88.041, 614.480, 633.488, 403.393, 965.328, 383.316, 37.725, 199.414, 373.101, 14.077, 322.213, 833.229, 190.577, 676.748, 626.687, 248.823, 693.525, 344.350, 128.931, 383.550, 588.671, 167.020, 823.844, 298.202, 290.828, 727.832, 596.370, 337.835, 887.974, 995.472,), (342.733, 901.384, 359.251, 188.426, 948.084, 918.205, 403.392, 228.418, 727.169, 131.206, 734.077, 589.693, 168.985, 366.591, 650.540, 37.363, 876.544, 255.789, 534.733, 48.587, 994.680, 661.970, 653.568, 19.742, 689.750, 416.776, 380.254, 547.282, 474.396, 153.127, 695.192, 630.311, 301.116, 661.665, 662.483, 269.977, 605.634, 137.164, 830.653, 104.914, 718.766, 117.735, 114.013, 106.264, 198.647, 199.749, 262.994, 523.146, 201.673, 703.437,), (295.351, 39.406, 496.355, 207.694, 933.124, 330.604, 2.738, 671.633, 906.880, 835.232, 669.022, 149.144, 90.083, 511.705, 723.564, 101.290, 255.892, 231.160, 988.666, 296.022, 464.277, 99.809, 174.702, 39.445, 290.567, 801.596, 312.707, 738.540, 94.998, 758.204, 45.889, 851.999, 663.355, 170.512, 357.527, 437.715, 621.807, 878.476, 92.951, 814.964, 182.869, 400.778, 962.310, 271.833, 385.715, 850.672, 799.899, 648.846, 796.910, 113.057,), (696.170, 58.646, 942.467, 159.395, 416.028, 590.750, 802.265, 678.393, 181.261, 379.751, 358.599, 28.816, 684.464, 838.536, 973.445, 130.655, 920.398, 112.937, 411.284, 45.972, 261.613, 314.238, 704.568, 677.929, 767.529, 576.649, 565.012, 977.896, 669.844, 338.301, 523.103, 700.580, 95.242, 661.713, 248.577, 345.749, 676.296, 384.877, 839.033, 558.344, 987.792, 54.566, 643.399, 156.927, 848.846, 851.871, 869.416, 74.865, 491.648, 240.892,), (970.145, 50.351, 222.707, 643.317, 403.277, 235.000, 459.095, 801.261, 448.099, 856.589, 447.068, 118.707, 497.373, 653.373, 102.643, 412.339, 557.131, 0.170, 90.896, 604.203, 619.066, 304.598, 508.338, 206.851, 671.474, 950.355, 363.342, 54.275, 222.918, 454.460, 560.151, 619.758, 473.134, 657.167, 715.914, 114.023, 759.320, 221.747, 341.357, 829.884, 964.434, 291.984, 521.985, 702.096, 45.778, 164.155, 140.449, 716.856, 721.559, 106.962,), (610.852, 187.543, 930.216, 392.896, 457.046, 781.420, 716.788, 107.766, 414.470, 926.627, 837.466, 588.811, 772.145, 450.505, 658.457, 956.190, 134.636, 498.829, 530.364, 48.572, 935.308, 838.816, 482.932, 508.333, 921.162, 177.202, 578.554, 730.495, 128.382, 387.406, 600.546, 882.696, 504.110, 384.663, 979.501, 915.910, 762.375, 273.596, 963.594, 970.492, 452.846, 133.372, 412.745, 700.014, 748.427, 298.913, 701.494, 860.708, 711.874, 935.512,), (632.583, 200.889, 624.168, 290.579, 345.294, 672.374, 981.335, 650.086, 958.326, 503.893, 694.312, 322.381, 115.405, 352.238, 480.370, 570.638, 667.157, 417.478, 747.869, 841.389, 285.928, 847.301, 808.305, 522.730, 25.272, 145.327, 670.254, 199.902, 750.185, 160.935, 286.616, 250.561, 839.382, 690.595, 295.141, 753.594, 32.306, 814.026, 102.480, 868.035, 739.492, 864.841, 742.413, 561.271, 237.595, 784.307, 798.822, 287.639, 664.494, 926.485,), (387.555, 956.702, 975.823, 312.654, 552.125, 12.965, 251.341, 620.562, 780.925, 870.118, 829.983, 911.486, 704.629, 647.632, 755.108, 546.615, 603.387, 776.147, 964.290, 294.178, 177.426, 682.659, 186.977, 173.795, 513.847, 377.198, 428.508, 556.599, 130.067, 583.986, 255.016, 330.563, 709.689, 154.806, 153.703, 322.630, 50.855, 932.382, 615.609, 661.890, 490.551, 572.677, 358.086, 784.031, 317.859, 219.962, 183.869, 68.176, 505.140, 415.931,), (537.036, 91.946, 221.198, 213.354, 331.884, 360.798, 218.445, 752.656, 530.499, 996.631, 823.688, 981.133, 8.804, 668.938, 445.667, 904.496, 613.701, 621.132, 958.897, 682.551, 320.937, 915.932, 944.988, 385.876, 540.237, 282.829, 911.336, 822.109, 374.958, 802.817, 445.557, 43.852, 898.282, 192.512, 513.895, 948.212, 167.395, 956.276, 537.975, 7.331, 65.472, 670.335, 773.582, 864.951, 424.209, 103.927, 537.754, 702.743, 976.224, 775.207,), (646.561, 939.751, 746.891, 153.755, 459.225, 331.715, 87.521, 54.268, 794.215, 558.084, 574.962, 227.646, 258.648, 388.033, 630.217, 433.025, 16.891, 673.299, 534.834, 641.423, 618.349, 755.961, 585.608, 700.882, 72.589, 928.048, 106.136, 786.892, 301.351, 86.505, 765.274, 437.676, 395.113, 660.723, 473.988, 533.468, 136.381, 390.993, 797.485, 545.724, 960.134, 144.076, 677.289, 914.169, 795.017, 729.325, 373.131, 949.465, 553.524, 555.070,), (123.235, 5.030, 596.655, 537.152, 946.979, 304.691, 748.297, 903.546, 343.852, 412.654, 645.932, 512.553, 160.954, 220.788, 834.748, 194.326, 181.358, 799.660, 852.251, 851.388, 932.370, 994.313, 461.265, 549.665, 290.653, 67.363, 98.202, 725.589, 487.190, 330.851, 128.215, 655.473, 100.045, 619.516, 900.119, 317.786, 450.646, 616.342, 305.675, 584.170, 565.552, 364.493, 316.333, 428.307, 4.832, 246.175, 221.526, 739.816, 436.124, 840.110,), (134.306, 732.973, 877.886, 462.848, 358.742, 305.472, 551.672, 175.770, 606.628, 841.793, 858.714, 140.002, 538.618, 263.235, 886.336, 76.462, 75.400, 18.630, 507.178, 31.194, 581.890, 405.134, 590.036, 906.304, 551.594, 543.469, 998.728, 472.104, 775.197, 365.819, 223.307, 772.145, 733.227, 290.999, 464.701, 510.412, 396.785, 502.167, 662.678, 847.982, 806.540, 614.036, 165.844, 514.137, 446.220, 179.145, 948.712, 659.413, 967.736, 735.920,), (483.503, 358.796, 218.819, 487.642, 62.861, 369.435, 42.808, 206.774, 907.726, 361.251, 469.674, 454.643, 46.437, 980.590, 324.071, 703.736, 521.373, 829.647, 834.872, 263.316, 544.350, 173.850, 653.675, 365.297, 653.337, 835.469, 516.663, 376.329, 907.242, 516.372, 352.898, 867.719, 486.862, 482.110, 604.211, 501.837, 138.968, 165.606, 77.088, 643.477, 211.517, 186.906, 362.223, 717.303, 118.330, 230.346, 811.173, 720.256, 481.517, 478.815,), (210.704, 161.246, 833.365, 22.446, 43.144, 573.487, 161.129, 629.540, 39.191, 572.269, 55.912, 258.260, 180.038, 958.238, 599.358, 563.605, 18.620, 719.547, 661.745, 283.455, 85.749, 449.203, 992.776, 867.302, 170.567, 830.364, 600.839, 794.616, 820.453, 181.884, 659.649, 264.521, 724.187, 342.671, 453.470, 590.596, 229.814, 385.462, 108.570, 202.349, 859.592, 504.360, 419.795, 149.561, 96.299, 475.869, 614.748, 39.037, 783.868, 503.329,), (117.516, 482.241, 130.329, 603.475, 827.522, 896.969, 774.870, 649.232, 522.044, 370.377, 43.438, 529.817, 229.486, 802.300, 789.556, 381.236, 589.048, 741.394, 761.539, 696.708, 97.717, 133.883, 477.141, 232.513, 859.053, 283.267, 876.766, 408.647, 189.021, 709.149, 789.422, 577.987, 117.829, 7.194, 654.546, 687.767, 315.902, 362.270, 154.779, 651.576, 253.633, 854.977, 423.562, 365.644, 275.561, 680.606, 754.972, 413.228, 783.788, 482.468,), (370.213, 554.911, 253.778, 306.653, 344.356, 705.495, 735.782, 854.999, 659.283, 747.814, 446.595, 699.311, 161.795, 214.458, 400.561, 338.438, 550.576, 697.057, 706.790, 160.738, 964.570, 5.291, 91.089, 145.328, 925.862, 435.377, 64.080, 221.770, 80.040, 37.755, 384.326, 984.448, 613.966, 521.006, 711.606, 597.473, 945.716, 820.229, 640.291, 438.972, 201.707, 656.884, 803.910, 286.007, 33.609, 599.515, 515.814, 231.671, 169.483, 36.061,), (239.257, 0.287, 157.445, 996.817, 779.673, 353.128, 395.143, 586.080, 517.743, 736.926, 68.617, 90.166, 284.494, 829.765, 915.009, 348.095, 963.288, 276.508, 606.363, 194.525, 929.714, 574.907, 261.108, 407.135, 106.465, 72.386, 294.252, 947.015, 802.942, 956.709, 876.113, 813.147, 574.894, 694.192, 966.055, 563.169, 769.967, 757.473, 961.239, 458.848, 460.720, 586.827, 27.351, 116.268, 67.554, 633.662, 994.198, 676.913, 229.930, 315.731,), (955.446, 516.504, 9.723, 832.177, 248.258, 93.009, 673.698, 821.075, 76.029, 931.396, 476.555, 353.538, 894.316, 269.076, 947.118, 683.107, 909.927, 498.999, 199.667, 735.429, 872.742, 206.779, 202.767, 249.695, 618.597, 155.996, 106.689, 920.188, 675.812, 663.424, 613.827, 764.244, 541.474, 42.263, 482.292, 620.667, 492.340, 985.361, 897.000, 868.769, 490.805, 984.395, 916.007, 280.267, 222.093, 576.665, 54.148, 799.270, 478.320, 540.768,), (502.475, 393.717, 686.339, 174.800, 976.507, 698.245, 460.071, 689.211, 11.820, 210.752, 581.008, 325.436, 612.778, 259.701, 548.563, 237.139, 471.345, 613.084, 365.924, 498.770, 210.532, 700.713, 372.310, 854.326, 279.630, 179.889, 131.139, 575.893, 228.567, 99.870, 269.949, 235.805, 432.219, 380.883, 145.844, 959.148, 149.548, 805.668, 176.607, 499.598, 995.562, 849.390, 517.007, 720.560, 785.333, 300.034, 562.138, 567.835, 398.402, 690.543,), (60.036, 813.818, 476.539, 629.862, 449.855, 334.657, 360.962, 560.350, 931.845, 257.715, 19.835, 121.237, 867.369, 963.117, 198.958, 575.894, 649.131, 174.539, 780.309, 355.109, 673.193, 487.494, 736.526, 889.632, 381.071, 286.524, 631.712, 144.848, 167.576, 807.717, 337.388, 631.273, 571.638, 848.901, 71.344, 161.999, 228.218, 316.878, 291.356, 267.472, 644.644, 271.248, 444.898, 862.806, 363.165, 586.920, 965.526, 413.989, 183.886, 23.101,), (727.772, 662.023, 940.437, 700.697, 80.065, 166.910, 103.009, 63.792, 878.691, 548.434, 26.365, 397.013, 764.996, 83.251, 262.452, 155.274, 654.833, 885.471, 309.371, 247.397, 284.175, 626.481, 131.277, 838.518, 28.571, 663.549, 860.369, 325.201, 476.155, 974.982, 540.584, 272.414, 444.845, 969.542, 697.623, 177.037, 597.584, 631.048, 635.851, 563.984, 523.460, 639.528, 309.661, 347.168, 539.668, 804.708, 441.860, 365.783, 259.807, 303.573,), (0.092, 815.380, 847.946, 343.885, 469.198, 8.317, 922.088, 946.958, 477.067, 9.133, 430.435, 292.923, 231.215, 7.218, 373.644, 411.736, 560.554, 394.752, 163.269, 737.118, 389.723, 378.358, 262.980, 422.239, 239.562, 764.538, 909.954, 807.575, 684.640, 284.677, 742.927, 808.809, 412.904, 853.482, 182.407, 289.595, 636.893, 617.729, 272.134, 622.754, 187.789, 19.395, 49.632, 534.971, 185.938, 102.273, 269.195, 715.196, 727.107, 232.810,), (150.684, 493.580, 341.913, 311.577, 799.462, 997.963, 463.684, 791.425, 330.249, 843.546, 951.644, 56.038, 775.653, 71.385, 470.147, 192.192, 841.539, 817.251, 828.252, 121.962, 768.146, 248.962, 771.225, 442.961, 737.619, 33.510, 460.835, 770.996, 521.139, 982.116, 472.826, 681.442, 312.109, 323.063, 629.164, 42.186, 937.421, 520.926, 253.313, 638.520, 198.724, 887.520, 863.658, 217.788, 112.928, 632.909, 324.513, 167.360, 276.100, 119.650,), (789.144, 8.930, 41.993, 783.475, 475.271, 596.212, 371.399, 89.480, 157.698, 91.402, 618.645, 930.849, 996.973, 625.132, 59.775, 644.575, 701.328, 791.466, 125.827, 232.675, 981.676, 788.562, 756.698, 805.525, 438.719, 192.965, 689.250, 358.167, 134.732, 898.663, 485.302, 437.500, 294.715, 697.038, 189.776, 186.627, 347.665, 732.402, 275.324, 831.350, 914.474, 554.520, 68.877, 155.025, 295.673, 263.349, 367.113, 0.720, 638.026, 379.044,), (185.534, 18.720, 856.829, 776.017, 238.787, 721.004, 658.289, 538.957, 387.491, 524.070, 497.549, 551.468, 613.039, 322.600, 640.904, 110.464, 523.201, 66.680, 835.193, 129.774, 873.493, 202.079, 485.370, 98.754, 571.012, 836.300, 657.921, 525.821, 701.314, 255.939, 366.354, 605.954, 70.874, 930.211, 208.738, 491.406, 889.767, 79.957, 801.020, 60.700, 558.020, 938.244, 415.953, 369.069, 708.434, 823.643, 265.816, 40.653, 70.388, 303.905,), (944.603, 960.587, 97.119, 725.172, 531.661, 189.460, 526.192, 248.763, 625.325, 178.898, 749.194, 415.185, 105.514, 638.624, 357.963, 458.721, 665.242, 882.824, 166.809, 180.397, 401.557, 337.513, 158.176, 998.434, 443.012, 352.324, 315.155, 991.463, 324.654, 371.720, 764.184, 430.588, 725.868, 608.413, 563.145, 213.928, 765.708, 926.147, 254.089, 961.652, 447.500, 397.091, 726.313, 982.956, 595.763, 517.609, 993.412, 301.842, 300.334, 221.887,), (855.720, 21.701, 821.940, 689.719, 275.957, 553.663, 556.323, 925.922, 154.715, 37.736, 355.656, 138.408, 367.083, 582.156, 232.994, 811.074, 91.905, 399.798, 917.882, 734.266, 723.581, 792.904, 172.902, 825.705, 689.595, 576.232, 907.656, 595.231, 300.393, 730.789, 576.284, 78.477, 55.923, 770.902, 347.930, 817.142, 416.522, 867.831, 869.787, 226.718, 652.779, 602.302, 11.434, 777.419, 382.487, 304.783, 41.182, 539.930, 149.580, 502.402,), (220.797, 50.520, 731.579, 392.883, 445.616, 595.132, 504.729, 222.086, 289.783, 394.322, 132.189, 82.545, 571.441, 49.311, 399.191, 85.079, 501.823, 773.825, 130.375, 134.871, 559.296, 487.861, 652.248, 196.099, 615.997, 735.668, 246.246, 71.644, 776.772, 323.412, 924.138, 89.595, 671.748, 423.541, 348.308, 320.738, 593.877, 24.207, 304.819, 987.652, 616.221, 990.159, 442.210, 145.818, 44.878, 818.172, 199.685, 373.821, 757.734, 852.764,), (112.372, 54.538, 948.941, 926.730, 868.752, 820.134, 13.733, 693.795, 111.278, 450.062, 22.748, 209.010, 538.005, 203.801, 523.266, 258.658, 483.026, 729.924, 141.347, 698.755, 18.389, 583.005, 663.528, 43.482, 170.320, 284.014, 789.188, 617.965, 53.085, 654.758, 8.334, 388.645, 271.310, 852.083, 660.100, 864.282, 19.078, 867.410, 649.411, 231.169, 380.701, 976.612, 99.604, 315.456, 866.773, 531.561, 186.417, 500.651, 457.986, 926.350,), (21.488, 247.392, 529.415, 333.570, 393.400, 157.005, 346.780, 351.913, 625.231, 236.205, 978.244, 501.251, 811.893, 625.792, 878.677, 890.402, 814.859, 29.466, 554.939, 280.194, 151.708, 897.175, 656.932, 87.795, 382.207, 960.606, 612.448, 625.525, 227.428, 240.361, 152.749, 970.537, 909.735, 329.285, 542.234, 206.757, 138.577, 541.354, 800.105, 862.588, 308.998, 705.136, 523.805, 135.252, 995.686, 975.777, 145.152, 933.030, 917.112, 317.496,), (557.340, 948.602, 118.387, 317.598, 879.638, 727.080, 765.435, 880.132, 414.040, 411.252, 443.004, 933.769, 894.130, 933.250, 273.796, 779.108, 106.771, 184.746, 762.447, 611.982, 266.863, 567.043, 230.911, 232.183, 687.378, 359.261, 688.141, 476.602, 502.325, 604.712, 712.019, 373.959, 852.129, 491.446, 137.513, 193.260, 32.230, 764.539, 15.014, 269.859, 413.044, 742.367, 988.243, 757.777, 66.136, 927.103, 985.628, 867.129, 489.943, 324.896,), (457.545, 246.784, 404.867, 41.826, 735.332, 380.374, 312.897, 611.505, 742.468, 593.806, 525.231, 875.783, 786.920, 520.649, 451.610, 827.010, 42.416, 995.836, 518.703, 395.611, 735.170, 557.701, 516.127, 630.649, 49.295, 291.179, 398.040, 304.554, 827.621, 461.347, 422.462, 613.134, 54.547, 516.970, 142.240, 829.894, 451.698, 722.647, 113.172, 778.731, 937.842, 696.114, 135.307, 413.559, 450.886, 178.879, 590.315, 712.634, 201.932, 454.683,), (250.082, 691.717, 907.162, 796.486, 718.375, 123.544, 114.165, 449.398, 362.943, 523.817, 384.087, 791.067, 511.666, 949.754, 378.679, 380.607, 768.260, 912.253, 565.492, 659.530, 150.090, 868.819, 178.867, 712.047, 419.582, 309.518, 768.630, 446.258, 626.453, 117.554, 131.571, 202.852, 622.560, 253.111, 458.643, 855.411, 543.501, 5.751, 882.703, 237.878, 588.862, 475.712, 410.151, 79.405, 600.102, 244.713, 547.342, 619.766, 557.549, 825.253,), (48.919, 148.256, 653.277, 36.721, 853.829, 666.997, 838.014, 298.442, 920.385, 49.031, 416.957, 178.248, 672.090, 611.090, 691.514, 594.969, 787.308, 177.419, 455.338, 578.966, 931.480, 93.126, 299.294, 368.569, 378.939, 67.667, 427.324, 550.471, 292.833, 134.546, 694.619, 274.419, 527.053, 524.646, 695.829, 612.054, 109.302, 729.729, 628.979, 987.189, 483.663, 688.654, 933.892, 986.278, 287.187, 608.845, 316.489, 525.391, 995.024, 353.853,)))"
|
|
]
|
|
},
|
|
"execution_count": 43,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"m"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 44,
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "fragment"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Matrix((639.4, ...), ..., (..., 353.9))[100x50]\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"print(m)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Similarily, `v` is now a `Vector` with $50$ entries."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 45,
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"v = Vector(1_000 * random.random() for _ in range(50))"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 46,
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "skip"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"Vector((129.713, 562.634, 519.706, 631.858, 492.504, 179.907, 609.406, 708.587, 979.258, 1.581, 23.987, 625.461, 117.926, 848.070, 799.564, 998.987, 414.041, 333.792, 560.416, 637.504, 11.297, 201.187, 281.627, 790.196, 307.773, 506.690, 323.924, 6.131, 685.836, 341.362, 724.397, 615.993, 29.117, 175.629, 330.515, 337.937, 672.473, 916.163, 797.254, 645.652, 481.496, 627.200, 892.058, 536.968, 335.110, 783.989, 413.953, 742.585, 835.106, 299.344))"
|
|
]
|
|
},
|
|
"execution_count": 46,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"v"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 47,
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "fragment"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Vector(129.7, ..., 299.3)[50]\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"print(v)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "skip"
|
|
}
|
|
},
|
|
"source": [
|
|
"The arithmetic works as before."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 48,
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"w = m * v"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 49,
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "fragment"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Vector(11378937.3, ..., 13593029.3)[100]\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"print(w)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "skip"
|
|
}
|
|
},
|
|
"source": [
|
|
"We can multiply `m` with its transpose or the other way round."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 50,
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"n = m * m.transpose()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 51,
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "fragment"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Matrix((14370711.3, ...), ..., (..., 16545418.2))[100x100]\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"print(n)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 52,
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "fragment"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"o = m.transpose() * m"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 53,
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "fragment"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Matrix((32618511.5, ...), ..., (..., 32339164.8))[50x50]\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"print(o)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
}
|
|
},
|
|
"source": [
|
|
"## Comparison with [numpy](https://www.numpy.org/)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "skip"
|
|
}
|
|
},
|
|
"source": [
|
|
"We started out in this chapter by realizing that Python provides us no good data type to model a vector $\\vec{x}$ or a matrix $\\bf{A}$. Then, we built up two custom data types, `Vector` and `Matrix`, that wrap a simple `tuple` object for $\\vec{x}$ and a `tuple` of `tuple`s for $\\bf{A}$ so that we can interact with their `._entries` in a \"natural\" way, which is similar to how we write linear algebra tasks by hand. By doing this, we extend Python with our own little \"dialect\" or **[domain-specific language <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_wiki.png\">](https://en.wikipedia.org/wiki/Domain-specific_language)** (DSL).\n",
|
|
"\n",
|
|
"If we feel like sharing our linear algebra library with the world, we could easily do so on either [GitHub <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_gh.png\">](https://github.com) or [PyPI](https://pypi.org). However, for the domain of linear algebra this would be rather pointless as there is already a widely adopted library with [numpy](https://www.numpy.org/) that not only has a lot more features than ours but also is implemented in C, which makes it a lot faster with big data.\n",
|
|
"\n",
|
|
"Let's model the example in the [first part <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_nb.png\">](https://nbviewer.jupyter.org/github/webartifex/intro-to-python/blob/develop/11_classes/00_content.ipynb#Example:-Vectors-&-Matrices) with both [numpy](https://www.numpy.org/) and our own DSL and compare them."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 54,
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"x = (1, 2, 3)\n",
|
|
"A = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 55,
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "fragment"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"ename": "TypeError",
|
|
"evalue": "can't multiply sequence by non-int of type 'tuple'",
|
|
"output_type": "error",
|
|
"traceback": [
|
|
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
|
|
"\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)",
|
|
"\u001b[0;32m<ipython-input-55-fd81d962f516>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mA\u001b[0m \u001b[0;34m*\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
|
|
"\u001b[0;31mTypeError\u001b[0m: can't multiply sequence by non-int of type 'tuple'"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"A * x"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "skip"
|
|
}
|
|
},
|
|
"source": [
|
|
"The creation of vectors and matrices is similar to our DSL. However, numpy uses the more general concept of an **n-dimensional array** (i.e., the `ndarray` type) where a vector is only a special case of a matrix and a matrix is yet another special case of an even higher dimensional structure."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 56,
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"import numpy as np"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 57,
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "fragment"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"x_arr = np.array(x)\n",
|
|
"A_arr = np.array(A)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 58,
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "fragment"
|
|
}
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"x_vec = Vector(x)\n",
|
|
"A_mat = Matrix(A)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "skip"
|
|
}
|
|
},
|
|
"source": [
|
|
"The text representations are very similar. However, [numpy](https://www.numpy.org/)'s `ndarray`s keep the entries as `int`s while our `Vector` and `Matrix` objects contain `float`s."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 59,
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"array([1, 2, 3])"
|
|
]
|
|
},
|
|
"execution_count": 59,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"x_arr"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 60,
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "fragment"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"Vector((1.000, 2.000, 3.000))"
|
|
]
|
|
},
|
|
"execution_count": 60,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"x_vec"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 61,
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "fragment"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"array([[1, 2, 3],\n",
|
|
" [4, 5, 6],\n",
|
|
" [7, 8, 9]])"
|
|
]
|
|
},
|
|
"execution_count": 61,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"A_arr"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 62,
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "fragment"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"Matrix(((1.000, 2.000, 3.000,), (4.000, 5.000, 6.000,), (7.000, 8.000, 9.000,)))"
|
|
]
|
|
},
|
|
"execution_count": 62,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"A_mat"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "skip"
|
|
}
|
|
},
|
|
"source": [
|
|
"[numpy](https://www.numpy.org/)'s `ndarray`s come with a `.shape` instance attribute that returns a `tuple` with the dimensions ..."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 63,
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"(3,)"
|
|
]
|
|
},
|
|
"execution_count": 63,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"x_arr.shape"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 64,
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "fragment"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"(3, 3)"
|
|
]
|
|
},
|
|
"execution_count": 64,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"A_arr.shape"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"... while `Matrix` objects come with `.n_rows` and `.n_cols` properties."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 65,
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "fragment"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"(3, 3)"
|
|
]
|
|
},
|
|
"execution_count": 65,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"A_mat.n_rows, A_mat.n_cols"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "skip"
|
|
}
|
|
},
|
|
"source": [
|
|
"The built-in [len() <img height=\"12\" style=\"display: inline-block\" src=\"../static/link/to_py.png\">](https://docs.python.org/3/library/functions.html#len) function does not return the number of entries in an `ndarray` but the number of the rows instead. This is equivalent to the first element in the `.shape` attribute."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 66,
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"3"
|
|
]
|
|
},
|
|
"execution_count": 66,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"len(x_arr)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 67,
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "fragment"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"3"
|
|
]
|
|
},
|
|
"execution_count": 67,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"len(x_vec)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 68,
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "fragment"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"3"
|
|
]
|
|
},
|
|
"execution_count": 68,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"len(A_arr)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 69,
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "fragment"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"9"
|
|
]
|
|
},
|
|
"execution_count": 69,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"len(A_mat)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "skip"
|
|
}
|
|
},
|
|
"source": [
|
|
"The `.transpose()` method also exists for `ndarray`s."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 70,
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"array([[1, 4, 7],\n",
|
|
" [2, 5, 8],\n",
|
|
" [3, 6, 9]])"
|
|
]
|
|
},
|
|
"execution_count": 70,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"A_arr.transpose()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 71,
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "fragment"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"Matrix(((1.000, 4.000, 7.000,), (2.000, 5.000, 8.000,), (3.000, 6.000, 9.000,)))"
|
|
]
|
|
},
|
|
"execution_count": 71,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"A_mat.transpose()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "skip"
|
|
}
|
|
},
|
|
"source": [
|
|
"To perform matrix-matrix, matrix-vector, or vector-matrix multiplication in [numpy](https://www.numpy.org/), we use the `.dot()` method. If we use the `*` operator with `ndarray`s, an *entry-wise* multiplication is performed."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 72,
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"array([14, 32, 50])"
|
|
]
|
|
},
|
|
"execution_count": 72,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"A_arr.dot(x_arr)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 73,
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "fragment"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"array([[ 1, 4, 9],\n",
|
|
" [ 4, 10, 18],\n",
|
|
" [ 7, 16, 27]])"
|
|
]
|
|
},
|
|
"execution_count": 73,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"A_arr * x_arr"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 74,
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "fragment"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"Vector((14.000, 32.000, 50.000))"
|
|
]
|
|
},
|
|
"execution_count": 74,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"A_mat * x_vec"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "skip"
|
|
}
|
|
},
|
|
"source": [
|
|
"Scalar multiplication, however, works as expected."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 75,
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"array([10, 20, 30])"
|
|
]
|
|
},
|
|
"execution_count": 75,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"10 * x_arr"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 76,
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "fragment"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"Vector((10.000, 20.000, 30.000))"
|
|
]
|
|
},
|
|
"execution_count": 76,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"10 * x_vec"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "skip"
|
|
}
|
|
},
|
|
"source": [
|
|
"Because we implemented our classes to support the sequence protocol, [numpy](https://www.numpy.org/)'s *one*-dimensional `ndarray`s are actually able to work with them: The `*` operator is applied on a per-entry basis."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 77,
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "slide"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"array([2., 4., 6.])"
|
|
]
|
|
},
|
|
"execution_count": 77,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"x_arr + x_vec"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 78,
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "fragment"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"array([1., 4., 9.])"
|
|
]
|
|
},
|
|
"execution_count": 78,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"x_arr * x_vec"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 79,
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "fragment"
|
|
}
|
|
},
|
|
"outputs": [
|
|
{
|
|
"ename": "ValueError",
|
|
"evalue": "operands could not be broadcast together with shapes (3,3) (9,) ",
|
|
"output_type": "error",
|
|
"traceback": [
|
|
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
|
|
"\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)",
|
|
"\u001b[0;32m<ipython-input-79-032c970f8cfc>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mA_arr\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0mA_mat\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
|
|
"\u001b[0;31mValueError\u001b[0m: operands could not be broadcast together with shapes (3,3) (9,) "
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"A_arr + A_mat"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"slideshow": {
|
|
"slide_type": "skip"
|
|
}
|
|
},
|
|
"source": [
|
|
"We conclude that it is rather easy to extend Python in a way that makes the resulting application code read like core Python again. As there are many well established third-party packages out there, it is unlikely that we have to implement a fundamental library ourselves. Yet, we can apply the concepts introduced in this chapter to organize the code in the applications we write."
|
|
]
|
|
}
|
|
],
|
|
"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.8.6"
|
|
},
|
|
"livereveal": {
|
|
"auto_select": "code",
|
|
"auto_select_fragment": true,
|
|
"scroll": true,
|
|
"theme": "serif"
|
|
},
|
|
"toc": {
|
|
"base_numbering": 1,
|
|
"nav_menu": {},
|
|
"number_sections": false,
|
|
"sideBar": true,
|
|
"skip_h1_title": true,
|
|
"title_cell": "Table of Contents",
|
|
"title_sidebar": "Contents",
|
|
"toc_cell": false,
|
|
"toc_position": {
|
|
"height": "calc(100% - 180px)",
|
|
"left": "10px",
|
|
"top": "150px",
|
|
"width": "384px"
|
|
},
|
|
"toc_section_display": false,
|
|
"toc_window_display": false
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 4
|
|
}
|