From 145afd758006f173290b657fb2768a387098abbd Mon Sep 17 00:00:00 2001 From: leslieDLcy Date: Wed, 21 Feb 2024 11:43:04 +0000 Subject: [PATCH 01/11] matrix multiplication --- intervals/mat_features.py | 79 ++++ tests/calculator.ipynb | 131 ++++++ tests/matrix_initialisation.ipynb | 123 ++++++ tests/test101.ipynb | 553 ++++++++++++++++++++++++ tests/test_matrix_multiply.ipynb | 687 ++++++++++++++++++++++++++++++ 5 files changed, 1573 insertions(+) create mode 100644 intervals/mat_features.py create mode 100644 tests/calculator.ipynb create mode 100644 tests/matrix_initialisation.ipynb create mode 100644 tests/test101.ipynb create mode 100644 tests/test_matrix_multiply.ipynb diff --git a/intervals/mat_features.py b/intervals/mat_features.py new file mode 100644 index 0000000..c52acdf --- /dev/null +++ b/intervals/mat_features.py @@ -0,0 +1,79 @@ +import numpy as np +from intervals.methods import (lo,hi,mid,rad,width,intervalise) + +''' this file contains the functions to create interval matrices from numpy arrays + +TODO: func `intervalise()` removes the ability to consume by the last axis; +''' + +def initialise_interval_matrix(low, high): + """ initialise an interval matrix from the shape (2, m, n) """ + + # low = np.arange(9).reshape(3,3) + # high = np.arange(10, 19).reshape(3,3) + + a_matrix = np.stack([low, high], axis=0) + return intervalise(a_matrix) + + +def create_interval(matrix, half_width=0.1): + """ mannually create an interval matrix from a numpy array """ + + low = matrix * (1 - half_width) + high = matrix * (1 + half_width) + return initialise_interval_matrix(low, high) + + +def dot(x,y): return sum(x*y) + + +def rowcol(W,x): + """ marco's original implementation of the rowcol function """ + + s = W.shape + y=[] + for i in range(s[0]): + y.append(dot(W[i],x)) + return intervalise(y) + + +def rowcol2(x, W): + """ Leslie's implementation of the rowcol function + + args: + - x: a vector, e.g. hidden layer output + - W: weight matrix of the next layer + + note: + - this is not full-fleged interval matrix computation + - it currently only fits for `x` as a vector + - it can be used for hidden-layer tensor propagation + """ + + s = W.shape + y=[] + for j in range(s[1]): + y.append(dot(x, W[:, j])) + result = intervalise(y) + return result[np.newaxis, :] + + +def intvl_matmul(x, W): + """ draft matrix multiplication function for interval matrices + + note: + - can be used for general matrix multiplication + """ + + row_list = [] + sx = x.shape + if len(sx) > 1: + for i in range(sx[0]): + row_list.append(rowcol2(x[i], W)) + return row_list + else: + return rowcol2(x, W) + + + + \ No newline at end of file diff --git a/tests/calculator.ipynb b/tests/calculator.ipynb new file mode 100644 index 0000000..8f8c5ce --- /dev/null +++ b/tests/calculator.ipynb @@ -0,0 +1,131 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "70aa6699-4f90-487e-be4a-3b9638cfc595", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "50a9457f-56c6-4cb6-9b98-b0855fb9ac54", + "metadata": {}, + "outputs": [], + "source": [ + "a = np.array([[1, 2], [3, 4]])" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "e15e1fd0-ee8a-4f9c-9deb-3561b184d5ac", + "metadata": {}, + "outputs": [], + "source": [ + "b = np.array([[5, 6], [7, 8]])" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "ceee93f9-530b-4298-b6e2-445257d9417f", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[ 5, 12],\n", + " [21, 32]])" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# \n", + "\n", + "a * b" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "67aa6025-28a8-4663-b3b0-2546b9b4abb2", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[19, 22],\n", + " [43, 50]])" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a @ b" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "0765a2a9-1c63-41d9-83a8-93d246f84cef", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[19, 22],\n", + " [43, 50]])" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "np.matmul(a, b)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fd42d615-865f-4e79-8190-9da9054ac956", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.10.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/tests/matrix_initialisation.ipynb b/tests/matrix_initialisation.ipynb new file mode 100644 index 0000000..a0c60c0 --- /dev/null +++ b/tests/matrix_initialisation.ipynb @@ -0,0 +1,123 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "64b25132-2920-474b-976b-f87f67666d5e", + "metadata": {}, + "source": [ + "matrix_initialisation" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e12d38fb-eef4-4eee-b1e6-073105b956cc", + "metadata": {}, + "outputs": [], + "source": [ + "from intervals.number import Interval as I\n", + "from intervals.methods import (lo,hi,mid,rad,width,intervalise)\n", + "from intervals.random import uniform_endpoints \n", + "from intervals.mat_features import initialise_interval_matrix, create_interval, dot, rowcol, rowcol2, intvl_matrix" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b993a247-9f1c-4e30-b115-28ae7d846df2", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a4edf763-94fa-470e-a03b-f509b9241e56", + "metadata": {}, + "outputs": [], + "source": [ + "%load_ext autoreload\n", + "%autoreload 2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4e7283e3-ea16-4260-a8a4-a9079ea7f1ce", + "metadata": {}, + "outputs": [], + "source": [ + "# interval matrix `initialisation` test\n", + "\n", + "- I'll first test a way to initialise an interval matrix, which is (2, m, n)\n", + "\n", + "- let's create a matrix whose shpae is (2,3,3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "064f53ed-463c-41b9-a4b3-b6fa97b90ab3", + "metadata": {}, + "outputs": [], + "source": [ + "low = np.arange(9).reshape(3,3)\n", + "low" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2fcb10df-c843-4038-b64c-84dded8664e6", + "metadata": {}, + "outputs": [], + "source": [ + "high = np.arange(10, 19).reshape(3,3)\n", + "high" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "24e8ef6a-83c8-4ec3-845e-1fe4fd3d1392", + "metadata": {}, + "outputs": [], + "source": [ + "intvl_matrix = initialise_interval_matrix(low, high)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a1736678-c8e0-48f5-900a-beb639570717", + "metadata": {}, + "outputs": [], + "source": [ + "intvl_matrix" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.10.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/tests/test101.ipynb b/tests/test101.ipynb new file mode 100644 index 0000000..619778f --- /dev/null +++ b/tests/test101.ipynb @@ -0,0 +1,553 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "2f691393-4806-4e64-8c6a-f05e6edf88dc", + "metadata": {}, + "outputs": [], + "source": [ + "from intervals.number import Interval as I\n", + "from intervals.methods import (lo,hi,mid,rad,width,intervalise)\n", + "from intervals.random import uniform_endpoints" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "46392979-d6f8-469d-96ab-3597b32c65d7", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np" + ] + }, + { + "cell_type": "markdown", + "id": "6980eb8f-d0f4-42a4-a5fa-1ccb1f5416c7", + "metadata": { + "jp-MarkdownHeadingCollapsed": true + }, + "source": [ + "# scalar tests" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f6b628f4-f39d-4d74-84b7-74b7d7bf87fc", + "metadata": {}, + "outputs": [], + "source": [ + "x=I(1,2)\n", + "print(x)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d6ac113c-9f19-43b2-b830-bbf9f0f45a53", + "metadata": {}, + "outputs": [], + "source": [ + "y=I(-3,-2)\n", + "print(y)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c98a9989-3d86-4b9b-b2dd-21cb732eb73a", + "metadata": {}, + "outputs": [], + "source": [ + "x" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cbab70b8-9665-4893-8144-4a25b1e3c91e", + "metadata": {}, + "outputs": [], + "source": [ + "x+y" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "84a93bee-7aa7-4a03-812e-09e3b60d3dbb", + "metadata": {}, + "outputs": [], + "source": [ + "x*y" + ] + }, + { + "cell_type": "markdown", + "id": "7c9c22db-c883-4750-87bf-054915897b22", + "metadata": {}, + "source": [ + "# vector tests" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d6d202a1-e089-4625-ba29-5f9f18d67182", + "metadata": {}, + "outputs": [], + "source": [ + "x = I(lo=[1,2,3,4],hi=[2,3,4,5])\n", + "print(x)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "185ada2e-adc2-4f0c-99c9-84afa1fea583", + "metadata": {}, + "outputs": [], + "source": [ + "y = I(lo=[-1,-2,-3,-4], hi=[-1,-1,-1,-1])\n", + "print(y)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "76832dfd-190e-421b-b137-c84fe928635e", + "metadata": {}, + "outputs": [], + "source": [ + "x.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9655b91c-fa6c-4d0c-9a7f-acc2fc8ff9b9", + "metadata": {}, + "outputs": [], + "source": [ + "# dir(x)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "722ee021-7a8e-42bf-b99e-20694036277a", + "metadata": {}, + "outputs": [], + "source": [ + "x * y" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4bfbb35b-cd7f-4661-9976-955d720da1d1", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "05ee35d3-3415-443b-9751-19a7a49805cb", + "metadata": {}, + "source": [ + "# matrix tests" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "70ecea53-9650-47c6-a156-454823bd3343", + "metadata": {}, + "outputs": [], + "source": [ + "a_matrix = np.array([[[1,2], [2,3], [4,5]],\n", + " [[-1,2],[-2,1],[3,5]],\n", + " [[0,2], [3,4], [6,8]]])" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "232b9980-09d2-4593-a82f-75dba6c95d74", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(3, 3, 2)" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a_matrix.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "cd04fbb9-ab36-495b-b57d-d2fa39e1d3c2", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[[ 1, 2],\n", + " [ 2, 3],\n", + " [ 4, 5]],\n", + "\n", + " [[-1, 2],\n", + " [-2, 1],\n", + " [ 3, 5]],\n", + "\n", + " [[ 0, 2],\n", + " [ 3, 4],\n", + " [ 6, 8]]])" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a_matrix" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "4538f82a-a302-46e1-bb86-da9fac4557a8", + "metadata": {}, + "outputs": [], + "source": [ + "int_a_matrix = intervalise(a_matrix)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "a348ab53-ebad-4716-ae9d-d5989454ed5f", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "intervals.number.Interval" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "type(int_a_matrix)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "791b1672-9845-4378-a197-c387c799d193", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[1. 2.] [-1. 2.] [0. 2.]\n", + "[2. 3.] [-2. 1.] [3. 4.]\n", + "[4. 5.] [3. 5.] [6. 8.]" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "int_a_matrix" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "05cef188-6261-41fc-bc84-40514c06e066", + "metadata": {}, + "outputs": [], + "source": [ + "# " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7af1f872-0766-49db-93fe-4ce85569ac84", + "metadata": {}, + "outputs": [], + "source": [ + "# element-wise multiplication\n", + "\n", + "int_a_matrix * int_a_matrix" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6991701d-c731-47e3-ac70-9776d5ef4118", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1f6f4f5c-31c4-4d22-9254-e535991c0b83", + "metadata": {}, + "outputs": [], + "source": [ + "# test the \n", + "\n", + "a = np.array([[1, 2], [3, 4]])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "52c697e7-b0e0-4ad7-99cb-0fc5bfea60a6", + "metadata": {}, + "outputs": [], + "source": [ + "int_a = intervalise(a)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9b224cce-e633-4e3e-9302-dde146ec3673", + "metadata": {}, + "outputs": [], + "source": [ + "int_a.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a050fa75-1d6e-4196-8a25-ef2d4e6b5630", + "metadata": {}, + "outputs": [], + "source": [ + "# currently, for (4, 2) take the last dimension which shall be 2\n", + "\n", + "a_42 = np.array([[1,2],[2,3],[4,5],[5,6]])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b2fa95c2-9e94-4701-91a5-17374700ff6e", + "metadata": {}, + "outputs": [], + "source": [ + "a_42.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "92d6204d-1378-45f0-b071-c6eb4e8de688", + "metadata": {}, + "outputs": [], + "source": [ + "a_42" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5d1c3ee2-0dec-4773-95ff-caef89d2d566", + "metadata": {}, + "outputs": [], + "source": [ + "int_a_42 = intervalise(a_42)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2763802e-5cbd-424a-8ea9-e93a7607c72d", + "metadata": {}, + "outputs": [], + "source": [ + "int_a_42.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c5cb8978-6f97-42f5-ac62-c6b7e2d9c180", + "metadata": {}, + "outputs": [], + "source": [ + "int_a_42" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b80aca89-8348-4fee-b8d8-08ff75e49101", + "metadata": {}, + "outputs": [], + "source": [ + "# somehow, it's weird that it also takes the first dimension" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "cabc6404-60e9-436f-968d-3086e7bd35bf", + "metadata": {}, + "outputs": [], + "source": [ + "a_24 = np.array([[1,2,4,5],[2,3,5,6]])" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "ff3f9852-4bdd-4f41-9dda-fc35cbfc2c2d", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(2, 4)" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a_24.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "fef3f9fd-6675-4065-b458-229aea28ffee", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[1, 2, 4, 5],\n", + " [2, 3, 5, 6]])" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a_24" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "7b530b01-b585-463c-bf9e-3a824cf7cea6", + "metadata": {}, + "outputs": [], + "source": [ + "int_a_24 = intervalise(a_24)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "29290e3b-a256-4e94-80be-db71ba4b5da0", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(4,)" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "int_a_24.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "9b16b7ee-a702-49b8-9776-602e7dac3b74", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[1.0,2.0]\n", + "[2.0,3.0]\n", + "[4.0,5.0]\n", + "[5.0,6.0]" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "int_a_24" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4f879d4e-37da-4e78-8579-ba00f21ca078", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "gpflow", + "language": "python", + "name": "gpflow" + }, + "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.10.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/tests/test_matrix_multiply.ipynb b/tests/test_matrix_multiply.ipynb new file mode 100644 index 0000000..ebf6d12 --- /dev/null +++ b/tests/test_matrix_multiply.ipynb @@ -0,0 +1,687 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "f6e8b17c-ae64-4d94-9ed7-0628ebcc22dd", + "metadata": {}, + "outputs": [], + "source": [ + "from intervals.number import Interval as I\n", + "from intervals.methods import (lo,hi,mid,rad,width,intervalise)\n", + "from intervals.random import uniform_endpoints \n", + "from intervals.mat_features import initialise_interval_matrix, create_interval, dot, rowcol, rowcol2, intvl_matmul" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "eb56342b-b2d3-4fd7-85e1-a45f64e12b44", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "95064f3d-8f26-403a-97f2-ffc944bd4e5f", + "metadata": {}, + "outputs": [], + "source": [ + "%load_ext autoreload\n", + "%autoreload 2" + ] + }, + { + "cell_type": "markdown", + "id": "1fe67acf-f856-4ede-8d6f-e706f2d69505", + "metadata": { + "tags": [] + }, + "source": [ + "# interval matrix `calculation` test\n", + "\n", + "- test with simple 3 by 3 case\n", + "- current workflow will work as long as there is no shape as 2" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "4d151557-6451-4e1e-8bf9-2d57c4d7950d", + "metadata": {}, + "outputs": [], + "source": [ + "a = np.arange(9).reshape(3,3)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "7ac135be-be97-406f-88f0-48bc604f7596", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[0, 1, 2],\n", + " [3, 4, 5],\n", + " [6, 7, 8]])" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "a" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "79da63ed-bd11-4117-8a7d-0826d873a200", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[0. 0.] [0.9 1.1] [1.8 2.2]\n", + "[2.7 3.3] [3.6 4.4] [4.5 5.5]\n", + "[5.4 6.6] [6.3 7.7] [7.2 8.8]" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# vev @ vec\n", + "\n", + "v1 = create_interval(matrix=a)\n", + "v1" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "b7fd240d-1b42-47c1-995c-1c5e1499a2b8", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(3, 3)" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "v1.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "67ede585-d4b3-4979-b111-8c191117a226", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[0.0,0.0]\n", + "[0.9,1.1]\n", + "[1.8,2.2]" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# create a row vector \n", + "\n", + "row_vec = v1[0]\n", + "row_vec" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "157d4b5f-a59d-4cf1-ae3e-5555bd305a82", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(3,)" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "row_vec.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "9e8d317c-7655-40eb-9f38-407d6310b66f", + "metadata": {}, + "outputs": [], + "source": [ + "# ''' add one more dimension succeeded '''\n", + "\n", + "# added_dim = row_vec[np.newaxis,:]\n", + "# print(added_dim.shape)\n", + "# added_dim" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "9a58174a-49e1-48f6-af8c-2bc8efb98259", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "' lower dimension failed '" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "''' lower dimension failed '''\n", + "\n", + "# np.ravel(added_dim)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "f8f0f97d-86b1-416c-866c-1c5c2cbeb445", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[12.15 18.15] [14.58 21.78] [17.01 25.41]" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# matrix which is v1\n", + "'''\n", + "(3, ) @ (3,3)\n", + "\n", + "'''\n", + "result = rowcol2(x=row_vec, W=v1)\n", + "result" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "5863a47b-c797-473b-8be0-1aa806af23b8", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(1, 3)" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "result.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "id": "e8c73ff7-1ade-47d1-b7be-7bcffc17569f", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[12.15 18.15] [14.58 21.78] [17.01 25.41]" + ] + }, + "execution_count": 35, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "result_ = intvl_matmul(x=row_vec, W=v1)\n", + "result_" + ] + }, + { + "cell_type": "markdown", + "id": "001896f8-b856-455c-972d-20b29274ca2a", + "metadata": {}, + "source": [ + "# vector computation" + ] + }, + { + "cell_type": "markdown", + "id": "5668b7ad-298b-486a-a034-c98515a5c4b9", + "metadata": {}, + "source": [ + "### scaler interval @ vector interval" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "c065ed91-870d-4bce-82fa-781036536cc1", + "metadata": {}, + "outputs": [], + "source": [ + "# scalar\n", + "x = 2." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "a017e76a-b6fb-49d0-b601-1f0aff776b18", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[1.8,2.2]" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "x_intvl = create_interval(matrix=x)\n", + "x_intvl" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "1cc11b29-96ac-4820-a0ad-165b5ed7fc30", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "()" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "x_intvl.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "57d11069-0ecf-4266-8798-6b5e4e71923b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(1, 3)" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "W1 = np.array([[1, 3, 5]])\n", + "# W1 = np.array([1, 3, 5])\n", + "W1.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "53ed7baf-a28c-470c-b094-31a9ec4cd5b6", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[1, 3, 5]])" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "W1" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "f3643fdb-387d-40dc-a1c6-6e8ee738a3ac", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[0.9 1.1] [2.7 3.3] [4.5 5.5]" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "W1_intvl = create_interval(matrix=W1)\n", + "W1_intvl" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "b8ddeda1-0d4c-4994-aef8-89c677a7f009", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(1, 3)" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "W1_intvl.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "ea3b0076-545a-4014-a01c-a7b00bdfad00", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[1.62 2.42] [4.86 7.26] [ 8.1 12.1]" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "#\n", + "''' \n", + "(3, ) @ (1, 3)\n", + "'''\n", + "\n", + "\n", + "h1 = x_intvl * W1_intvl\n", + "h1" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "c5b06fc9-177b-4c6f-a03f-cf78b506e4a7", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(1, 3)" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "h1.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "62561636-783e-4d59-998d-ceb0c0da705b", + "metadata": {}, + "outputs": [], + "source": [ + "# tst= dot(h1, row_vec)" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "55848810-9cfc-4328-b2d2-497f3c24de94", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(3, 1)" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# another test\n", + "\n", + "W2 = np.array([1, 3, 5])[:, np.newaxis]\n", + "W2.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "343ea692-fea7-4650-a45c-42b108dd8aed", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[0.9 1.1]\n", + "[2.7 3.3]\n", + "[4.5 5.5]" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "W2_intvl = create_interval(matrix=W2)\n", + "W2_intvl" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "5f9e63cf-80b8-434d-bcb2-f1aac363a127", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(3, 1)" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "W2_intvl.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "aa2e5d7c-77c2-428e-b957-979dd66e881c", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'\\n# (1 by 3) * (3 by 1)\\ny = hidden_tensor * W2_int\\n'" + ] + }, + "execution_count": 28, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# to mimic the second layer propagation, from h1 to output \n", + "\n", + "'''\n", + "# (1 by 3) * (3 by 1)\n", + "y = hidden_tensor * W2_int\n", + "'''" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "136c2bd5-81ad-41dc-aa56-aaeef7270828", + "metadata": {}, + "outputs": [], + "source": [ + "y_hat = intvl_matmul(x=h1, W=W2_intvl)" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "a2686064-1720-409a-a909-d2ee7cb8e3c5", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[[51.03 93.17]]" + ] + }, + "execution_count": 31, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "y_hat" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "f0ee30f5-1951-4bb1-a1c6-59adcb9b4219", + "metadata": {}, + "outputs": [], + "source": [ + "y_hat2 = intvl_matmul(x=h1, W=v1)" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "d4245b87-a0ae-43c3-85de-1369fdb926af", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[[ 56.862 103.818] [ 69.984 127.776] [ 83.106 151.734]]" + ] + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "y_hat2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6a3f2cd6-97b4-4b08-b729-092c3449be62", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "gpflow", + "language": "python", + "name": "gpflow" + }, + "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.10.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From e31836a6be3f7a2fdfb481201b9fbfab82195c6f Mon Sep 17 00:00:00 2001 From: leslieDLcy Date: Thu, 22 Feb 2024 20:44:01 +0000 Subject: [PATCH 02/11] add interval activation functions --- intervals/activation.py | 8 + tests/matrix_initialisation.ipynb | 73 ++++-- tests/test_matrix_multiply.ipynb | 372 ++++++++++-------------------- 3 files changed, 182 insertions(+), 271 deletions(-) create mode 100644 intervals/activation.py diff --git a/intervals/activation.py b/intervals/activation.py new file mode 100644 index 0000000..f30dc98 --- /dev/null +++ b/intervals/activation.py @@ -0,0 +1,8 @@ +from intervals.number import Interval +from intervals.methods import exp + + +''' a series of popular activation functions for interval arithmetic ''' + +def sigmoid(x:Interval): return 1/(1 + exp(-x)) +def tanh(x:Interval): return (exp(2*x)-1)/(exp(2*x)+1) \ No newline at end of file diff --git a/tests/matrix_initialisation.ipynb b/tests/matrix_initialisation.ipynb index a0c60c0..230baa9 100644 --- a/tests/matrix_initialisation.ipynb +++ b/tests/matrix_initialisation.ipynb @@ -10,7 +10,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "id": "e12d38fb-eef4-4eee-b1e6-073105b956cc", "metadata": {}, "outputs": [], @@ -18,12 +18,12 @@ "from intervals.number import Interval as I\n", "from intervals.methods import (lo,hi,mid,rad,width,intervalise)\n", "from intervals.random import uniform_endpoints \n", - "from intervals.mat_features import initialise_interval_matrix, create_interval, dot, rowcol, rowcol2, intvl_matrix" + "from intervals.mat_features import initialise_interval_matrix, create_interval, dot, rowcol, rowcol2, intvl_matmul" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "id": "b993a247-9f1c-4e30-b115-28ae7d846df2", "metadata": {}, "outputs": [], @@ -33,7 +33,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "id": "a4edf763-94fa-470e-a03b-f509b9241e56", "metadata": {}, "outputs": [], @@ -43,11 +43,9 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "4e7283e3-ea16-4260-a8a4-a9079ea7f1ce", + "cell_type": "markdown", + "id": "d82207b3-a49d-4d5f-90db-59ad1599c5a2", "metadata": {}, - "outputs": [], "source": [ "# interval matrix `initialisation` test\n", "\n", @@ -58,10 +56,23 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "id": "064f53ed-463c-41b9-a4b3-b6fa97b90ab3", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "array([[0, 1, 2],\n", + " [3, 4, 5],\n", + " [6, 7, 8]])" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "low = np.arange(9).reshape(3,3)\n", "low" @@ -69,10 +80,23 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "id": "2fcb10df-c843-4038-b64c-84dded8664e6", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "array([[10, 11, 12],\n", + " [13, 14, 15],\n", + " [16, 17, 18]])" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "high = np.arange(10, 19).reshape(3,3)\n", "high" @@ -80,7 +104,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "id": "24e8ef6a-83c8-4ec3-845e-1fe4fd3d1392", "metadata": {}, "outputs": [], @@ -90,10 +114,23 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "id": "a1736678-c8e0-48f5-900a-beb639570717", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "[ 0. 10.] [ 1. 11.] [ 2. 12.]\n", + "[ 3. 13.] [ 4. 14.] [ 5. 15.]\n", + "[ 6. 16.] [ 7. 17.] [ 8. 18.]" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "intvl_matrix" ] @@ -101,9 +138,9 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": "transformer", "language": "python", - "name": "python3" + "name": "transformer" }, "language_info": { "codemirror_mode": { @@ -115,7 +152,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.11.4" } }, "nbformat": 4, diff --git a/tests/test_matrix_multiply.ipynb b/tests/test_matrix_multiply.ipynb index ebf6d12..e4c6269 100644 --- a/tests/test_matrix_multiply.ipynb +++ b/tests/test_matrix_multiply.ipynb @@ -8,14 +8,24 @@ "outputs": [], "source": [ "from intervals.number import Interval as I\n", - "from intervals.methods import (lo,hi,mid,rad,width,intervalise)\n", + "from intervals.methods import (lo,hi,mid,rad,width,intervalise, exp)\n", "from intervals.random import uniform_endpoints \n", "from intervals.mat_features import initialise_interval_matrix, create_interval, dot, rowcol, rowcol2, intvl_matmul" ] }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 3, + "id": "7778e3c6-c484-49d6-ad56-7d8f4b1fc45a", + "metadata": {}, + "outputs": [], + "source": [ + "from intervals.activation import sigmoid, tanh" + ] + }, + { + "cell_type": "code", + "execution_count": 4, "id": "eb56342b-b2d3-4fd7-85e1-a45f64e12b44", "metadata": {}, "outputs": [], @@ -25,7 +35,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 5, "id": "95064f3d-8f26-403a-97f2-ffc944bd4e5f", "metadata": {}, "outputs": [], @@ -49,7 +59,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 6, "id": "4d151557-6451-4e1e-8bf9-2d57c4d7950d", "metadata": {}, "outputs": [], @@ -59,7 +69,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 7, "id": "7ac135be-be97-406f-88f0-48bc604f7596", "metadata": {}, "outputs": [ @@ -71,7 +81,7 @@ " [6, 7, 8]])" ] }, - "execution_count": 5, + "execution_count": 7, "metadata": {}, "output_type": "execute_result" } @@ -82,7 +92,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 8, "id": "79da63ed-bd11-4117-8a7d-0826d873a200", "metadata": {}, "outputs": [ @@ -94,7 +104,7 @@ "[5.4 6.6] [6.3 7.7] [7.2 8.8]" ] }, - "execution_count": 6, + "execution_count": 8, "metadata": {}, "output_type": "execute_result" } @@ -108,7 +118,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 9, "id": "b7fd240d-1b42-47c1-995c-1c5e1499a2b8", "metadata": {}, "outputs": [ @@ -118,7 +128,7 @@ "(3, 3)" ] }, - "execution_count": 7, + "execution_count": 9, "metadata": {}, "output_type": "execute_result" } @@ -129,7 +139,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 10, "id": "67ede585-d4b3-4979-b111-8c191117a226", "metadata": {}, "outputs": [ @@ -141,7 +151,7 @@ "[1.8,2.2]" ] }, - "execution_count": 8, + "execution_count": 10, "metadata": {}, "output_type": "execute_result" } @@ -155,7 +165,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 11, "id": "157d4b5f-a59d-4cf1-ae3e-5555bd305a82", "metadata": {}, "outputs": [ @@ -165,7 +175,7 @@ "(3,)" ] }, - "execution_count": 9, + "execution_count": 11, "metadata": {}, "output_type": "execute_result" } @@ -176,58 +186,82 @@ }, { "cell_type": "code", - "execution_count": 10, - "id": "9e8d317c-7655-40eb-9f38-407d6310b66f", - "metadata": {}, - "outputs": [], - "source": [ - "# ''' add one more dimension succeeded '''\n", - "\n", - "# added_dim = row_vec[np.newaxis,:]\n", - "# print(added_dim.shape)\n", - "# added_dim" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "9a58174a-49e1-48f6-af8c-2bc8efb98259", + "execution_count": 12, + "id": "f75a5aaf-9013-4951-bb84-88a09d50b270", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "' lower dimension failed '" + "[0.5,0.5]\n", + "[0.7109495026250039,0.7502601055951177]\n", + "[0.8581489350995123,0.9002495108803148]" ] }, - "execution_count": 11, + "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "''' lower dimension failed '''\n", - "\n", - "# np.ravel(added_dim)" + "sigmoid(row_vec)" ] }, { "cell_type": "code", - "execution_count": 12, - "id": "f8f0f97d-86b1-416c-866c-1c5c2cbeb445", + "execution_count": 13, + "id": "0631a1bf-dd74-4b0e-88df-a102c073c9eb", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "[12.15 18.15] [14.58 21.78] [17.01 25.41]" + "[0.5 0.5] [0.7109495 0.75026011] [0.85814894 0.90024951]\n", + "[0.93702664 0.96442881] [0.97340301 0.98787157] [0.98901306 0.99592986]\n", + "[0.99550373 0.99864148] [0.99816706 0.99954738] [0.99925397 0.99984929]" ] }, - "execution_count": 12, + "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], + "source": [ + "sigmoid(v1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9e8d317c-7655-40eb-9f38-407d6310b66f", + "metadata": {}, + "outputs": [], + "source": [ + "# ''' add one more dimension succeeded '''\n", + "\n", + "# added_dim = row_vec[np.newaxis,:]\n", + "# print(added_dim.shape)\n", + "# added_dim" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9a58174a-49e1-48f6-af8c-2bc8efb98259", + "metadata": {}, + "outputs": [], + "source": [ + "''' lower dimension failed '''\n", + "\n", + "# np.ravel(added_dim)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f8f0f97d-86b1-416c-866c-1c5c2cbeb445", + "metadata": {}, + "outputs": [], "source": [ "# matrix which is v1\n", "'''\n", @@ -240,42 +274,20 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": null, "id": "5863a47b-c797-473b-8be0-1aa806af23b8", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(1, 3)" - ] - }, - "execution_count": 14, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "result.shape" ] }, { "cell_type": "code", - "execution_count": 35, + "execution_count": null, "id": "e8c73ff7-1ade-47d1-b7be-7bcffc17569f", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[12.15 18.15] [14.58 21.78] [17.01 25.41]" - ] - }, - "execution_count": 35, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "result_ = intvl_matmul(x=row_vec, W=v1)\n", "result_" @@ -299,7 +311,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": null, "id": "c065ed91-870d-4bce-82fa-781036536cc1", "metadata": {}, "outputs": [], @@ -310,21 +322,10 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": null, "id": "a017e76a-b6fb-49d0-b601-1f0aff776b18", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[1.8,2.2]" - ] - }, - "execution_count": 16, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "x_intvl = create_interval(matrix=x)\n", "x_intvl" @@ -332,42 +333,30 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": null, "id": "1cc11b29-96ac-4820-a0ad-165b5ed7fc30", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "()" - ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "x_intvl.shape" ] }, { "cell_type": "code", - "execution_count": 18, + "execution_count": null, + "id": "71850317-1c60-42df-b3ad-610e1109bb5e", + "metadata": {}, + "outputs": [], + "source": [ + "# sigmoid(x_intvl)" + ] + }, + { + "cell_type": "code", + "execution_count": null, "id": "57d11069-0ecf-4266-8798-6b5e4e71923b", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(1, 3)" - ] - }, - "execution_count": 18, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "W1 = np.array([[1, 3, 5]])\n", "# W1 = np.array([1, 3, 5])\n", @@ -376,42 +365,20 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": null, "id": "53ed7baf-a28c-470c-b094-31a9ec4cd5b6", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([[1, 3, 5]])" - ] - }, - "execution_count": 19, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "W1" ] }, { "cell_type": "code", - "execution_count": 20, + "execution_count": null, "id": "f3643fdb-387d-40dc-a1c6-6e8ee738a3ac", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[0.9 1.1] [2.7 3.3] [4.5 5.5]" - ] - }, - "execution_count": 20, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "W1_intvl = create_interval(matrix=W1)\n", "W1_intvl" @@ -419,42 +386,20 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": null, "id": "b8ddeda1-0d4c-4994-aef8-89c677a7f009", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(1, 3)" - ] - }, - "execution_count": 21, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "W1_intvl.shape" ] }, { "cell_type": "code", - "execution_count": 22, + "execution_count": null, "id": "ea3b0076-545a-4014-a01c-a7b00bdfad00", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[1.62 2.42] [4.86 7.26] [ 8.1 12.1]" - ] - }, - "execution_count": 22, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "#\n", "''' \n", @@ -468,28 +413,17 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": null, "id": "c5b06fc9-177b-4c6f-a03f-cf78b506e4a7", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(1, 3)" - ] - }, - "execution_count": 23, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "h1.shape" ] }, { "cell_type": "code", - "execution_count": 24, + "execution_count": null, "id": "62561636-783e-4d59-998d-ceb0c0da705b", "metadata": {}, "outputs": [], @@ -499,21 +433,10 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": null, "id": "55848810-9cfc-4328-b2d2-497f3c24de94", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(3, 1)" - ] - }, - "execution_count": 25, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "# another test\n", "\n", @@ -523,23 +446,10 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": null, "id": "343ea692-fea7-4650-a45c-42b108dd8aed", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[0.9 1.1]\n", - "[2.7 3.3]\n", - "[4.5 5.5]" - ] - }, - "execution_count": 26, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "W2_intvl = create_interval(matrix=W2)\n", "W2_intvl" @@ -547,42 +457,20 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": null, "id": "5f9e63cf-80b8-434d-bcb2-f1aac363a127", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(3, 1)" - ] - }, - "execution_count": 27, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "W2_intvl.shape" ] }, { "cell_type": "code", - "execution_count": 28, + "execution_count": null, "id": "aa2e5d7c-77c2-428e-b957-979dd66e881c", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'\\n# (1 by 3) * (3 by 1)\\ny = hidden_tensor * W2_int\\n'" - ] - }, - "execution_count": 28, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "# to mimic the second layer propagation, from h1 to output \n", "\n", @@ -594,7 +482,7 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": null, "id": "136c2bd5-81ad-41dc-aa56-aaeef7270828", "metadata": {}, "outputs": [], @@ -604,28 +492,17 @@ }, { "cell_type": "code", - "execution_count": 31, + "execution_count": null, "id": "a2686064-1720-409a-a909-d2ee7cb8e3c5", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[[51.03 93.17]]" - ] - }, - "execution_count": 31, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "y_hat" ] }, { "cell_type": "code", - "execution_count": 33, + "execution_count": null, "id": "f0ee30f5-1951-4bb1-a1c6-59adcb9b4219", "metadata": {}, "outputs": [], @@ -635,21 +512,10 @@ }, { "cell_type": "code", - "execution_count": 34, + "execution_count": null, "id": "d4245b87-a0ae-43c3-85de-1369fdb926af", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[[ 56.862 103.818] [ 69.984 127.776] [ 83.106 151.734]]" - ] - }, - "execution_count": 34, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "y_hat2" ] From abbe449d138f504288de8ca160045466fa0acc08 Mon Sep 17 00:00:00 2001 From: leslieDLcy Date: Fri, 23 Feb 2024 12:11:14 +0000 Subject: [PATCH 03/11] list of vec intervals to a matrix interval --- intervals/mat_features.py | 32 +++- tests/test_matrix_multiply.ipynb | 278 ++++++++++++++++++++++++------- 2 files changed, 244 insertions(+), 66 deletions(-) diff --git a/intervals/mat_features.py b/intervals/mat_features.py index c52acdf..58b4453 100644 --- a/intervals/mat_features.py +++ b/intervals/mat_features.py @@ -7,8 +7,13 @@ ''' def initialise_interval_matrix(low, high): - """ initialise an interval matrix from the shape (2, m, n) """ - + """ initialise an interval matrix from `low, high` arrays; + + note: + from the shape (2, m, n) + """ + + # e.g. # low = np.arange(9).reshape(3,3) # high = np.arange(10, 19).reshape(3,3) @@ -58,11 +63,32 @@ def rowcol2(x, W): return result[np.newaxis, :] +def consume_list(list_intervals): + """ consume a list of interval matrices into a single interval matrix + + note: + - being used for interval matrix multiplication + """ + + low, upper = [], [] + for interval in list_intervals: + low.append(interval.lo) + upper.append(interval.hi) + + low_a = np.vstack(low) + upper_a = np.vstack(upper) + + return intervalise(low_a, upper_a) + + def intvl_matmul(x, W): """ draft matrix multiplication function for interval matrices note: - can be used for general matrix multiplication + + return: + - an interval matrix """ row_list = [] @@ -70,7 +96,7 @@ def intvl_matmul(x, W): if len(sx) > 1: for i in range(sx[0]): row_list.append(rowcol2(x[i], W)) - return row_list + return consume_list(row_list) else: return rowcol2(x, W) diff --git a/tests/test_matrix_multiply.ipynb b/tests/test_matrix_multiply.ipynb index e4c6269..4bef7bb 100644 --- a/tests/test_matrix_multiply.ipynb +++ b/tests/test_matrix_multiply.ipynb @@ -10,12 +10,12 @@ "from intervals.number import Interval as I\n", "from intervals.methods import (lo,hi,mid,rad,width,intervalise, exp)\n", "from intervals.random import uniform_endpoints \n", - "from intervals.mat_features import initialise_interval_matrix, create_interval, dot, rowcol, rowcol2, intvl_matmul" + "from intervals.mat_features import initialise_interval_matrix, create_interval, dot, rowcol, rowcol2, intvl_matmul, consume_list" ] }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 2, "id": "7778e3c6-c484-49d6-ad56-7d8f4b1fc45a", "metadata": {}, "outputs": [], @@ -25,7 +25,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 3, "id": "eb56342b-b2d3-4fd7-85e1-a45f64e12b44", "metadata": {}, "outputs": [], @@ -35,7 +35,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 4, "id": "95064f3d-8f26-403a-97f2-ffc944bd4e5f", "metadata": {}, "outputs": [], @@ -59,7 +59,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 5, "id": "4d151557-6451-4e1e-8bf9-2d57c4d7950d", "metadata": {}, "outputs": [], @@ -69,7 +69,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 6, "id": "7ac135be-be97-406f-88f0-48bc604f7596", "metadata": {}, "outputs": [ @@ -81,7 +81,7 @@ " [6, 7, 8]])" ] }, - "execution_count": 7, + "execution_count": 6, "metadata": {}, "output_type": "execute_result" } @@ -92,7 +92,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 7, "id": "79da63ed-bd11-4117-8a7d-0826d873a200", "metadata": {}, "outputs": [ @@ -104,7 +104,7 @@ "[5.4 6.6] [6.3 7.7] [7.2 8.8]" ] }, - "execution_count": 8, + "execution_count": 7, "metadata": {}, "output_type": "execute_result" } @@ -118,114 +118,109 @@ }, { "cell_type": "code", - "execution_count": 9, - "id": "b7fd240d-1b42-47c1-995c-1c5e1499a2b8", + "execution_count": 11, + "id": "aa4e3c4d-7163-4ad3-8f17-2ab8f5b8039e", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "(3, 3)" + "[12.15 12.15] [14.58 14.58] [17.01 17.01]\n", + "[34.02 34.02] [43.74 43.74] [53.46 53.46]\n", + "[55.89 55.89] [72.9 72.9] [89.91 89.91]" ] }, - "execution_count": 9, + "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "v1.shape" + "aaa = intvl_matmul(v1, v1)\n", + "aaa" ] }, { "cell_type": "code", - "execution_count": 10, - "id": "67ede585-d4b3-4979-b111-8c191117a226", + "execution_count": 12, + "id": "640fcecf-6bff-461a-8cfe-67908bfd14b9", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "[0.0,0.0]\n", - "[0.9,1.1]\n", - "[1.8,2.2]" + "intervals.number.Interval" ] }, - "execution_count": 10, + "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "# create a row vector \n", - "\n", - "row_vec = v1[0]\n", - "row_vec" + "type(aaa)" ] }, { "cell_type": "code", - "execution_count": 11, - "id": "157d4b5f-a59d-4cf1-ae3e-5555bd305a82", + "execution_count": 13, + "id": "81f88d0a-2caa-4b71-b64c-ae2e268879b7", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "(3,)" + "3" ] }, - "execution_count": 11, + "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], + "source": [ + "len(aaa)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "67ede585-d4b3-4979-b111-8c191117a226", + "metadata": {}, + "outputs": [], + "source": [ + "# create a row vector \n", + "\n", + "row_vec = v1[0]\n", + "row_vec" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "157d4b5f-a59d-4cf1-ae3e-5555bd305a82", + "metadata": {}, + "outputs": [], "source": [ "row_vec.shape" ] }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "id": "f75a5aaf-9013-4951-bb84-88a09d50b270", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[0.5,0.5]\n", - "[0.7109495026250039,0.7502601055951177]\n", - "[0.8581489350995123,0.9002495108803148]" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "sigmoid(row_vec)" ] }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "id": "0631a1bf-dd74-4b0e-88df-a102c073c9eb", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[0.5 0.5] [0.7109495 0.75026011] [0.85814894 0.90024951]\n", - "[0.93702664 0.96442881] [0.97340301 0.98787157] [0.98901306 0.99592986]\n", - "[0.99550373 0.99864148] [0.99816706 0.99954738] [0.99925397 0.99984929]" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "sigmoid(v1)" ] @@ -290,9 +285,73 @@ "outputs": [], "source": [ "result_ = intvl_matmul(x=row_vec, W=v1)\n", - "result_" + "type(result_)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "565c716b-09db-4493-b0fc-affcd460a8ee", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8d928b16-c5c8-4131-9e0d-deedd67484ba", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "57a775aa-046f-4e17-8ad5-43927f640f83", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "74042df9-b537-49af-aeb3-c9bde1d78e76", + "metadata": {}, + "outputs": [], + "source": [ + "ds = [[[1,2], [2,3], [4,5]],\n", + " [[-1,2],[-2,1],[3,5]],\n", + " [[0,2], [3,4], [6,8]]]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c0caee81-854b-4635-a7a7-4cd6f5a1914b", + "metadata": {}, + "outputs": [], + "source": [ + "type(ds[0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "44f235e6-797a-4b15-b83c-56fa45c66165", + "metadata": {}, + "outputs": [], + "source": [ + "treat_list" ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "269f069a-2675-4a80-b68a-94a1807efbdd", + "metadata": {}, + "outputs": [], + "source": [] + }, { "cell_type": "markdown", "id": "001896f8-b856-455c-972d-20b29274ca2a", @@ -317,7 +376,7 @@ "outputs": [], "source": [ "# scalar\n", - "x = 2." + "x = 3.2" ] }, { @@ -421,6 +480,99 @@ "h1.shape" ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "2c8056b0-c95e-4048-b6b9-b1fc54dd7e83", + "metadata": {}, + "outputs": [], + "source": [ + "3.2 * h1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "90868753-32eb-48d9-a2cc-eb5caad50a95", + "metadata": {}, + "outputs": [], + "source": [ + "x = np.array([3.2])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "36f6919d-68df-4350-963c-f94392e63225", + "metadata": {}, + "outputs": [], + "source": [ + "# scaler * interval vector\n", + "print(x * h1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c049bfdf-eb62-4d37-958d-34e8642f639a", + "metadata": {}, + "outputs": [], + "source": [ + "x2 = I(3.2, 3.2)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1d634e8b-828c-4faa-a5bd-aa943ae3bcf3", + "metadata": {}, + "outputs": [], + "source": [ + "x2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "90d81cb1-8b19-4ee4-9429-460805f63f1d", + "metadata": {}, + "outputs": [], + "source": [ + "x2 * h1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "808c83f0-c772-4f6d-886e-609885d58815", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dd8bb6b6-02e7-4d44-a689-d6a9ab13055f", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "85853f1c-5c25-4946-b8a9-7c708134e58b", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e7dd9b64-e5b9-4663-a035-c6dfd37c3370", + "metadata": {}, + "outputs": [], + "source": [] + }, { "cell_type": "code", "execution_count": null, @@ -531,9 +683,9 @@ ], "metadata": { "kernelspec": { - "display_name": "gpflow", + "display_name": "transformer", "language": "python", - "name": "gpflow" + "name": "transformer" }, "language_info": { "codemirror_mode": { @@ -545,7 +697,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.11.4" } }, "nbformat": 4, From 34c50e164a604206afc634708b4921072858379a Mon Sep 17 00:00:00 2001 From: leslieDLcy Date: Mon, 1 Apr 2024 15:13:22 +0100 Subject: [PATCH 04/11] interval matrix multiplication succeed --- intervals/mat_features.py | 77 ++- intervals/plotting.py | 38 +- tests/calculator.ipynb | 2 +- ... => interval_objects_initialisation.ipynb} | 306 ++++++----- tests/matrix_initialisation.ipynb | 160 ------ ...iply.ipynb => matrix_multiplication.ipynb} | 519 +++++++++--------- tests/plotting.ipynb | 222 ++++++++ 7 files changed, 726 insertions(+), 598 deletions(-) rename tests/{test101.ipynb => interval_objects_initialisation.ipynb} (74%) delete mode 100644 tests/matrix_initialisation.ipynb rename tests/{test_matrix_multiply.ipynb => matrix_multiplication.ipynb} (66%) create mode 100644 tests/plotting.ipynb diff --git a/intervals/mat_features.py b/intervals/mat_features.py index 58b4453..67682f2 100644 --- a/intervals/mat_features.py +++ b/intervals/mat_features.py @@ -3,22 +3,22 @@ ''' this file contains the functions to create interval matrices from numpy arrays -TODO: func `intervalise()` removes the ability to consume by the last axis; +TODO: func `intervalise()` change the default setting to consume by the last axis to first axis or 2by2 matrix will be wrong; ''' -def initialise_interval_matrix(low, high): +def consume_interval(low, high): """ initialise an interval matrix from `low, high` arrays; note: - from the shape (2, m, n) + initialise from the shape (2, m, n) as preferred; + + example: + low = np.arange(9).reshape(3,3) + high = np.arange(10, 19).reshape(3,3) """ - # e.g. - # low = np.arange(9).reshape(3,3) - # high = np.arange(10, 19).reshape(3,3) - a_matrix = np.stack([low, high], axis=0) - return intervalise(a_matrix) + return intervalise(a_matrix, index=0) def create_interval(matrix, half_width=0.1): @@ -26,7 +26,7 @@ def create_interval(matrix, half_width=0.1): low = matrix * (1 - half_width) high = matrix * (1 + half_width) - return initialise_interval_matrix(low, high) + return consume_interval(low, high) def dot(x,y): return sum(x*y) @@ -42,31 +42,48 @@ def rowcol(W,x): return intervalise(y) -def rowcol2(x, W): - """ Leslie's implementation of the rowcol function +def rowcol2(x,W): + """ Leslie changed the argument order for notational convecience original implementation of the rowcol function args: - - x: a vector, e.g. hidden layer output - - W: weight matrix of the next layer - - note: - - this is not full-fleged interval matrix computation - - it currently only fits for `x` as a vector - - it can be used for hidden-layer tensor propagation + - W: have to be a vector; """ - - s = W.shape + + s = x.shape y=[] - for j in range(s[1]): - y.append(dot(x, W[:, j])) - result = intervalise(y) - return result[np.newaxis, :] + for i in range(s[0]): + y.append(dot(x[i],W)) + return intervalise(y) + + + +# def rowcol_wrong(x, W): +# """ Leslie's implementation of the rowcol function + +# args: +# - x: a vector, e.g. hidden layer output, as a row vector +# - W: weight matrix of the next layer + +# note: +# - this is not full-fleged interval matrix computation +# - it currently only fits for `x` as a vector +# - it can be used for hidden-layer tensor propagation +# """ + +# s = W.shape +# y=[] +# for j in range(s[1]): +# y.append(dot(x, W[:, j])) +# result = intervalise(y) +# return result[np.newaxis, :] def consume_list(list_intervals): """ consume a list of interval matrices into a single interval matrix + ! of no use now note: + - being used for interval matrix multiplication """ @@ -91,12 +108,12 @@ def intvl_matmul(x, W): - an interval matrix """ - row_list = [] - sx = x.shape - if len(sx) > 1: - for i in range(sx[0]): - row_list.append(rowcol2(x[i], W)) - return consume_list(row_list) + row_cp_list = [] + sW = W.shape + if (len(sW)) > 1 & (sW[1]>1): + for j in range(sW[1]): + row_cp_list.append(rowcol2(x, W[:, j])) + return intervalise(row_cp_list) else: return rowcol2(x, W) diff --git a/intervals/plotting.py b/intervals/plotting.py index ca4b39f..f5a18dd 100644 --- a/intervals/plotting.py +++ b/intervals/plotting.py @@ -1,15 +1,47 @@ +from __future__ import annotations +import numpy as np +import matplotlib.pyplot as plt +from intervals.number import Interval + """ -------------------------- Created Feb 2022 Marco De Angelis github.com/marcodeangelis +Editted by Leslie Feb 2024 MIT License -------------------------- """ -from __future__ import annotations -import matplotlib.pyplot as pyplot +def plot_intervals(x, y_i, **kwargs): + """ plot intervals vertically + + args: + x: array-like + x-axis locations + y_i: array-like + array of intervals + """ + + fig, ax = plt.subplots() + if len(x.shape) > 1: + for xx, interval in zip(x, y_i): + ax.plot([xx, xx], [interval.hi, interval.lo], 'r', **kwargs) + else: + ax.plot([x, x], [y_i.hi, y_i.lo], 'r', **kwargs) -from intervals.number import Interval + +def plot_lower_bound(x, y_i, **kwargs): + """ plot lower bound of intervals + + args: + x: array-like + x-axis locations + y_i: array-like + array of intervals + """ + + fig, ax = plt.subplots() + ax.scatter(x, y_i.lo, **kwargs) diff --git a/tests/calculator.ipynb b/tests/calculator.ipynb index 8f8c5ce..74a30e0 100644 --- a/tests/calculator.ipynb +++ b/tests/calculator.ipynb @@ -123,7 +123,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.13" + "version": "3.8.13" } }, "nbformat": 4, diff --git a/tests/test101.ipynb b/tests/interval_objects_initialisation.ipynb similarity index 74% rename from tests/test101.ipynb rename to tests/interval_objects_initialisation.ipynb index 619778f..f57a421 100644 --- a/tests/test101.ipynb +++ b/tests/interval_objects_initialisation.ipynb @@ -22,14 +22,26 @@ "import numpy as np" ] }, + { + "cell_type": "code", + "execution_count": 3, + "id": "b800e6a1-73ad-48e6-9b71-0b427d448db5", + "metadata": {}, + "outputs": [], + "source": [ + "%load_ext autoreload\n", + "%autoreload 2" + ] + }, { "cell_type": "markdown", "id": "6980eb8f-d0f4-42a4-a5fa-1ccb1f5416c7", "metadata": { - "jp-MarkdownHeadingCollapsed": true + "jp-MarkdownHeadingCollapsed": true, + "tags": [] }, "source": [ - "# scalar tests" + "# scalar interval tests" ] }, { @@ -87,9 +99,12 @@ { "cell_type": "markdown", "id": "7c9c22db-c883-4750-87bf-054915897b22", - "metadata": {}, + "metadata": { + "jp-MarkdownHeadingCollapsed": true, + "tags": [] + }, "source": [ - "# vector tests" + "# vector interval tests" ] }, { @@ -100,7 +115,7 @@ "outputs": [], "source": [ "x = I(lo=[1,2,3,4],hi=[2,3,4,5])\n", - "print(x)\n" + "print(x)" ] }, { @@ -145,28 +160,34 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "id": "4bfbb35b-cd7f-4661-9976-955d720da1d1", - "metadata": {}, - "outputs": [], - "source": [] + "cell_type": "markdown", + "id": "05ee35d3-3415-443b-9751-19a7a49805cb", + "metadata": { + "tags": [] + }, + "source": [ + "# matrix interval initialisation tests" + ] }, { "cell_type": "markdown", - "id": "05ee35d3-3415-443b-9751-19a7a49805cb", - "metadata": {}, + "id": "7f96e186-39dd-4036-971a-91ca6400b10c", + "metadata": { + "tags": [] + }, "source": [ - "# matrix tests" + "#### Marco's initialisation" ] }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "id": "70ecea53-9650-47c6-a156-454823bd3343", "metadata": {}, "outputs": [], "source": [ + "# initialise a regular matrix of certain shape and transform it into an `interval matrix`\n", + "\n", "a_matrix = np.array([[[1,2], [2,3], [4,5]],\n", " [[-1,2],[-2,1],[3,5]],\n", " [[0,2], [3,4], [6,8]]])" @@ -174,118 +195,44 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "id": "232b9980-09d2-4593-a82f-75dba6c95d74", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(3, 3, 2)" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "a_matrix.shape" ] }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "id": "cd04fbb9-ab36-495b-b57d-d2fa39e1d3c2", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([[[ 1, 2],\n", - " [ 2, 3],\n", - " [ 4, 5]],\n", - "\n", - " [[-1, 2],\n", - " [-2, 1],\n", - " [ 3, 5]],\n", - "\n", - " [[ 0, 2],\n", - " [ 3, 4],\n", - " [ 6, 8]]])" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "a_matrix" ] }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "id": "4538f82a-a302-46e1-bb86-da9fac4557a8", "metadata": {}, "outputs": [], "source": [ + "# Transform with Marco's default `intervalise` func\n", "int_a_matrix = intervalise(a_matrix)" ] }, - { - "cell_type": "code", - "execution_count": 7, - "id": "a348ab53-ebad-4716-ae9d-d5989454ed5f", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "intervals.number.Interval" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "type(int_a_matrix)" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "791b1672-9845-4378-a197-c387c799d193", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[1. 2.] [-1. 2.] [0. 2.]\n", - "[2. 3.] [-2. 1.] [3. 4.]\n", - "[4. 5.] [3. 5.] [6. 8.]" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "int_a_matrix" - ] - }, { "cell_type": "code", "execution_count": null, - "id": "05cef188-6261-41fc-bc84-40514c06e066", + "id": "a348ab53-ebad-4716-ae9d-d5989454ed5f", "metadata": {}, "outputs": [], "source": [ - "# " + "print(f'data type is: {type(int_a_matrix)}')\n", + "print(f'the value is:\\n{int_a_matrix}')" ] }, { @@ -300,14 +247,6 @@ "int_a_matrix * int_a_matrix" ] }, - { - "cell_type": "code", - "execution_count": null, - "id": "6991701d-c731-47e3-ac70-9776d5ef4118", - "metadata": {}, - "outputs": [], - "source": [] - }, { "cell_type": "code", "execution_count": null, @@ -317,7 +256,8 @@ "source": [ "# test the \n", "\n", - "a = np.array([[1, 2], [3, 4]])" + "a = np.array([[1, 2], [3, 4]])\n", + "a.shape" ] }, { @@ -414,7 +354,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "id": "cabc6404-60e9-436f-968d-3086e7bd35bf", "metadata": {}, "outputs": [], @@ -424,50 +364,27 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "id": "ff3f9852-4bdd-4f41-9dda-fc35cbfc2c2d", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(2, 4)" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "a_24.shape" ] }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "id": "fef3f9fd-6675-4065-b458-229aea28ffee", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([[1, 2, 4, 5],\n", - " [2, 3, 5, 6]])" - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "a_24" ] }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "id": "7b530b01-b585-463c-bf9e-3a824cf7cea6", "metadata": {}, "outputs": [], @@ -477,53 +394,144 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "id": "29290e3b-a256-4e94-80be-db71ba4b5da0", "metadata": {}, + "outputs": [], + "source": [ + "int_a_24.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9b16b7ee-a702-49b8-9776-602e7dac3b74", + "metadata": {}, + "outputs": [], + "source": [ + "int_a_24" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4f879d4e-37da-4e78-8579-ba00f21ca078", + "metadata": {}, + "outputs": [], + "source": [ + "# question, which dimension has the priority" + ] + }, + { + "cell_type": "markdown", + "id": "93c8db4b-11df-47e2-a65c-233c5914b0f1", + "metadata": {}, + "source": [ + "#### Leslie's initialisation\n", + "\n", + "- I'll first test a way to initialise an interval matrix, which is (2, m, n)\n", + "\n", + "- let's create a matrix whose shpae is (2,3,3)" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "476b1e18-1a47-4b17-ad62-033202649f84", + "metadata": {}, + "outputs": [], + "source": [ + "from intervals.number import Interval as I\n", + "from intervals.methods import (lo,hi,mid,rad,width,intervalise)\n", + "from intervals.random import uniform_endpoints \n", + "from intervals.mat_features import consume_interval, create_interval, dot, rowcol, rowcol2, intvl_matmul" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "f794fd90-aaaa-4f57-b8e6-027fbeab7953", + "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "(4,)" + "array([[0, 1, 2],\n", + " [3, 4, 5],\n", + " [6, 7, 8]])" ] }, - "execution_count": 13, + "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "int_a_24.shape" + "low = np.arange(9).reshape(3,3)\n", + "low" ] }, { "cell_type": "code", - "execution_count": 14, - "id": "9b16b7ee-a702-49b8-9776-602e7dac3b74", + "execution_count": 6, + "id": "f1592880-326a-4664-8eca-d2c565503b7a", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "[1.0,2.0]\n", - "[2.0,3.0]\n", - "[4.0,5.0]\n", - "[5.0,6.0]" + "array([[10, 11, 12],\n", + " [13, 14, 15],\n", + " [16, 17, 18]])" ] }, - "execution_count": 14, + "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "int_a_24" + "high = np.arange(10, 19).reshape(3,3)\n", + "high" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "e7f2addd-33f0-4a92-a9c5-8d87515a0854", + "metadata": {}, + "outputs": [], + "source": [ + "intvl_matrix = consume_interval(low, high)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "b15e3073-8bcc-4ae6-9578-8f0d63f597a0", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[ 0. 10.] [ 1. 11.] [ 2. 12.]\n", + "[ 3. 13.] [ 4. 14.] [ 5. 15.]\n", + "[ 6. 16.] [ 7. 17.] [ 8. 18.]" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "intvl_matrix" ] }, { "cell_type": "code", "execution_count": null, - "id": "4f879d4e-37da-4e78-8579-ba00f21ca078", + "id": "28a14109-ce40-4315-9738-5cd2635e66cf", "metadata": {}, "outputs": [], "source": [] diff --git a/tests/matrix_initialisation.ipynb b/tests/matrix_initialisation.ipynb deleted file mode 100644 index 230baa9..0000000 --- a/tests/matrix_initialisation.ipynb +++ /dev/null @@ -1,160 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "64b25132-2920-474b-976b-f87f67666d5e", - "metadata": {}, - "source": [ - "matrix_initialisation" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "e12d38fb-eef4-4eee-b1e6-073105b956cc", - "metadata": {}, - "outputs": [], - "source": [ - "from intervals.number import Interval as I\n", - "from intervals.methods import (lo,hi,mid,rad,width,intervalise)\n", - "from intervals.random import uniform_endpoints \n", - "from intervals.mat_features import initialise_interval_matrix, create_interval, dot, rowcol, rowcol2, intvl_matmul" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "b993a247-9f1c-4e30-b115-28ae7d846df2", - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "a4edf763-94fa-470e-a03b-f509b9241e56", - "metadata": {}, - "outputs": [], - "source": [ - "%load_ext autoreload\n", - "%autoreload 2" - ] - }, - { - "cell_type": "markdown", - "id": "d82207b3-a49d-4d5f-90db-59ad1599c5a2", - "metadata": {}, - "source": [ - "# interval matrix `initialisation` test\n", - "\n", - "- I'll first test a way to initialise an interval matrix, which is (2, m, n)\n", - "\n", - "- let's create a matrix whose shpae is (2,3,3)" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "064f53ed-463c-41b9-a4b3-b6fa97b90ab3", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([[0, 1, 2],\n", - " [3, 4, 5],\n", - " [6, 7, 8]])" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "low = np.arange(9).reshape(3,3)\n", - "low" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "2fcb10df-c843-4038-b64c-84dded8664e6", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([[10, 11, 12],\n", - " [13, 14, 15],\n", - " [16, 17, 18]])" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "high = np.arange(10, 19).reshape(3,3)\n", - "high" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "24e8ef6a-83c8-4ec3-845e-1fe4fd3d1392", - "metadata": {}, - "outputs": [], - "source": [ - "intvl_matrix = initialise_interval_matrix(low, high)" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "a1736678-c8e0-48f5-900a-beb639570717", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[ 0. 10.] [ 1. 11.] [ 2. 12.]\n", - "[ 3. 13.] [ 4. 14.] [ 5. 15.]\n", - "[ 6. 16.] [ 7. 17.] [ 8. 18.]" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "intvl_matrix" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "transformer", - "language": "python", - "name": "transformer" - }, - "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.11.4" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/tests/test_matrix_multiply.ipynb b/tests/matrix_multiplication.ipynb similarity index 66% rename from tests/test_matrix_multiply.ipynb rename to tests/matrix_multiplication.ipynb index 4bef7bb..8e00d57 100644 --- a/tests/test_matrix_multiply.ipynb +++ b/tests/matrix_multiplication.ipynb @@ -1,5 +1,18 @@ { "cells": [ + { + "cell_type": "markdown", + "id": "bb67a0bf-f22e-4fde-9a2e-4c524333920c", + "metadata": { + "tags": [] + }, + "source": [ + "# interval matrix `calculation` test\n", + "\n", + "- test with simple 3 by 3 case\n", + "- current workflow will work as long as there is no shape as 2" + ] + }, { "cell_type": "code", "execution_count": 1, @@ -10,7 +23,7 @@ "from intervals.number import Interval as I\n", "from intervals.methods import (lo,hi,mid,rad,width,intervalise, exp)\n", "from intervals.random import uniform_endpoints \n", - "from intervals.mat_features import initialise_interval_matrix, create_interval, dot, rowcol, rowcol2, intvl_matmul, consume_list" + "from intervals.mat_features import consume_interval, create_interval, dot, rowcol, rowcol2, intvl_matmul, consume_list" ] }, { @@ -46,15 +59,12 @@ }, { "cell_type": "markdown", - "id": "1fe67acf-f856-4ede-8d6f-e706f2d69505", + "id": "bd29348b-91be-43b7-800b-741a918336b3", "metadata": { "tags": [] }, "source": [ - "# interval matrix `calculation` test\n", - "\n", - "- test with simple 3 by 3 case\n", - "- current workflow will work as long as there is no shape as 2" + "#### mat @ mat" ] }, { @@ -70,15 +80,15 @@ { "cell_type": "code", "execution_count": 6, - "id": "7ac135be-be97-406f-88f0-48bc604f7596", + "id": "79da63ed-bd11-4117-8a7d-0826d873a200", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "array([[0, 1, 2],\n", - " [3, 4, 5],\n", - " [6, 7, 8]])" + "[0. 0.] [0.9 1.1] [1.8 2.2]\n", + "[2.7 3.3] [3.6 4.4] [4.5 5.5]\n", + "[5.4 6.6] [6.3 7.7] [7.2 8.8]" ] }, "execution_count": 6, @@ -87,21 +97,22 @@ } ], "source": [ - "a" + "v1 = create_interval(matrix=a, half_width=0.1)\n", + "v1" ] }, { "cell_type": "code", "execution_count": 7, - "id": "79da63ed-bd11-4117-8a7d-0826d873a200", + "id": "aa4e3c4d-7163-4ad3-8f17-2ab8f5b8039e", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "[0. 0.] [0.9 1.1] [1.8 2.2]\n", - "[2.7 3.3] [3.6 4.4] [4.5 5.5]\n", - "[5.4 6.6] [6.3 7.7] [7.2 8.8]" + "[12.15 18.15] [34.02 50.82] [55.89 83.49]\n", + "[14.58 21.78] [43.74 65.34] [ 72.9 108.9]\n", + "[17.01 25.41] [53.46 79.86] [ 89.91 134.31]" ] }, "execution_count": 7, @@ -110,99 +121,215 @@ } ], "source": [ - "# vev @ vec\n", "\n", - "v1 = create_interval(matrix=a)\n", - "v1" + "mat_mul_test = intvl_matmul(v1, v1)\n", + "mat_mul_test" + ] + }, + { + "cell_type": "markdown", + "id": "f5e18d79-62f4-462b-80ca-50b947a7fe84", + "metadata": { + "jp-MarkdownHeadingCollapsed": true, + "tags": [] + }, + "source": [ + "#### row @ mat" ] }, { "cell_type": "code", - "execution_count": 11, - "id": "aa4e3c4d-7163-4ad3-8f17-2ab8f5b8039e", + "execution_count": null, + "id": "4eff5388-d7b3-4202-a34b-6dcc102a8ce9", + "metadata": {}, + "outputs": [], + "source": [ + "row_vec = create_interval(matrix=np.array([[1, 3, 5]]))\n", + "row_vec" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f5995b3c-6f73-4f13-b299-160d83ddcf7b", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d4cd727b-4393-4c50-8b44-715476d7ff1e", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9a2c2999-2a7d-4376-b0fd-70089a4f519c", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bf7c771f-e297-46b5-8af8-71ba14ed430b", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "70d232da-a898-449b-aa13-b6696272d2c2", + "metadata": { + "tags": [] + }, + "source": [ + "#### mat @ col_vec" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "6db7d27c-3493-45af-bf03-6fd3ac53bfe8", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "[12.15 12.15] [14.58 14.58] [17.01 17.01]\n", - "[34.02 34.02] [43.74 43.74] [53.46 53.46]\n", - "[55.89 55.89] [72.9 72.9] [89.91 89.91]" + "[0. 0.] [0.9 1.1] [1.8 2.2]\n", + "[2.7 3.3] [3.6 4.4] [4.5 5.5]\n", + "[5.4 6.6] [6.3 7.7] [7.2 8.8]" ] }, - "execution_count": 11, + "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "aaa = intvl_matmul(v1, v1)\n", - "aaa" + "# given a matrix\n", + "v1" ] }, { "cell_type": "code", - "execution_count": 12, - "id": "640fcecf-6bff-461a-8cfe-67908bfd14b9", + "execution_count": 9, + "id": "c835a252-6aed-43fb-91a2-3fe62307ed12", + "metadata": {}, + "outputs": [], + "source": [ + "# consider just a vector\n", + "vec = create_interval(matrix=np.array([1, 3, 5]))" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "55846437-7298-43c7-92f9-a49d85da66a8", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "intervals.number.Interval" + "3" ] }, - "execution_count": 12, + "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "type(aaa)" + "v1.shape[0]" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "6fe6ff32-de12-45ee-95f4-95a8b4d27385", + "metadata": {}, + "outputs": [], + "source": [ + "# therefore, marco's rowvec works when the latter vec is just a vector" ] }, { "cell_type": "code", - "execution_count": 13, - "id": "81f88d0a-2caa-4b71-b64c-ae2e268879b7", + "execution_count": 14, + "id": "989f92e5-08b3-4493-9451-77f30f202a26", "metadata": {}, "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(3,)\n" + ] + }, { "data": { "text/plain": [ - "3" + "[10.53,15.730000000000002]\n", + "[32.4,48.400000000000006]\n", + "[54.269999999999996,81.07000000000002]" ] }, - "execution_count": 13, + "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "len(aaa)" + "test_marco = rowcol2(v1, vec)\n", + "print(test_marco.shape)\n", + "test_marco" ] }, { - "cell_type": "code", - "execution_count": null, - "id": "67ede585-d4b3-4979-b111-8c191117a226", - "metadata": {}, - "outputs": [], + "cell_type": "markdown", + "id": "ea3e169a-88cf-4645-b613-fc513f686bd1", + "metadata": { + "tags": [] + }, "source": [ - "# create a row vector \n", - "\n", - "row_vec = v1[0]\n", - "row_vec" + "#### vector @ matrix" ] }, { "cell_type": "code", - "execution_count": null, - "id": "157d4b5f-a59d-4cf1-ae3e-5555bd305a82", + "execution_count": 17, + "id": "67ede585-d4b3-4979-b111-8c191117a226", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(3,)\n" + ] + }, + { + "data": { + "text/plain": [ + "[0.9,1.1]\n", + "[2.7,3.3000000000000003]\n", + "[4.5,5.5]" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "row_vec.shape" + "# create a row vector \n", + "\n", + "row_vec = create_interval(matrix=np.array([1, 3, 5]))\n", + "print(row_vec.shape)\n", + "row_vec" ] }, { @@ -212,7 +339,7 @@ "metadata": {}, "outputs": [], "source": [ - "sigmoid(row_vec)" + "# sigmoid(row_vec)" ] }, { @@ -222,7 +349,7 @@ "metadata": {}, "outputs": [], "source": [ - "sigmoid(v1)" + "# sigmoid(v1)" ] }, { @@ -253,49 +380,77 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 18, "id": "f8f0f97d-86b1-416c-866c-1c5c2cbeb445", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "[29.16,43.56000000000001]\n", + "[87.48,130.68000000000004]\n", + "[145.79999999999998,217.80000000000004]" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "# matrix which is v1\n", "'''\n", "(3, ) @ (3,3)\n", "\n", "'''\n", + "\n", "result = rowcol2(x=row_vec, W=v1)\n", "result" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 19, "id": "5863a47b-c797-473b-8be0-1aa806af23b8", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "(3,)" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "result.shape" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 20, "id": "e8c73ff7-1ade-47d1-b7be-7bcffc17569f", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "intervals.number.Interval" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "result_ = intvl_matmul(x=row_vec, W=v1)\n", "type(result_)" ] }, - { - "cell_type": "code", - "execution_count": null, - "id": "565c716b-09db-4493-b0fc-affcd460a8ee", - "metadata": {}, - "outputs": [], - "source": [] - }, { "cell_type": "code", "execution_count": null, @@ -304,68 +459,15 @@ "outputs": [], "source": [] }, - { - "cell_type": "code", - "execution_count": null, - "id": "57a775aa-046f-4e17-8ad5-43927f640f83", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "74042df9-b537-49af-aeb3-c9bde1d78e76", - "metadata": {}, - "outputs": [], - "source": [ - "ds = [[[1,2], [2,3], [4,5]],\n", - " [[-1,2],[-2,1],[3,5]],\n", - " [[0,2], [3,4], [6,8]]]" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c0caee81-854b-4635-a7a7-4cd6f5a1914b", - "metadata": {}, - "outputs": [], - "source": [ - "type(ds[0])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "44f235e6-797a-4b15-b83c-56fa45c66165", - "metadata": {}, - "outputs": [], - "source": [ - "treat_list" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "269f069a-2675-4a80-b68a-94a1807efbdd", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "id": "001896f8-b856-455c-972d-20b29274ca2a", - "metadata": {}, - "source": [ - "# vector computation" - ] - }, { "cell_type": "markdown", "id": "5668b7ad-298b-486a-a034-c98515a5c4b9", - "metadata": {}, + "metadata": { + "jp-MarkdownHeadingCollapsed": true, + "tags": [] + }, "source": [ - "### scaler interval @ vector interval" + "#### scaler @ vector" ] }, { @@ -376,40 +478,11 @@ "outputs": [], "source": [ "# scalar\n", - "x = 3.2" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a017e76a-b6fb-49d0-b601-1f0aff776b18", - "metadata": {}, - "outputs": [], - "source": [ + "x = 3\n", "x_intvl = create_interval(matrix=x)\n", "x_intvl" ] }, - { - "cell_type": "code", - "execution_count": null, - "id": "1cc11b29-96ac-4820-a0ad-165b5ed7fc30", - "metadata": {}, - "outputs": [], - "source": [ - "x_intvl.shape" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "71850317-1c60-42df-b3ad-610e1109bb5e", - "metadata": {}, - "outputs": [], - "source": [ - "# sigmoid(x_intvl)" - ] - }, { "cell_type": "code", "execution_count": null, @@ -417,19 +490,8 @@ "metadata": {}, "outputs": [], "source": [ - "W1 = np.array([[1, 3, 5]])\n", - "# W1 = np.array([1, 3, 5])\n", - "W1.shape" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "53ed7baf-a28c-470c-b094-31a9ec4cd5b6", - "metadata": {}, - "outputs": [], - "source": [ - "W1" + "# a vector\n", + "W1 = np.array([[1, 3, 5]])" ] }, { @@ -460,12 +522,10 @@ "metadata": {}, "outputs": [], "source": [ - "#\n", "''' \n", "(3, ) @ (1, 3)\n", "'''\n", "\n", - "\n", "h1 = x_intvl * W1_intvl\n", "h1" ] @@ -487,7 +547,9 @@ "metadata": {}, "outputs": [], "source": [ - "3.2 * h1" + "'''\n", + "a further test where if (I) a scalar * interval vector matches with (II) scalar interval * interval vector\n", + "'''" ] }, { @@ -500,17 +562,6 @@ "x = np.array([3.2])" ] }, - { - "cell_type": "code", - "execution_count": null, - "id": "36f6919d-68df-4350-963c-f94392e63225", - "metadata": {}, - "outputs": [], - "source": [ - "# scaler * interval vector\n", - "print(x * h1)" - ] - }, { "cell_type": "code", "execution_count": null, @@ -518,16 +569,8 @@ "metadata": {}, "outputs": [], "source": [ - "x2 = I(3.2, 3.2)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "1d634e8b-828c-4faa-a5bd-aa943ae3bcf3", - "metadata": {}, - "outputs": [], - "source": [ + "# scaler * interval vector\n", + "x2 = I(3.2, 3.2)\n", "x2" ] }, @@ -538,21 +581,13 @@ "metadata": {}, "outputs": [], "source": [ - "x2 * h1" + "3.2 * h1 == x2 * h1 " ] }, { "cell_type": "code", "execution_count": null, - "id": "808c83f0-c772-4f6d-886e-609885d58815", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "dd8bb6b6-02e7-4d44-a689-d6a9ab13055f", + "id": "9f8f1d70-c66e-4003-b58c-f253f5b24a08", "metadata": {}, "outputs": [], "source": [] @@ -560,27 +595,25 @@ { "cell_type": "code", "execution_count": null, - "id": "85853f1c-5c25-4946-b8a9-7c708134e58b", + "id": "bb1a50bc-00b0-4a98-bbb9-c5bdb4de1f0a", "metadata": {}, "outputs": [], "source": [] }, { - "cell_type": "code", - "execution_count": null, - "id": "e7dd9b64-e5b9-4663-a035-c6dfd37c3370", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "62561636-783e-4d59-998d-ceb0c0da705b", - "metadata": {}, - "outputs": [], + "cell_type": "markdown", + "id": "3f04e74c-3d22-4588-90bd-0895933a5b9d", + "metadata": { + "tags": [] + }, "source": [ - "# tst= dot(h1, row_vec)" + "#### vector @ vector\n", + "\n", + "> to mimic the second layer propagation, from h1 to output\n", + "\n", + "> (1 by 3) * (3 by 1)\n", + "\n", + "> y = hidden_tensor * W2_int" ] }, { @@ -590,10 +623,9 @@ "metadata": {}, "outputs": [], "source": [ - "# another test\n", + "# consider a column vector\n", "\n", - "W2 = np.array([1, 3, 5])[:, np.newaxis]\n", - "W2.shape" + "W2 = np.array([1, 3, 5])[:, np.newaxis]" ] }, { @@ -604,6 +636,7 @@ "outputs": [], "source": [ "W2_intvl = create_interval(matrix=W2)\n", + "print(W2_intvl.shape)\n", "W2_intvl" ] }, @@ -613,24 +646,7 @@ "id": "5f9e63cf-80b8-434d-bcb2-f1aac363a127", "metadata": {}, "outputs": [], - "source": [ - "W2_intvl.shape" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "aa2e5d7c-77c2-428e-b957-979dd66e881c", - "metadata": {}, - "outputs": [], - "source": [ - "# to mimic the second layer propagation, from h1 to output \n", - "\n", - "'''\n", - "# (1 by 3) * (3 by 1)\n", - "y = hidden_tensor * W2_int\n", - "'''" - ] + "source": [] }, { "cell_type": "code", @@ -639,16 +655,7 @@ "metadata": {}, "outputs": [], "source": [ - "y_hat = intvl_matmul(x=h1, W=W2_intvl)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a2686064-1720-409a-a909-d2ee7cb8e3c5", - "metadata": {}, - "outputs": [], - "source": [ + "y_hat = intvl_matmul(x=h1, W=W2_intvl)\n", "y_hat" ] }, @@ -659,26 +666,27 @@ "metadata": {}, "outputs": [], "source": [ - "y_hat2 = intvl_matmul(x=h1, W=v1)" + "y_hat2 = intvl_matmul(x=h1, W=v1)\n", + "y_hat2" ] }, { - "cell_type": "code", - "execution_count": null, - "id": "d4245b87-a0ae-43c3-85de-1369fdb926af", + "cell_type": "markdown", + "id": "66e3bc0f-eb3c-452a-b7ac-2dba3a898270", "metadata": {}, - "outputs": [], "source": [ - "y_hat2" + "# activation function" ] }, { "cell_type": "code", "execution_count": null, - "id": "6a3f2cd6-97b4-4b08-b729-092c3449be62", + "id": "5c7d91b8-31e2-46f3-b4b6-02223ded3d7a", "metadata": {}, "outputs": [], - "source": [] + "source": [ + "# sigmoid(x_intvl)" + ] } ], "metadata": { @@ -698,7 +706,8 @@ "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.4" - } + }, + "toc-autonumbering": true }, "nbformat": 4, "nbformat_minor": 5 diff --git a/tests/plotting.ipynb b/tests/plotting.ipynb new file mode 100644 index 0000000..7de079b --- /dev/null +++ b/tests/plotting.ipynb @@ -0,0 +1,222 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "340b20c6-58ae-4175-a4cf-757905bb8c47", + "metadata": {}, + "outputs": [], + "source": [ + "from intervals.number import Interval as I\n", + "from intervals.methods import (lo,hi,mid,rad,width,intervalise, exp)\n", + "from intervals.random import uniform_endpoints \n", + "from intervals.mat_features import initialise_interval_matrix, create_interval, dot, rowcol, rowcol2, intvl_matmul, consume_list\n", + "from intervals.plotting import plot_intervals" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "808b0878-876e-42b3-b603-b41b4b941407", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "38fea7d5-233c-409d-8cf8-a5ff3bf1b95e", + "metadata": {}, + "outputs": [], + "source": [ + "%load_ext autoreload\n", + "%autoreload 2" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "725c8f94-a582-4a44-8296-ca9de529dad3", + "metadata": {}, + "outputs": [], + "source": [ + "x = np.arange(4)\n", + "y = np.arange(4)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "957cbb39-6781-4bdc-b546-8fddd0ba2a54", + "metadata": {}, + "outputs": [], + "source": [ + "y_i = create_interval(matrix=y, half_width=0.5)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "8b862885-dc41-4085-a306-287605210b49", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[0.0,0.0]\n", + "[0.5,1.5]\n", + "[1.0,3.0]\n", + "[1.5,4.5]" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "y_i" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "18307e47-7967-4ad6-9178-d667e3590eb3", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAhYAAAGdCAYAAABO2DpVAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAAAVqUlEQVR4nO3db2yV5fnA8esA9tRC28kcCKH+2cxw6MDJxFSTiYoSZ4y8mlsWR5z741IXCck2eDNi9qIuW3RmI2rmlGSbwalBEzdlDgUyp1ELZMCMmc64LgrMZGmhLNW0z+8FoftVKfbU6/T00M8nOUl7ep8+F3eenH7znENbKoqiCACABFNqPQAAcOIQFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAmmnjfcDBwcF46623orm5OUql0ngfHgAYg6Io4uDBgzF37tyYMmXk6xLjHhZvvfVWtLW1jfdhAYAE3d3dMW/evBG/Pu5h0dzcHBFHBmtpaRnvwwMAY9Db2xttbW1DP8dHMu5hcfTlj5aWFmEBAHXmw97G4M2bAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAECacf9bIQBAFRRFxOHDRz5uaor4kL/pUS2uWADAieDw4YgZM47cjgZGDQgLACCNsAAA0ggLACCNsAAA0ggLACCNsAAA0ggLACCNsAAA0ggLACCNsAAA0ggLACCNsAAA0ggLACCNsAAA0ggLACCNsAAA0ggLACCNsAAA0ggLACCNsAAA0ggLACCNsAAA0ggLACCNsAAA0ggLACCNsAAA0ggLACCNsAAA0ggLACCNsAAA0ggLACCNsAAA0ggLACCNsAAA0nyksLj99tujVCrFqlWrksYBAOrZmMPipZdeinvvvTcWLlyYOQ8AUMfGFBaHDh2Kr371q/HLX/4yTjnllOyZAIA6Naaw6OjoiGuuuSaWLVv2oWv7+/ujt7d32A0AODFNq/QBGzdujB07dsRLL700qvWdnZ1x2223VTwYAFB/Krpi0d3dHbfeemv89re/jcbGxlE9Zu3atdHT0zN06+7uHtOgAMDEV9EVi66urjhw4EBccMEFQ/cNDAzE9u3b4xe/+EX09/fH1KlThz2mXC5HuVzOmRYAmNAqCosrrrgidu/ePey+G2+8Mc4555z4wQ9+8IGoAAAml4rCorm5Oc4777xh902fPj0+/vGPf+B+AGDy8Zs3AYA0Ff+vkPfbunVrwhgAwInAFQsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAIE1FYXH33XfHwoULo6WlJVpaWqK9vT2efPLJas0GANSZisJi3rx5cfvtt0dXV1e8/PLLcfnll8d1110Xe/furdZ8AEAdKRVFUXyUbzBz5sz4yU9+EjfddNOo1vf29kZra2v09PRES0vLRzk0QH0qiojDh4983NQUUSrVdh5ODH19ETNmHPn40KGI6dNTv/1of35PG+sBBgYG4uGHH46+vr5ob28fcV1/f3/09/cPGwxgUjt8uKo/AKCWKn7z5u7du2PGjBlRLpfj5ptvjk2bNsWCBQtGXN/Z2Rmtra1Dt7a2to80MAAwcVX8Usi7774b//znP6OnpyceeeSRuO+++2Lbtm0jxsWxrli0tbV5KQSYvKp8yZpJql5fCmloaIizzz47IiIWL14cL730Utx1111x7733HnN9uVyOcrlc6WEAgDr0kX+PxeDg4LArEgDA5FXRFYu1a9fG1VdfHaeffnocPHgwHnzwwdi6dWts3ry5WvMBAHWkorA4cOBAfO1rX4u33347WltbY+HChbF58+a48sorqzUfAFBHKgqLX/3qV9WaAwA4AfhbIQBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKSpKCw6OzvjwgsvjObm5pg1a1asWLEiXn311WrNBgDUmYrCYtu2bdHR0REvvPBCPP300/Hee+/FVVddFX19fdWaDwCoI9MqWfzUU08N+3zDhg0xa9as6Orqii984QupgwEA9aeisHi/np6eiIiYOXPmiGv6+/ujv79/6PPe3t6PckgAYAIb85s3BwcHY9WqVXHJJZfEeeedN+K6zs7OaG1tHbq1tbWN9ZAAwAQ35rDo6OiIPXv2xMaNG4+7bu3atdHT0zN06+7uHushAYAJbkwvhdxyyy3xxBNPxPbt22PevHnHXVsul6NcLo9pOACgvlQUFkVRxHe/+93YtGlTbN26Nc4666xqzQUA1KGKwqKjoyMefPDBePzxx6O5uTn27dsXERGtra1x8sknV2VAAKB+VPQei7vvvjt6enpi6dKlMWfOnKHbQw89VK35AIA6UvFLIQAAI/G3QgCANMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgzrdYDwIRVFBGHDx/5uKkpolSq7TwAdcAVCxjJ4cMRM2YcuR0NDACOS1gAAGm8FAIAJ4KmpohDh/73cY0ICwA4EZRKEdOn13oKL4UAAHmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGkqDovt27fHtddeG3Pnzo1SqRSPPfZYFcYCAOpRxWHR19cXixYtivXr11djHgCgjk2r9AFXX311XH311dWYBQCocxWHRaX6+/ujv79/6PPe3t5qHxIAqJGqv3mzs7MzWltbh25tbW3VPiQAUCNVD4u1a9dGT0/P0K27u7vahwSY2JqaIg4dOnJraqr1NJCq6i+FlMvlKJfL1T4MQP0olSKmT6/1FFAVfo8FAJCm4isWhw4ditdee23o8zfeeCN27doVM2fOjNNPPz11OACgvlQcFi+//HJcdtllQ5+vXr06IiJWrlwZGzZsSBsMAKg/FYfF0qVLoyiKaswCANQ577EAANIICwAgjbAAANIICwAgjbAAANIICwAgjbAAANIICwAgjbAAANIICwAgjbAAANIICwAgjbAAANIICwAgjbAAANIICwAgjbAAANIICwAgjbAAANIICwAgjbAAANIICwAgjbAAANIICwAgjbAAANIICwAgjbAAANIICwAgjbAAANIICwAgjbAAANJMq/UAMGE1NUUcOvS/jwH4UMICRlIqRUyfXuspAOqKl0IAgDTCAgBIIywAgDTCAgBIIywAgDTCAgBIIywAgDTCAgBIIywAgDTCAgBIIywAgDTCAgBIIywAgDTCAgBIIywAgDTCAgBIIywAgDTCAgBIIywAgDTCAgBIIywAgDTCAgBIIywAgDTCAgBIIywAgDTCAgBIIywAgDTCAgBIIywAgDTCAgBIM6awWL9+fZx55pnR2NgYF110Ubz44ovZcwEAdajisHjooYdi9erVsW7dutixY0csWrQoli9fHgcOHKjGfABAHak4LO6444745je/GTfeeGMsWLAg7rnnnmhqaor777+/GvMBAHWkorB49913o6urK5YtW/a/bzBlSixbtiyef/75Yz6mv78/ent7h90AgBNTRWHxzjvvxMDAQMyePXvY/bNnz459+/Yd8zGdnZ3R2to6dGtraxv7tADAhFb1/xWydu3a6OnpGbp1d3dX+5AAQI1Mq2TxqaeeGlOnTo39+/cPu3///v1x2mmnHfMx5XI5yuXy2CcEAOpGRVcsGhoaYvHixbFly5ah+wYHB2PLli3R3t6ePhwAUF8qumIREbF69epYuXJlfP7zn48lS5bEz372s+jr64sbb7yxGvMBAHWk4rC4/vrr49///nf88Ic/jH379sX5558fTz311Afe0AkATD6loiiK8Txgb29vtLa2Rk9PT7S0tIznoQGAMRrtz29/KwQASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIA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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# plot a vector interval\n", + "plot_intervals(x, y_i)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "7ad57e12-fcd2-4279-bd3e-7864dd355870", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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fydOnNBDDz2k3r17KzIyUomJicrMzNShQ4cCttG1a9ca+3D27NkN2l9j9SjV7TnYUvehpFpfgw6HQ0899ZS/pin2YX3627lzp37961/7x/fcc8/VWjd37lx17dpV4eHhSklJqfFecezYMWVlZeniiy9Wu3bt9Otf/1rl5eX1b8aEsNWrV5t/+7d/M2+99ZaRZJYvX37O+j//+c8mKirK5OXlmX379pmlS5eadu3amf/+7//213zwwQcmLCzMzJkzx+zatcs8+uijpk2bNuaTTz7x18yePdu4XC6zYsUK87//+7/mlltuMcnJyeb777+3vr9//ud/NnPnzjXbt283n376qZkwYYJxuVzm4MGD/prx48eb4cOHm7KyMv/03XffNWhvjdXfokWLTHR0dMDY3W53wHaaav81Vo+HDx8O6G/Hjh0mLCzMLFq0yF/TVPswPT3dLFq0yOzYscOUlJSYX/7yl6Zz586msrLyrOs01Gts+PDhpm/fvmbz5s3m/fffN926dTPjxo2zvr+KigqTlpZmXn/9dfPZZ5+ZoqIiM2jQIDNgwICA7XTp0sX84Q9/CNiH53pcm3o0pm7PwZa6D40xAX2VlZWZhQsXGofDYfbt2+evaYp9WJ/+tm7daqZPn26WLl1q4uPjzbPPPlujJi8vz7Rt29YsXLjQ7Ny509x1112mffv2pry83F9z7733mqSkJJOfn2+2bdtmrrnmGjN48OB69xLSgeWH6vJmkJqaaqZPnx4wb9q0aWbIkCH++7fddpsZOXJkQE1KSoq55557jDHGVFdXm/j4ePPUU0/5l1dUVBin02mWLl16gV2cXUP192MnT540UVFR5tVXX/XPGz9+vBk9evSFDDdoDdXfokWLjMvlOus2mmv/GdN4+/DZZ581UVFRAX+gmmMfGmPM119/bSSZwsLCs9Y0xGts165dRpL561//6q955513jMPhMF999VVDthSgIfqrzdatW40k8+WXX/rndenSpdY3ksbWUD2e7zkYavtw9OjR5he/+EXAvObYh3Xp74fONsZBgwaZrKws//1Tp06ZxMREk5OTY4w5/Zps06aNWbZsmb/m008/NZJMUVFRvcYe0h8JBauqqqrGxwMRERHaunWrTpw4IUkqKipSWlpaQE16erqKiookSaWlpXK73QE1LpdLKSkp/prmUpf+fuzo0aM6ceKEYmJiAuYXFBQoNjZWPXr00OTJk3X48OFGG3dd1bW/yspKdenSRUlJSRo9erR27tzpX2bz/pPqtw8XLFigsWPHKjIyMmB+c+xDj8cjSTWeTz/UEK+xoqIitW/fXldffbW/Ji0tTa1atdKWLVsarJ8fa4j+zrZdh8Oh9u3bB8yfPXu2Lr74YvXv319PPfWUTp48Wf/B11FD9niu52Ao7cPy8nK9/fbbmjhxYo1lTb0P69Lf+Rw/flzFxcUB/watWrVSWlqa/9+guLhYJ06cCKjp2bOnOnfuXO+/pQSWH0hPT9crr7yi4uJiGWO0bds2vfLKKzpx4oS+/fZbSZLb7VZcXFzAenFxcXK73f7lZ+adraa51KW/H3vooYeUmJgY8KQbPny4Fi9erPz8fD355JMqLCzUiBEjdOrUqaZqpVZ16a9Hjx5auHChVq5cqddee03V1dUaPHiwDh48KMnu/ScFvw+3bt2qHTt2aNKkSQHzm2MfVldXa+rUqRoyZIh69ep11rqGeI253W7FxsYGLG/durViYmIabT82VH8/duzYMT300EMaN25cwI/O/eu//qvy8vK0YcMG3XPPPXriiSf04IMPNkwzZ9GQPZ7vORhK+/DVV19VVFSU/vEf/zFgflPvw7r2dz7ffvutTp06dd7XYNu2bWuE7Av5WxoSv9bcUGbMmCG3261rrrlGxhjFxcVp/PjxmjNnznl/9rolCLa/2bNnKy8vTwUFBQH/qx87dqz/du/evdWnTx9dfvnlKigo0E033dQkvdSmLv2lpqYqNTXVv87gwYN15ZVX6sUXX9Rjjz3WXEOvs2D34YIFC9S7d28NGjQoYH5z7MOsrCzt2LFDmzZtapTtN7fG6O/EiRO67bbbZIzRvHnzApZNmzbNf7tPnz5q27at7rnnHuXk5DTa5dMbskcb/4401nN04cKFuv3222scHW3qfdjSX4Mt/124AUVERGjhwoU6evSovvjiC+3fv19du3ZVVFSUOnbsKEmKj4+vcZZzeXm54uPj/cvPzDtbTXOpS39nPP3005o9e7beffdd9enT55zbveyyy3TJJZdo7969jTn88wqmvzPatGmj/v37+8du8/6TguvR5/MpLy+v1sPQP9bY+3DKlClatWqVNmzYoE6dOp2ztiFeY/Hx8fr6668Dlp88eVLfffddo+zHhuzvjDNh5csvv9S6desCjq7UJiUlRSdPntQXX3xRrx7OpzF6/KEfPwdDYR9K0vvvv6/du3fXOMpZm8bch8H0dz6XXHKJwsLCzvsaPH78uCoqKs5aEywCSy3atGmjTp06KSwsTHl5efqHf/iHgP+h5+fnB9SvW7fO/7/25ORkxcfHB9R4vV5t2bIl4H/2zelc/UnSnDlz9Nhjj2nNmjUBnx+fzcGDB3X48GElJCQ05rDr7Hz9/dCpU6f0ySef+MfeEvafVLcely1bpqqqKv3mN7857/Yaax8aYzRlyhQtX75c69evV3Jy8nnXaYjXWGpqqioqKlRcXOyvWb9+vaqrq5WSktIQrUlqnP6kv4eVPXv26L333tPFF1983u2WlJSoVatWNT5GuVCN1eOP/fg52NL34RkLFizQgAED1Ldv3/NutzH2YX36O5+2bdtqwIABAf8G1dXVys/P9/8bDBgwQG3atAmo2b17t/bv31//v6X1OlW3hThy5IjZvn272b59u5FknnnmGbN9+3b/mfYPP/ywueOOO/z1u3fvNn/5y1/M//3f/5ktW7aYMWPGmJiYGFNaWuqv+eCDD0zr1q3N008/bT799FMza9asWr9y2b59e7Ny5Urz8ccfm9GjRzfK12Ibo7/Zs2ebtm3bmv/6r/8K+KrdkSNH/I85ffp0U1RUZEpLS817771nfv7zn5vu3bubY8eOWd/fv//7v5u1a9eaffv2meLiYjN27FgTHh5udu7cGfBv0BT7r7F6POPaa681Y8aMqfUxm2ofTp482bhcLlNQUBDwfDp69Ki/5o477jAPP/yw/35DvcaGDx9u+vfvb7Zs2WI2bdpkunfv3uBfiW2M/o4fP25uueUW06lTJ1NSUhKw3aqqKmOMMR9++KF59tlnTUlJidm3b5957bXXTMeOHU1mZmaD9tdYPdb1OdhS9+EZHo/HXHTRRWbevHk1Hrep9mF9+quqqvL/XUpISDDTp08327dvN3v27PHX5OXlGafTaXJzc82uXbvM3Xffbdq3bx9wmYh7773XdO7c2axfv95s27bNpKammtTU1Hr3EtKBZcOGDUZSjWn8+PHGmNNfq7vhhhv89bt27TL9+vUzERERJjo62owePdp89tlnNbb7xhtvmCuuuMK0bdvWXHXVVebtt98OWF5dXW1mzJhh4uLijNPpNDfddJPZvXt3i+ivS5cutW5z1qxZxhhjjh49aoYNG2Y6duxo2rRpY7p06WLuuuuuGtcysbW/qVOnms6dO5u2bduauLg488tf/tJ89NFHATVNtf8aq0djjPnss8+MJPPuu+/WWNaU+7C23iQFXBPmhhtu8Pd7RkO8xg4fPmzGjRtn2rVrZ6Kjo82dd97pD94291daWnrW7W7YsMEYY0xxcbFJSUkxLpfLhIeHmyuvvNI88cQTDR44G6vHuj4HW+o+POPFF180ERERpqKiosayptqH9envbM/BH/4tMsaY//zP//T/PR00aJDZvHlzwPLvv//e/Mu//Ivp0KGDueiii8yvfvUrU1ZWVu9eHP+/IQAAAGtxDgsAALAegQUAAFiPwAIAAKxHYAEAANYjsAAAAOsRWAAAgPUILAAAwHoEFgAAYD0CCwAAsB6BBQAAWI/AAgAArEdgAQAA1vt/MA0F6S68/wsAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# plot scaler interval\n", + "plot_intervals(x[2], y_i[2])" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "07738b78-0491-48e7-bf29-46599371b926", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "2" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "x[2]" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "73e9ee8c-4109-445e-999f-1275f155fdc3", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "1" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "x_test = np.array([[2]])\n", + "len(x_test)" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "5c55c689-70a7-4151-999f-32cc2079c4a0", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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fydOnNBDDz2k3r17KzIyUomJicrMzNShQ4cCttG1a9ca+3D27NkN2l9j9SjV7TnYUvehpFpfgw6HQ0899ZS/pin2YX3627lzp37961/7x/fcc8/VWjd37lx17dpV4eHhSklJqfFecezYMWVlZeniiy9Wu3bt9Otf/1rl5eX1b8aEsNWrV5t/+7d/M2+99ZaRZJYvX37O+j//+c8mKirK5OXlmX379pmlS5eadu3amf/+7//213zwwQcmLCzMzJkzx+zatcs8+uijpk2bNuaTTz7x18yePdu4XC6zYsUK87//+7/mlltuMcnJyeb777+3vr9//ud/NnPnzjXbt283n376qZkwYYJxuVzm4MGD/prx48eb4cOHm7KyMv/03XffNWhvjdXfokWLTHR0dMDY3W53wHaaav81Vo+HDx8O6G/Hjh0mLCzMLFq0yF/TVPswPT3dLFq0yOzYscOUlJSYX/7yl6Zz586msrLyrOs01Gts+PDhpm/fvmbz5s3m/fffN926dTPjxo2zvr+KigqTlpZmXn/9dfPZZ5+ZoqIiM2jQIDNgwICA7XTp0sX84Q9/CNiH53pcm3o0pm7PwZa6D40xAX2VlZWZhQsXGofDYfbt2+evaYp9WJ/+tm7daqZPn26WLl1q4uPjzbPPPlujJi8vz7Rt29YsXLjQ7Ny509x1112mffv2pry83F9z7733mqSkJJOfn2+2bdtmrrnmGjN48OB69xLSgeWH6vJmkJqaaqZPnx4wb9q0aWbIkCH++7fddpsZOXJkQE1KSoq55557jDHGVFdXm/j4ePPUU0/5l1dUVBin02mWLl16gV2cXUP192MnT540UVFR5tVXX/XPGz9+vBk9evSFDDdoDdXfokWLjMvlOus2mmv/GdN4+/DZZ581UVFRAX+gmmMfGmPM119/bSSZwsLCs9Y0xGts165dRpL561//6q955513jMPhMF999VVDthSgIfqrzdatW40k8+WXX/rndenSpdY3ksbWUD2e7zkYavtw9OjR5he/+EXAvObYh3Xp74fONsZBgwaZrKws//1Tp06ZxMREk5OTY4w5/Zps06aNWbZsmb/m008/NZJMUVFRvcYe0h8JBauqqqrGxwMRERHaunWrTpw4IUkqKipSWlpaQE16erqKiookSaWlpXK73QE1LpdLKSkp/prmUpf+fuzo0aM6ceKE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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plot_intervals(x_test, y_i[2])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4336c600-e35a-4e5d-b387-2479f8449e95", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "transformer", + "language": "python", + "name": "transformer" + }, + "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.11.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} From 1bc8557c707c3abf1252a73e604cdb4e5563216f Mon Sep 17 00:00:00 2001 From: leslieDLcy Date: Tue, 2 Apr 2024 22:49:35 +0100 Subject: [PATCH 05/11] plotting function succeeds --- intervals/mat_features.py | 25 +- intervals/plotting.py | 27 +- questions.md | 3 + tests/matrix_multiplication.ipynb | 568 ++++++++++++++++++++++++------ tests/plotting.ipynb | 127 +++++-- 5 files changed, 589 insertions(+), 161 deletions(-) create mode 100644 questions.md diff --git a/intervals/mat_features.py b/intervals/mat_features.py index 67682f2..f6616c7 100644 --- a/intervals/mat_features.py +++ b/intervals/mat_features.py @@ -50,10 +50,14 @@ def rowcol2(x,W): """ s = x.shape - y=[] - for i in range(s[0]): - y.append(dot(x[i],W)) - return intervalise(y) + if len(s) > 1: + y=[] + for i in range(s[0]): + y.append(dot(x[i],W)) + + return intervalise(y) + else: + print('x shall be a 2 dimensional array') @@ -110,10 +114,15 @@ def intvl_matmul(x, W): row_cp_list = [] sW = W.shape - if (len(sW)) > 1 & (sW[1]>1): - for j in range(sW[1]): - row_cp_list.append(rowcol2(x, W[:, j])) - return intervalise(row_cp_list) + if (len(sW)) > 1: + if (sW[1]>1): + for j in range(sW[1]): + row_cp_list.append(rowcol2(x, W[:, j])) + return intervalise(row_cp_list) + elif sW[1]==1: + return rowcol2(x, W[:, 0]) + else: + return rowcol2(x, W) else: return rowcol2(x, W) diff --git a/intervals/plotting.py b/intervals/plotting.py index f5a18dd..28dae5b 100644 --- a/intervals/plotting.py +++ b/intervals/plotting.py @@ -5,9 +5,6 @@ """ -------------------------- -Created Feb 2022 -Marco De Angelis -github.com/marcodeangelis Editted by Leslie Feb 2024 MIT License -------------------------- @@ -17,18 +14,27 @@ def plot_intervals(x, y_i, **kwargs): """ plot intervals vertically args: - x: array-like - x-axis locations - y_i: array-like + x: array-like precise values + x-axis coordinates + y_i: array-like Interval objects array of intervals """ fig, ax = plt.subplots() + + def basic_plot(x, y_i, **kwargs): + ax.plot([x, x], [y_i.hi, y_i.lo], 'blue', **kwargs) + if np.any(y_i.lo == y_i.hi): + sc_x = x[y_i.lo == y_i.hi] + sc_y = y_i[y_i.lo == y_i.hi].lo + ax.scatter(sc_x, sc_y, c='blue', **kwargs) + if len(x.shape) > 1: for xx, interval in zip(x, y_i): - ax.plot([xx, xx], [interval.hi, interval.lo], 'r', **kwargs) + basic_plot([xx, xx], [interval.hi, interval.lo]) else: - ax.plot([x, x], [y_i.hi, y_i.lo], 'r', **kwargs) + basic_plot(x, y_i) + return ax def plot_lower_bound(x, y_i, **kwargs): @@ -36,12 +42,13 @@ def plot_lower_bound(x, y_i, **kwargs): args: x: array-like - x-axis locations + x-axis coordinates y_i: array-like array of intervals """ fig, ax = plt.subplots() - ax.scatter(x, y_i.lo, **kwargs) + ax.scatter(x, y_i.lo, label='lower bound', **kwargs) + ax.legend() diff --git a/questions.md b/questions.md new file mode 100644 index 0000000..b5c2b3b --- /dev/null +++ b/questions.md @@ -0,0 +1,3 @@ +Here I note some questions that are to be solved by Marco + +- [ ] how to squeeze e.g. shape (32, 1) into (32,) \ No newline at end of file diff --git a/tests/matrix_multiplication.ipynb b/tests/matrix_multiplication.ipynb index 8e00d57..e328037 100644 --- a/tests/matrix_multiplication.ipynb +++ b/tests/matrix_multiplication.ipynb @@ -130,7 +130,6 @@ "cell_type": "markdown", "id": "f5e18d79-62f4-462b-80ca-50b947a7fe84", "metadata": { - "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ @@ -139,12 +138,155 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, + "id": "dadc30a0-8f0b-4cce-b3fa-f82cf86612cc", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(3,)\n" + ] + }, + { + "data": { + "text/plain": [ + "[0.9,1.1]\n", + "[2.7,3.3000000000000003]\n", + "[4.5,5.5]" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "vec = create_interval(matrix=np.array([1, 3, 5]))\n", + "print(vec.shape)\n", + "vec" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "bb37117e-7156-4273-8f68-c373dfb289fe", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(3,)" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "vec.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "dda27fcf-29cc-4454-926f-b2bd7bb70715", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[0.9,1.1]" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "vec[0]" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "f9ed7783-218a-4757-ad14-e9dd7a04c850", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "x shall be a 2 dimensional array\n", + "x shall be a 2 dimensional array\n", + "x shall be a 2 dimensional array\n" + ] + }, + { + "data": { + "text/plain": [ + "[nan,nan]\n", + "[nan,nan]\n", + "[nan,nan]" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "intvl_matmul(vec, v1)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "68ae81db-9b26-4bbb-bc03-ef0f524cf659", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "x shall be a 2 dimensional array\n" + ] + } + ], + "source": [ + "rowcol2(vec, v1)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, "id": "4eff5388-d7b3-4202-a34b-6dcc102a8ce9", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(1, 3)\n" + ] + }, + { + "data": { + "text/plain": [ + "[0.9 1.1] [2.7 3.3] [4.5 5.5]" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "row_vec = create_interval(matrix=np.array([[1, 3, 5]]))\n", + "print(row_vec.shape)\n", "row_vec" ] }, @@ -154,140 +296,387 @@ "id": "f5995b3c-6f73-4f13-b299-160d83ddcf7b", "metadata": {}, "outputs": [], - "source": [] + "source": [ + "# In theory, (1 by 3) @ (3 by 3)" + ] }, { "cell_type": "code", "execution_count": null, - "id": "d4cd727b-4393-4c50-8b44-715476d7ff1e", + "id": "9a2c2999-2a7d-4376-b0fd-70089a4f519c", "metadata": {}, "outputs": [], - "source": [] + "source": [ + "# what if we explicitly write down the row vector as (1 by 3)" + ] }, { "cell_type": "code", - "execution_count": null, - "id": "9a2c2999-2a7d-4376-b0fd-70089a4f519c", + "execution_count": 20, + "id": "f19a824e-afbf-44dc-9f4b-5ebe114a1419", "metadata": {}, - "outputs": [], - "source": [] + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(3, 1)\n" + ] + }, + { + "data": { + "text/plain": [ + "[31.59 47.19]\n", + "[38.88 58.08]\n", + "[46.17 68.97]" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tt = intvl_matmul(row_vec, v1)\n", + "print(tt.shape)\n", + "tt" + ] }, { "cell_type": "code", - "execution_count": null, - "id": "bf7c771f-e297-46b5-8af8-71ba14ed430b", + "execution_count": 32, + "id": "f6098480-d5af-48c0-acea-0026597818b8", "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "markdown", - "id": "70d232da-a898-449b-aa13-b6696272d2c2", - "metadata": { - "tags": [] - }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[31.590000000000003,47.190000000000005]\n", + "[38.879999999999995,58.08000000000001]\n", + "[46.17,68.97000000000001]\n" + ] + } + ], "source": [ - "#### mat @ col_vec" + "for i in tt:\n", + " print(i)" ] }, { "cell_type": "code", - "execution_count": 8, - "id": "6db7d27c-3493-45af-bf03-6fd3ac53bfe8", + "execution_count": 35, + "id": "24aed9d8-2345-4046-928c-dab988247b13", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "[0. 0.] [0.9 1.1] [1.8 2.2]\n", - "[2.7 3.3] [3.6 4.4] [4.5 5.5]\n", - "[5.4 6.6] [6.3 7.7] [7.2 8.8]" + "['_Interval__hi',\n", + " '_Interval__lo',\n", + " '_Interval__shape',\n", + " '__add__',\n", + " '__class__',\n", + " '__delattr__',\n", + " '__dict__',\n", + " '__dir__',\n", + " '__doc__',\n", + " '__eq__',\n", + " '__format__',\n", + " '__ge__',\n", + " '__getattribute__',\n", + " '__getitem__',\n", + " '__getstate__',\n", + " '__gt__',\n", + " '__hash__',\n", + " '__init__',\n", + " '__init_subclass__',\n", + " '__iter__',\n", + " '__le__',\n", + " '__len__',\n", + " '__lt__',\n", + " '__module__',\n", + " '__mul__',\n", + " '__ne__',\n", + " '__neg__',\n", + " '__new__',\n", + " '__next__',\n", + " '__pos__',\n", + " '__pow__',\n", + " '__radd__',\n", + " '__reduce__',\n", + " '__reduce_ex__',\n", + " '__repr__',\n", + " '__rge__',\n", + " '__rgt__',\n", + " '__rle__',\n", + " '__rlt__',\n", + " '__rmul__',\n", + " '__rsub__',\n", + " '__rtruediv__',\n", + " '__setattr__',\n", + " '__sizeof__',\n", + " '__str__',\n", + " '__sub__',\n", + " '__subclasshook__',\n", + " '__truediv__',\n", + " '__weakref__',\n", + " 'hi',\n", + " 'lo',\n", + " 'scalar',\n", + " 'shape',\n", + " 'unsized',\n", + " 'val']" ] }, - "execution_count": 8, + "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "# given a matrix\n", - "v1" + "dir(tt)" ] }, { "cell_type": "code", - "execution_count": 9, - "id": "c835a252-6aed-43fb-91a2-3fe62307ed12", + "execution_count": null, + "id": "1cddc556-f4da-42a4-9ccb-01e7a52098eb", "metadata": {}, "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 36, + "id": "3f915c01-50c9-48eb-a996-9f01128d8d4d", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[31.59],\n", + " [38.88],\n", + " [46.17]])" + ] + }, + "execution_count": 36, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "# consider just a vector\n", - "vec = create_interval(matrix=np.array([1, 3, 5]))" + "tt.lo" ] }, { "cell_type": "code", - "execution_count": 10, - "id": "55846437-7298-43c7-92f9-a49d85da66a8", + "execution_count": 38, + "id": "af2c2205-0dc2-4077-8873-a8439160d3d3", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "3" + "array([[47.19],\n", + " [58.08],\n", + " [68.97]])" ] }, - "execution_count": 10, + "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "v1.shape[0]" + "tt.hi" ] }, { "cell_type": "code", - "execution_count": 11, - "id": "6fe6ff32-de12-45ee-95f4-95a8b4d27385", + "execution_count": 48, + "id": "bf7c771f-e297-46b5-8af8-71ba14ed430b", "metadata": {}, "outputs": [], "source": [ - "# therefore, marco's rowvec works when the latter vec is just a vector" + "def reshape(interval):\n", + " length = len(interval)\n", + " new = I(lo=np.squeeze(interval.lo), hi=np.squeeze(interval.hi))\n", + " return new[np.newaxis, :]" ] }, { "cell_type": "code", - "execution_count": 14, - "id": "989f92e5-08b3-4493-9451-77f30f202a26", + "execution_count": 49, + "id": "5dfbe597-4ba6-4669-a6f1-8b4d3400c0a1", + "metadata": {}, + "outputs": [], + "source": [ + "new = reshape(tt)" + ] + }, + { + "cell_type": "code", + "execution_count": 50, + "id": "379ef942-6691-4ce4-89a8-627e35634db4", "metadata": {}, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "(3,)\n" - ] - }, + "data": { + "text/plain": [ + "(1, 3)" + ] + }, + "execution_count": 50, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "new.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "id": "fee62ac2-3f42-421b-9b96-5bfec3218d35", + "metadata": {}, + "outputs": [ { "data": { "text/plain": [ - "[10.53,15.730000000000002]\n", - "[32.4,48.400000000000006]\n", - "[54.269999999999996,81.07000000000002]" + "[31.59 47.19] [38.88 58.08] [46.17 68.97]" ] }, - "execution_count": 14, + "execution_count": 51, "metadata": {}, "output_type": "execute_result" } ], "source": [ + "new" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1c9c2e95-a4a3-4041-a828-524bfba0305b", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "93d79e7e-57be-454b-97f1-96c708454bd9", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "70d232da-a898-449b-aa13-b6696272d2c2", + "metadata": { + "tags": [] + }, + "source": [ + "#### mat @ col_vec" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6db7d27c-3493-45af-bf03-6fd3ac53bfe8", + "metadata": {}, + "outputs": [], + "source": [ + "# given a matrix\n", + "v1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "eb667504-afbb-4be1-886e-d757f0535d6c", + "metadata": {}, + "outputs": [], + "source": [ + "intvl_matmul(v1, vec)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "77879741-133a-4ef2-94bd-d0d75650aea3", + "metadata": {}, + "outputs": [], + "source": [ + "# therefore, marco's rowvec works when the latter vec is just a vector\n", + "\n", "test_marco = rowcol2(v1, vec)\n", "print(test_marco.shape)\n", "test_marco" ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "c835a252-6aed-43fb-91a2-3fe62307ed12", + "metadata": {}, + "outputs": [], + "source": [ + "# what if we explicitly express a col vector\n", + "\n", + "col_vec = create_interval(matrix=np.array([1, 3, 5]))\n", + "col_vec.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "55846437-7298-43c7-92f9-a49d85da66a8", + "metadata": {}, + "outputs": [], + "source": [ + "col_vec = col_vec[:, np.newaxis]\n", + "print(col_vec.shape)\n", + "col_vec" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6fe6ff32-de12-45ee-95f4-95a8b4d27385", + "metadata": {}, + "outputs": [], + "source": [ + "intvl_matmul(v1, col_vec)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cff4877d-0a67-4e0a-9804-911231fba552", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a8b747e4-4f00-46a4-a527-ac17234d9b79", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "63eb993c-1d64-4fe0-851f-6fc3cc90d31f", + "metadata": {}, + "outputs": [], + "source": [] + }, { "cell_type": "markdown", "id": "ea3e169a-88cf-4645-b613-fc513f686bd1", @@ -300,30 +689,10 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": null, "id": "67ede585-d4b3-4979-b111-8c191117a226", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(3,)\n" - ] - }, - { - "data": { - "text/plain": [ - "[0.9,1.1]\n", - "[2.7,3.3000000000000003]\n", - "[4.5,5.5]" - ] - }, - "execution_count": 17, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "# create a row vector \n", "\n", @@ -380,23 +749,10 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": null, "id": "f8f0f97d-86b1-416c-866c-1c5c2cbeb445", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[29.16,43.56000000000001]\n", - "[87.48,130.68000000000004]\n", - "[145.79999999999998,217.80000000000004]" - ] - }, - "execution_count": 18, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "# matrix which is v1\n", "'''\n", @@ -410,42 +766,20 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": null, "id": "5863a47b-c797-473b-8be0-1aa806af23b8", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "(3,)" - ] - }, - "execution_count": 19, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "result.shape" ] }, { "cell_type": "code", - "execution_count": 20, + "execution_count": null, "id": "e8c73ff7-1ade-47d1-b7be-7bcffc17569f", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "intervals.number.Interval" - ] - }, - "execution_count": 20, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "result_ = intvl_matmul(x=row_vec, W=v1)\n", "type(result_)" diff --git a/tests/plotting.ipynb b/tests/plotting.ipynb index 7de079b..63f679b 100644 --- a/tests/plotting.ipynb +++ b/tests/plotting.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": 16, "id": "340b20c6-58ae-4175-a4cf-757905bb8c47", "metadata": {}, "outputs": [], @@ -10,8 +10,8 @@ "from intervals.number import Interval as I\n", "from intervals.methods import (lo,hi,mid,rad,width,intervalise, exp)\n", "from intervals.random import uniform_endpoints \n", - "from intervals.mat_features import initialise_interval_matrix, create_interval, dot, rowcol, rowcol2, intvl_matmul, consume_list\n", - "from intervals.plotting import plot_intervals" + "from intervals.plotting import plot_intervals, plot_lower_bound\n", + "from intervals.mat_features import create_interval" ] }, { @@ -84,12 +84,86 @@ { "cell_type": "code", "execution_count": 7, + "id": "70faa6b6-ebe3-4e5a-8847-a3b7395db672", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([0])" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "x[y_i.lo == y_i.hi]" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "14badbe4-ec58-49f8-9462-944600985e76", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([0.])" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "y_i[y_i.lo == y_i.hi].lo" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "86ea9341-371e-40c9-9826-78d9c19ea7d8", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "fig, ax = plt.subplots()\n", + "ax.scatter(x[y_i.lo == y_i.hi], y_i[y_i.lo == y_i.hi].lo)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, "id": "18307e47-7967-4ad6-9178-d667e3590eb3", "metadata": {}, "outputs": [ { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAhYAAAGdCAYAAABO2DpVAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAAAVqUlEQVR4nO3db2yV5fnA8esA9tRC28kcCKH+2cxw6MDJxFSTiYoSZ4y8mlsWR5z741IXCck2eDNi9qIuW3RmI2rmlGSbwalBEzdlDgUyp1ELZMCMmc64LgrMZGmhLNW0z+8FoftVKfbU6/T00M8nOUl7ep8+F3eenH7znENbKoqiCACABFNqPQAAcOIQFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAmmnjfcDBwcF46623orm5OUql0ngfHgAYg6Io4uDBgzF37tyYMmXk6xLjHhZvvfVWtLW1jfdhAYAE3d3dMW/evBG/Pu5h0dzcHBFHBmtpaRnvwwMAY9Db2xttbW1DP8dHMu5hcfTlj5aWFmEBAHXmw97G4M2bAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAECacf9bIQBAFRRFxOHDRz5uaor4kL/pUS2uWADAieDw4YgZM47cjgZGDQgLACCNsAAA0ggLACCNsAAA0ggLACCNsAAA0ggLACCNsAAA0ggLACCNsAAA0ggLACCNsAAA0ggLACCNsAAA0ggLACCNsAAA0ggLACCNsAAA0ggLACCNsAAA0ggLACCNsAAA0ggLACCNsAAA0ggLACCNsAAA0ggLACCNsAAA0ggLACCNsAAA0ggLACCNsAAA0ggLACCNsAAA0nyksLj99tujVCrFqlWrksYBAOrZmMPipZdeinvvvTcWLlyYOQ8AUMfGFBaHDh2Kr371q/HLX/4yTjnllOyZAIA6Naaw6OjoiGuuuSaWLVv2oWv7+/ujt7d32A0AODFNq/QBGzdujB07dsRLL700qvWdnZ1x2223VTwYAFB/Krpi0d3dHbfeemv89re/jcbGxlE9Zu3atdHT0zN06+7uHtOgAMDEV9EVi66urjhw4EBccMEFQ/cNDAzE9u3b4xe/+EX09/fH1KlThz2mXC5HuVzOmRYAmNAqCosrrrgidu/ePey+G2+8Mc4555z4wQ9+8IGoAAAml4rCorm5Oc4777xh902fPj0+/vGPf+B+AGDy8Zs3AYA0Ff+vkPfbunVrwhgAwInAFQsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAII2wAADSCAsAIE1FYXH33XfHwoULo6WlJVpaWqK9vT2efPLJas0GANSZisJi3rx5cfvtt0dXV1e8/PLLcfnll8d1110Xe/furdZ8AEAdKRVFUXyUbzBz5sz4yU9+EjfddNOo1vf29kZra2v09PRES0vLRzk0QH0qiojDh4983NQUUSrVdh5ODH19ETNmHPn40KGI6dNTv/1of35PG+sBBgYG4uGHH46+vr5ob28fcV1/f3/09/cPGwxgUjt8uKo/AKCWKn7z5u7du2PGjBlRLpfj5ptvjk2bNsWCBQtGXN/Z2Rmtra1Dt7a2to80MAAwcVX8Usi7774b//znP6OnpyceeeSRuO+++2Lbtm0jxsWxrli0tbV5KQSYvKp8yZpJql5fCmloaIizzz47IiIWL14cL730Utx1111x7733HnN9uVyOcrlc6WEAgDr0kX+PxeDg4LArEgDA5FXRFYu1a9fG1VdfHaeffnocPHgwHnzwwdi6dWts3ry5WvMBAHWkorA4cOBAfO1rX4u33347WltbY+HChbF58+a48sorqzUfAFBHKgqLX/3qV9WaAwA4AfhbIQBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKSpKCw6OzvjwgsvjObm5pg1a1asWLEiXn311WrNBgDUmYrCYtu2bdHR0REvvPBCPP300/Hee+/FVVddFX19fdWaDwCoI9MqWfzUU08N+3zDhg0xa9as6Orqii984QupgwEA9aeisHi/np6eiIiYOXPmiGv6+/ujv79/6PPe3t6PckgAYAIb85s3BwcHY9WqVXHJJZfEeeedN+K6zs7OaG1tHbq1tbWN9ZAAwAQ35rDo6OiIPXv2xMaNG4+7bu3atdHT0zN06+7uHushAYAJbkwvhdxyyy3xxBNPxPbt22PevHnHXVsul6NcLo9pOACgvlQUFkVRxHe/+93YtGlTbN26Nc4666xqzQUA1KGKwqKjoyMefPDBePzxx6O5uTn27dsXERGtra1x8sknV2VAAKB+VPQei7vvvjt6enpi6dKlMWfOnKHbQw89VK35AIA6UvFLIQAAI/G3QgCANMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgzrdYDwIRVFBGHDx/5uKkpolSq7TwAdcAVCxjJ4cMRM2YcuR0NDACOS1gAAGm8FAIAJ4KmpohDh/73cY0ICwA4EZRKEdOn13oKL4UAAHmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGkqDovt27fHtddeG3Pnzo1SqRSPPfZYFcYCAOpRxWHR19cXixYtivXr11djHgCgjk2r9AFXX311XH311dWYBQCocxWHRaX6+/ujv79/6PPe3t5qHxIAqJGqv3mzs7MzWltbh25tbW3VPiQAUCNVD4u1a9dGT0/P0K27u7vahwSY2JqaIg4dOnJraqr1NJCq6i+FlMvlKJfL1T4MQP0olSKmT6/1FFAVfo8FAJCm4isWhw4ditdee23o8zfeeCN27doVM2fOjNNPPz11OACgvlQcFi+//HJcdtllQ5+vXr06IiJWrlwZGzZsSBsMAKg/FYfF0qVLoyiKaswCANQ577EAANIICwAgjbAAANIICwAgjbAAANIICwAgjbAAANIICwAgjbAAANIICwAgjbAAANIICwAgjbAAANIICwAgjbAAANIICwAgjbAAANIICwAgjbAAANIICwAgjbAAANIICwAgjbAAANIICwAgjbAAANIICwAgjbAAANIICwAgjbAAANIICwAgjbAAANJMq/UAMGE1NUUcOvS/jwH4UMICRlIqRUyfXuspAOqKl0IAgDTCAgBIIywAgDTCAgBIIywAgDTCAgBIIywAgDTCAgBIIywAgDTCAgBIIywAgDTCAgBIIywAgDTCAgBIIywAgDTCAgBIIywAgDTCAgBIIywAgDTCAgBIIywAgDTCAgBIIywAgDTCAgBIIywAgDTCAgBIIywAgDTCAgBIIywAgDTCAgBIM6awWL9+fZx55pnR2NgYF110Ubz44ovZcwEAdajisHjooYdi9erVsW7dutixY0csWrQoli9fHgcOHKjGfABAHak4LO6444745je/GTfeeGMsWLAg7rnnnmhqaor777+/GvMBAHWkorB49913o6urK5YtW/a/bzBlSixbtiyef/75Yz6mv78/ent7h90AgBNTRWHxzjvvxMDAQMyePXvY/bNnz459+/Yd8zGdnZ3R2to6dGtraxv7tADAhFb1/xWydu3a6OnpGbp1d3dX+5AAQI1Mq2TxqaeeGlOnTo39+/cPu3///v1x2mmnHfMx5XI5yuXy2CcEAOpGRVcsGhoaYvHixbFly5ah+wYHB2PLli3R3t6ePhwAUF8qumIREbF69epYuXJlfP7zn48lS5bEz372s+jr64sbb7yxGvMBAHWk4rC4/vrr49///nf88Ic/jH379sX5558fTz311Afe0AkATD6loiiK8Txgb29vtLa2Rk9PT7S0tIznoQGAMRrtz29/KwQASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIA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", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAhYAAAGdCAYAAABO2DpVAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAAAWeElEQVR4nO3df2zcdf3A8Ve30Svb2srEje3bwlDiEHBDFlgKQQYMFiSEhRjRr8EFMQophGWJuv3jQvyjGI18iSxIQJlRyRBwkKAwcbBNEQJ0WxxIiOCCRfZDEtNunSmk/Xz/aFYtrKPXvdrrrY9Hcll7fV/vtXc+uT7zueu1piiKIgAAEkyq9AAAwLFDWAAAaYQFAJBGWAAAaYQFAJBGWAAAaYQFAJBGWAAAaaaM9R329fXF22+/HfX19VFTUzPWdw8AjEBRFLF///6YM2dOTJo09HmJMQ+Lt99+O5qbm8f6bgGABB0dHdHU1DTk18c8LOrr6yOif7CGhoaxvnsAYAS6urqiubl54Of4UMY8LA49/dHQ0CAsAKDKfNjLGLx4EwBIIywAgDTCAgBIIywAgDTCAgBIIywAgDTCAgBIIywAgDTCAgBIIywAgDTCAgBIM+Z/KwQAyFcUEQcP9n88dWrEh/xJj1HjjAUAHAMOHoyYPr3/cigwKkFYAABphAUAkEZYAABphAUAkEZYAABphAUAkEZYAABphAUAkEZYAABphAUAkEZYAABphAUAkEZYAABphAUAkEZYAABphAUAkEZYAABphAUAkEZYAABphAUAkEZYAABphAUAkEZYAABphAUAkEZYAABphAUAkEZYAABphAUAkEZYAABphAUAkEZYAABphAUAkEZYAABphAUAkOaowuL222+PmpqaWLFiRdI4AEA1G3FYvPjii3HPPffE/PnzM+cBAKrYiMLiwIED8eUvfznuvffeOOGEE7JnAgCq1IjCorW1Na688spYsmTJh67t6emJrq6uQRcA4Ng0pdwbrF+/PrZt2xYvvvjisNa3tbXFbbfdVvZgAED1KeuMRUdHR9x6663xy1/+Murq6oZ1m9WrV0dnZ+fApaOjY0SDAgDjX1lnLNrb22Pfvn1xzjnnDFzX29sbW7dujbvuuit6enpi8uTJg25TKpWiVCrlTAsAjGtlhcWll14aO3fuHHTd9ddfH6effnp8+9vf/kBUAAATS1lhUV9fH2edddag66ZNmxYf/ehHP3A9ADDxeOdNACBN2b8V8n6bN29OGAMAOBY4YwEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApCkrLO6+++6YP39+NDQ0RENDQ7S0tMQTTzwxWrMBAFWmrLBoamqK22+/Pdrb2+Oll16KSy65JK6++up45ZVXRms+AKCK1BRFURzNN5gxY0Z8//vfjxtuuGFY67u6uqKxsTE6OzujoaHhaO4aoCoVRcTBg/0fT50aUVNT2Xk4NnR3R0yf3v/xgQMR06blfv/h/vyeMtI76O3tjYceeii6u7ujpaVlyHU9PT3R09MzaDCAiezgwdH9AQCVVPaLN3fu3BnTp0+PUqkUN954Y2zYsCHOOOOMIde3tbVFY2PjwKW5ufmoBgYAxq+ynwp599134+9//3t0dnbGww8/HPfdd19s2bJlyLg43BmL5uZmT4UAE9Zon7JmYqrap0Jqa2vjtNNOi4iIhQsXxosvvhh33nln3HPPPYddXyqVolQqlXs3AEAVOur3sejr6xt0RgIAmLjKOmOxevXquOKKK+Lkk0+O/fv3xwMPPBCbN2+OjRs3jtZ8AEAVKSss9u3bF1/5yldi9+7d0djYGPPnz4+NGzfGZZddNlrzAQBVpKyw+MlPfjJacwAAxwB/KwQASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0ZYVFW1tbnHvuuVFfXx8zZ86MZcuWxWuvvTZaswEAVaassNiyZUu0trbG888/H0899VS89957cfnll0d3d/dozQcAVJEp5Sx+8sknB32+bt26mDlzZrS3t8dnP/vZ1MEAgOpTVli8X2dnZ0REzJgxY8g1PT090dPTM/B5V1fX0dwlADCOjfjFm319fbFixYq44IIL4qyzzhpyXVtbWzQ2Ng5cmpubR3qXAMA4N+KwaG1tjZdffjnWr19/xHWrV6+Ozs7OgUtHR8dI7xIAGOdG9FTIzTffHI8//nhs3bo1mpqajri2VCpFqVQa0XAAQHUpKyyKoohbbrklNmzYEJs3b45TTz11tOYCAKpQWWHR2toaDzzwQDz22GNRX18fe/bsiYiIxsbGOP7440dlQACgepT1Gou77747Ojs7Y/HixTF79uyBy4MPPjha8wEAVaTsp0IAAIbib4UAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQZkqlB4DxqigiDh7s/3jq1IiamsrOA1ANnLGAIRw8GDF9ev/lUGAAcGTCAgBI46kQADgGTJ0aceDAfz6uFGEBAMeAmpqIadMqPYWnQgCARMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgjLACANGWHxdatW+Oqq66KOXPmRE1NTTz66KOjMBYAUI3KDovu7u5YsGBBrF27djTmAQCq2JRyb3DFFVfEFVdcMRqzAABVruywKFdPT0/09PQMfN7V1TXadwkAVMiov3izra0tGhsbBy7Nzc2jfZcAQIWMelisXr06Ojs7By4dHR2jfZcA49rUqREHDvRfpk6t9DSQa9SfCimVSlEqlUb7bgCqRk1NxLRplZ4CRof3sQAA0pR9xuLAgQPx+uuvD3y+a9eu2LFjR8yYMSNOPvnk1OEAgOpSdli89NJLcfHFFw98vnLlyoiIWL58eaxbty5tMACg+pQdFosXL46iKEZjFgCgynmNBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQZkqlB4DxaurUiAMH/vMxAB9OWMAQamoipk2r9BQA1cVTIQBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAmimVHiBDb2/EH/4QsXt3xOzZERdeGDF5cqWnAoCJZ0RnLNauXRtz586Nurq6WLRoUbzwwgvZcw3br38dMXduxMUXR/zv//b/O3du//UAwNgqOywefPDBWLlyZaxZsya2bdsWCxYsiKVLl8a+fftGY74j+vWvIz7/+Yi33hp8/T/+0X+9uACAsVVTFEVRzg0WLVoU5557btx1110REdHX1xfNzc1xyy23xKpVqz709l1dXdHY2BidnZ3R0NAwsqmj/+mPuXM/GBWH1NRENDVF7NrlaREAOFrD/fld1hmLd999N9rb22PJkiX/+QaTJsWSJUviueeeO+xtenp6oqura9Alwx/+MHRUREQURURHR/86AGBslBUW77zzTvT29sasWbMGXT9r1qzYs2fPYW/T1tYWjY2NA5fm5uaRT/tfdu/OXQcAHL1R/3XT1atXR2dn58Clo6Mj5fvOnp27DgA4emX9uumJJ54YkydPjr179w66fu/evXHSSScd9jalUilKpdLIJxzChRf2v4biH//of9rj/Q69xuLCC9PvGgAYQllnLGpra2PhwoWxadOmgev6+vpi06ZN0dLSkj7ckUyeHHHnnf0f19QM/tqhz//v/7xwEwDGUtlPhaxcuTLuvffe+NnPfhavvvpq3HTTTdHd3R3XX3/9aMx3RNdcE/HwwxH/8z+Dr29q6r/+mmvGfCQAmNDKfufNa6+9Nv75z3/Gd77zndizZ0+cffbZ8eSTT37gBZ1j5ZprIq6+2jtvAsB4UPb7WBytrPexAADGzqi8jwUAwJEICwAgjbAAANIICwAgjbAAANIICwAgjbAAANIICwAgjbAAANKU/ZbeR+vQG312dXWN9V0DACN06Of2h71h95iHxf79+yMiorm5eazvGgA4Svv374/GxsYhvz7mfyukr68v3n777aivr4+a9/+986PQ1dUVzc3N0dHR4W+QfAh7NXz2qjz2a/js1fDZq+Ebzb0qiiL2798fc+bMiUmThn4lxZifsZg0aVI0NTWN2vdvaGhw4A2TvRo+e1Ue+zV89mr47NXwjdZeHelMxSFevAkApBEWAECaYyYsSqVSrFmzJkqlUqVHGffs1fDZq/LYr+GzV8Nnr4ZvPOzVmL94EwA4dh0zZywAgMoTFgBAGmEBAKQRFgBAmqoKi7Vr18bcuXOjrq4uFi1aFC+88MIR1z/00ENx+umnR11dXXz605+O3/72t2M0aeWVs1fr1q2LmpqaQZe6uroxnLZytm7dGldddVXMmTMnampq4tFHH/3Q22zevDnOOeecKJVKcdppp8W6detGfc7xoNy92rx58weOq5qamtizZ8/YDFxBbW1tce6550Z9fX3MnDkzli1bFq+99tqH3m4iPmaNZK8m6mPW3XffHfPnzx9486uWlpZ44oknjnibShxTVRMWDz74YKxcuTLWrFkT27ZtiwULFsTSpUtj3759h13/pz/9Kb70pS/FDTfcENu3b49ly5bFsmXL4uWXXx7jycdeuXsV0f8ubbt37x64vPnmm2M4ceV0d3fHggULYu3atcNav2vXrrjyyivj4osvjh07dsSKFSvia1/7WmzcuHGUJ628cvfqkNdee23QsTVz5sxRmnD82LJlS7S2tsbzzz8fTz31VLz33ntx+eWXR3d395C3maiPWSPZq4iJ+ZjV1NQUt99+e7S3t8dLL70Ul1xySVx99dXxyiuvHHZ9xY6pokqcd955RWtr68Dnvb29xZw5c4q2trbDrv/CF75QXHnllYOuW7RoUfGNb3xjVOccD8rdq/vvv79obGwco+nGr4goNmzYcMQ13/rWt4ozzzxz0HXXXnttsXTp0lGcbPwZzl4988wzRUQU//rXv8ZkpvFs3759RUQUW7ZsGXLNRH7M+m/D2SuPWf9xwgknFPfdd99hv1apY6oqzli8++670d7eHkuWLBm4btKkSbFkyZJ47rnnDnub5557btD6iIilS5cOuf5YMZK9iog4cOBAnHLKKdHc3HzEAp7oJupxdTTOPvvsmD17dlx22WXx7LPPVnqciujs7IyIiBkzZgy5xrHVbzh7FeExq7e3N9avXx/d3d3R0tJy2DWVOqaqIizeeeed6O3tjVmzZg26ftasWUM+X7tnz56y1h8rRrJX8+bNi5/+9Kfx2GOPxS9+8Yvo6+uL888/P956662xGLmqDHVcdXV1xb///e8KTTU+zZ49O3784x/HI488Eo888kg0NzfH4sWLY9u2bZUebUz19fXFihUr4oILLoizzjpryHUT9THrvw13rybyY9bOnTtj+vTpUSqV4sYbb4wNGzbEGWeccdi1lTqmxvyvmzL+tLS0DCre888/Pz71qU/FPffcE9/97ncrOBnVbN68eTFv3ryBz88///x444034o477oif//znFZxsbLW2tsbLL78cf/zjHys9yrg33L2ayI9Z8+bNix07dkRnZ2c8/PDDsXz58tiyZcuQcVEJVXHG4sQTT4zJkyfH3r17B12/d+/eOOmkkw57m5NOOqms9ceKkezV+x133HHxmc98Jl5//fXRGLGqDXVcNTQ0xPHHH1+hqarHeeedN6GOq5tvvjkef/zxeOaZZ6KpqemIayfqY9Yh5ezV+02kx6za2to47bTTYuHChdHW1hYLFiyIO++887BrK3VMVUVY1NbWxsKFC2PTpk0D1/X19cWmTZuGfG6ppaVl0PqIiKeeemrI9ceKkezV+/X29sbOnTtj9uzZozVm1Zqox1WWHTt2TIjjqiiKuPnmm2PDhg3x9NNPx6mnnvqht5mox9ZI9ur9JvJjVl9fX/T09Bz2axU7pkb1paGJ1q9fX5RKpWLdunXFX/7yl+LrX/968ZGPfKTYs2dPURRFcd111xWrVq0aWP/ss88WU6ZMKX7wgx8Ur776arFmzZriuOOOK3bu3Fmp/8KYKXevbrvttmLjxo3FG2+8UbS3txdf/OIXi7q6uuKVV16p1H9hzOzfv7/Yvn17sX379iIiih/+8IfF9u3bizfffLMoiqJYtWpVcd111w2s/9vf/lZMnTq1+OY3v1m8+uqrxdq1a4vJkycXTz75ZKX+C2Om3L264447ikcffbT461//WuzcubO49dZbi0mTJhW///3vK/VfGDM33XRT0djYWGzevLnYvXv3wOXgwYMDazxm9RvJXk3Ux6xVq1YVW7ZsKXbt2lX8+c9/LlatWlXU1NQUv/vd74qiGD/HVNWERVEUxY9+9KPi5JNPLmpra4vzzjuveP755we+dtFFFxXLly8ftP5Xv/pV8clPfrKora0tzjzzzOI3v/nNGE9cOeXs1YoVKwbWzpo1q/jc5z5XbNu2rQJTj71DvxL5/suh/Vm+fHlx0UUXfeA2Z599dlFbW1t8/OMfL+6///4xn7sSyt2r733ve8UnPvGJoq6urpgxY0axePHi4umnn67M8GPscPsUEYOOFY9Z/UayVxP1MeurX/1qccoppxS1tbXFxz72seLSSy8diIqiGD/HlD+bDgCkqYrXWAAA1UFYAABphAUAkEZYAABphAUAkEZYAABphAUAkEZYAABphAUAkEZYAABphAUAkEZYAABp/h9M/2u+nRF6fgAAAABJRU5ErkJggg==", "text/plain": [ "
" ] @@ -105,13 +179,13 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 11, "id": "7ad57e12-fcd2-4279-bd3e-7864dd355870", "metadata": {}, "outputs": [ { "data": { - "image/png": "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fydOnNBDDz2k3r17KzIyUomJicrMzNShQ4cCttG1a9ca+3D27NkN2l9j9SjV7TnYUvehpFpfgw6HQ0899ZS/pin2YX3627lzp37961/7x/fcc8/VWjd37lx17dpV4eHhSklJqfFecezYMWVlZeniiy9Wu3bt9Otf/1rl5eX1b8aEsNWrV5t/+7d/M2+99ZaRZJYvX37O+j//+c8mKirK5OXlmX379pmlS5eadu3amf/+7//213zwwQcmLCzMzJkzx+zatcs8+uijpk2bNuaTTz7x18yePdu4XC6zYsUK87//+7/mlltuMcnJyeb777+3vr9//ud/NnPnzjXbt283n376qZkwYYJxuVzm4MGD/prx48eb4cOHm7KyMv/03XffNWhvjdXfokWLTHR0dMDY3W53wHaaav81Vo+HDx8O6G/Hjh0mLCzMLFq0yF/TVPswPT3dLFq0yOzYscOUlJSYX/7yl6Zz586msrLyrOs01Gts+PDhpm/fvmbz5s3m/fffN926dTPjxo2zvr+KigqTlpZmXn/9dfPZZ5+ZoqIiM2jQIDNgwICA7XTp0sX84Q9/CNiH53pcm3o0pm7PwZa6D40xAX2VlZWZhQsXGofDYfbt2+evaYp9WJ/+tm7daqZPn26WLl1q4uPjzbPPPlujJi8vz7Rt29YsXLjQ7Ny509x1112mffv2pry83F9z7733mqSkJJOfn2+2bdtmrrnmGjN48OB69xLSgeWH6vJmkJqaaqZPnx4wb9q0aWbIkCH++7fddpsZOXJkQE1KSoq55557jDHGVFdXm/j4ePPUU0/5l1dUVBin02mWLl16gV2cXUP192MnT540UVFR5tVXX/XPGz9+vBk9evSFDDdoDdXfokWLjMvlOus2mmv/GdN4+/DZZ581UVFRAX+gmmMfGmPM119/bSSZwsLCs9Y0xGts165dRpL561//6q955513jMPhMF999VVDthSgIfqrzdatW40k8+WXX/rndenSpdY3ksbWUD2e7zkYavtw9OjR5he/+EXAvObYh3Xp74fONsZBgwaZrKws//1Tp06ZxMREk5OTY4w5/Zps06aNWbZsmb/m008/NZJMUVFRvcYe0h8JBauqqqrGxwMRERHaunWrTpw4IUkqKipSWlpaQE16erqKiookSaWlpXK73QE1LpdLKSkp/prmUpf+fuzo0aM6ceKE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", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAiwAAAGdCAYAAAAxCSikAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAAAufUlEQVR4nO3de3QUZZ7/8U8ToBND0hAlNwkQBcGR6yDEgBccI4FhkczOKrCOAQ94YYMrg4waV2B2dA2i422HAS9AZDwQZRXYRQQxkCAaYIhkFVAWMApIOipOukkj4ZLn9wc/emwTIB1yedK+X+fUOd1V36p+vlR3+kN1dbXDGGMEAABgsVbNPQAAAIDzIbAAAADrEVgAAID1CCwAAMB6BBYAAGA9AgsAALAegQUAAFiPwAIAAKzXurkH0BCqq6t16NAhRUVFyeFwNPdwAABAHRhjdOTIESUmJqpVq3MfQwmJwHLo0CElJSU19zAAAEA9HDhwQJ06dTpnTUgElqioKEmnG46Ojm7m0QAAgLrwer1KSkryv4+fS0gEljMfA0VHRxNYAABoYepyOgcn3QIAAOsRWAAAgPUILAAAwHoEFgAAYD0CCwAAsB6BBQAAWI/AAgAArEdgAQAA1iOwAAAA6wUVWObNm6c+ffr4ryibmpqqd95555zrLFu2TD179lR4eLh69+6t1atXByw3xmjmzJlKSEhQRESE0tLStGfPnuA7AQAAISuowNKpUyfNnj1bxcXF2rZtm37xi19o9OjR2rlzZ631H374ocaNG6eJEydq+/btysjIUEZGhnbs2OGvmTNnjl544QXNnz9fW7ZsUWRkpNLT03Xs2LEL6wwAAIQMhzHGXMgGYmJi9NRTT2nixIk1lo0ZM0Y+n0+rVq3yz7vmmmvUr18/zZ8/X8YYJSYm6oEHHtD06dMlSR6PR3FxccrNzdXYsWPrNAav1yuXyyWPx8NvCQEhxBjp6NHTty+6SKrDz40AaEGCef+u9zksp06dUl5ennw+n1JTU2utKSoqUlpaWsC89PR0FRUVSZJKS0vldrsDalwul1JSUvw1tamqqpLX6w2YAISeo0eldu1OT2eCC4CfpqADyyeffKJ27drJ6XTq3nvv1fLly/Wzn/2s1lq32624uLiAeXFxcXK73f7lZ+adraY2OTk5crlc/ikpKSnYNgAAQAsSdGDp0aOHSkpKtGXLFk2ePFnjx4/Xrl27GmNsZ5WdnS2Px+OfDhw40KSPDwAAmlbrYFdo27atunXrJkkaMGCA/vrXv+r555/Xiy++WKM2Pj5e5eXlAfPKy8sVHx/vX35mXkJCQkBNv379zjoGp9Mpp9MZ7NABAEALdcHXYamurlZVVVWty1JTU5Wfnx8wb926df5zXpKTkxUfHx9Q4/V6tWXLlrOeFwMAAH56gjrCkp2drREjRqhz5846cuSIlixZooKCAq1du1aSlJmZqUsvvVQ5OTmSpPvvv1833HCD/vjHP2rkyJHKy8vTtm3b9NJLL0mSHA6Hpk6dqscff1zdu3dXcnKyZsyYocTERGVkZDRspwAAoMUKKrB8/fXXyszMVFlZmVwul/r06aO1a9fq5ptvliTt379frVr9/aDN4MGDtWTJEj366KN65JFH1L17d61YsUK9evXy1zz44IPy+Xy6++67VVFRoWuvvVZr1qxReHh4A7UIAABaugu+DosNuA4LEJp8vtNfaZakykopMrJ5xwOgYTXJdVgAAACaCoEFAABYj8ACAACsR2ABAADWI7AAAADrEVgAAID1CCwAAMB6BBYAAGA9AgsAALAegQUAAFiPwAIAAKxHYAEAANYjsAAAAOsRWAAAgPUILAAAwHoEFgAAYD0CCwAAsB6BBQAAWI/AAgAArEdgAQAA1iOwAAAA6xFYAACA9QgsAADAegQWAABgPQILAACwHoEFAABYj8ACAACsR2ABAADWI7AAAADrEVgAAID1CCwAAMB6QQWWnJwcDRw4UFFRUYqNjVVGRoZ27959znWGDh0qh8NRYxo5cqS/ZsKECTWWDx8+vH4dAQCAkNM6mOLCwkJlZWVp4MCBOnnypB555BENGzZMu3btUmRkZK3rvPXWWzp+/Lj//uHDh9W3b1/deuutAXXDhw/XokWL/PedTmcwQwMAACEsqMCyZs2agPu5ubmKjY1VcXGxrr/++lrXiYmJCbifl5eniy66qEZgcTqdio+PD2Y4AADgJ+KCzmHxeDySaoaSc1mwYIHGjh1b44hMQUGBYmNj1aNHD02ePFmHDx8+6zaqqqrk9XoDJgAAELrqHViqq6s1depUDRkyRL169arTOlu3btWOHTs0adKkgPnDhw/X4sWLlZ+fryeffFKFhYUaMWKETp06Vet2cnJy5HK5/FNSUlJ92wAAAC2Awxhj6rPi5MmT9c4772jTpk3q1KlTnda55557VFRUpI8//vicdZ9//rkuv/xyvffee7rppptqLK+qqlJVVZX/vtfrVVJSkjwej6Kjo4NrBIC1fD6pXbvTtysrpbOcKgeghfJ6vXK5XHV6/67XEZYpU6Zo1apV2rBhQ53Dis/nU15eniZOnHje2ssuu0yXXHKJ9u7dW+typ9Op6OjogAkAAISuoE66Ncbovvvu0/Lly1VQUKDk5OQ6r7ts2TJVVVXpN7/5zXlrDx48qMOHDyshISGY4QEAgBAV1BGWrKwsvfbaa1qyZImioqLkdrvldrv1/fff+2syMzOVnZ1dY90FCxYoIyNDF198ccD8yspK/e53v9PmzZv1xRdfKD8/X6NHj1a3bt2Unp5ez7YAAEAoCeoIy7x58ySdvhjcDy1atEgTJkyQJO3fv1+tWgXmoN27d2vTpk169913a2wzLCxMH3/8sV599VVVVFQoMTFRw4YN02OPPca1WAAAgKQLOOnWJsGctAOg5eCkWyC0NfpJtwAAAE2JwAIAAKxHYAEAANYjsAAAAOsRWAAAgPUILAAAwHoEFgAAYD0CCwAAsB6BBQAAWI/AAgAArEdgAQAA1iOwAAAA6xFYAACA9QgsAADAegQWAABgPQILAACwHoEFAABYj8ACAACsR2ABAADWI7AAAADrEVgAAID1CCwAAMB6BBYAAGA9AgsAALAegQUAAFiPwAIAAKxHYAEAANYjsAAAAOsRWAAAgPUILAAAwHoEFgAAYL2gAktOTo4GDhyoqKgoxcbGKiMjQ7t37z7nOrm5uXI4HAFTeHh4QI0xRjNnzlRCQoIiIiKUlpamPXv2BN8NAAAISUEFlsLCQmVlZWnz5s1at26dTpw4oWHDhsnn851zvejoaJWVlfmnL7/8MmD5nDlz9MILL2j+/PnasmWLIiMjlZ6ermPHjgXfEQAACDmtgyles2ZNwP3c3FzFxsaquLhY119//VnXczgcio+Pr3WZMUbPPfecHn30UY0ePVqStHjxYsXFxWnFihUaO3ZsMEMEAAAh6ILOYfF4PJKkmJiYc9ZVVlaqS5cuSkpK0ujRo7Vz507/stLSUrndbqWlpfnnuVwupaSkqKioqNbtVVVVyev1BkwAACB01TuwVFdXa+rUqRoyZIh69ep11roePXpo4cKFWrlypV577TVVV1dr8ODBOnjwoCTJ7XZLkuLi4gLWi4uL8y/7sZycHLlcLv+UlJRU3zYAAEALUO/AkpWVpR07digvL++cdampqcrMzFS/fv10ww036K233lLHjh314osv1vehlZ2dLY/H458OHDhQ720BAAD7BXUOyxlTpkzRqlWrtHHjRnXq1Cmoddu0aaP+/ftr7969kuQ/t6W8vFwJCQn+uvLycvXr16/WbTidTjmdzvoMHQAAtEBBHWExxmjKlClavny51q9fr+Tk5KAf8NSpU/rkk0/84SQ5OVnx8fHKz8/313i9Xm3ZskWpqalBbx8AAISeoI6wZGVlacmSJVq5cqWioqL855i4XC5FRERIkjIzM3XppZcqJydHkvSHP/xB11xzjbp166aKigo99dRT+vLLLzVp0iRJp79BNHXqVD3++OPq3r27kpOTNWPGDCUmJiojI6MBWwUAAC1VUIFl3rx5kqShQ4cGzF+0aJEmTJggSdq/f79atfr7gZu//e1vuuuuu+R2u9WhQwcNGDBAH374oX72s5/5ax588EH5fD7dfffdqqio0LXXXqs1a9bUuMAcAAD4aXIYY0xzD+JCeb1euVwueTweRUdHN/dwADQQn09q1+707cpKKTKyeccDoGEF8/7NbwkBAADrEVgAAID1CCwAAMB6BBYAAGA9AgsAALAegQUAAFiPwAIAAKxHYAEAANYjsAAAAOsRWAAAgPUILAAAwHoEFgAAYD0CCwAAsB6BBQAAWI/AAgAArEdgAQAA1iOwAAAA6xFYAACA9QgsAADAegQWAABgPQILAACwHoEFAABYj8ACAACsR2ABAADWI7AAAADrEVgAAID1CCwAAMB6BBYAAGA9AgsAALAegQUAAFiPwAIAAKwXVGDJycnRwIEDFRUVpdjYWGVkZGj37t3nXOfll1/Wddddpw4dOqhDhw5KS0vT1q1bA2omTJggh8MRMA0fPjz4bgAAQEgKKrAUFhYqKytLmzdv1rp163TixAkNGzZMPp/vrOsUFBRo3Lhx2rBhg4qKipSUlKRhw4bpq6++CqgbPny4ysrK/NPSpUvr1xEAAAg5DmOMqe/K33zzjWJjY1VYWKjrr7++TuucOnVKHTp00J/+9CdlZmZKOn2EpaKiQitWrKjXOLxer1wulzwej6Kjo+u1DQD28fmkdu1O366slCIjm3c8ABpWMO/fF3QOi8fjkSTFxMTUeZ2jR4/qxIkTNdYpKChQbGysevToocmTJ+vw4cNn3UZVVZW8Xm/ABAAAQle9A0t1dbWmTp2qIUOGqFevXnVe76GHHlJiYqLS0tL884YPH67FixcrPz9fTz75pAoLCzVixAidOnWq1m3k5OTI5XL5p6SkpPq2AQAAWoB6fyQ0efJkvfPOO9q0aZM6depUp3Vmz56tOXPmqKCgQH369Dlr3eeff67LL79c7733nm666aYay6uqqlRVVeW/7/V6lZSUxEdCQIjhIyEgtDX6R0JTpkzRqlWrtGHDhjqHlaefflqzZ8/Wu+++e86wIkmXXXaZLrnkEu3du7fW5U6nU9HR0QETAAAIXa2DKTbG6L777tPy5ctVUFCg5OTkOq03Z84c/cd//IfWrl2rq6+++rz1Bw8e1OHDh5WQkBDM8AAAQIgK6ghLVlaWXnvtNS1ZskRRUVFyu91yu936/vvv/TWZmZnKzs7233/yySc1Y8YMLVy4UF27dvWvU1lZKUmqrKzU7373O23evFlffPGF8vPzNXr0aHXr1k3p6ekN1CYAAGjJggos8+bNk8fj0dChQ5WQkOCfXn/9dX/N/v37VVZWFrDO8ePH9U//9E8B6zz99NOSpLCwMH388ce65ZZbdMUVV2jixIkaMGCA3n//fTmdzgZqEwAAtGQXdB0WW3AdFiA0cdItENqa7DosAAAATYHAAgAArEdgAQAA1iOwAAAA6xFYAACA9QgsAADAegQWAABgPQILAACwHoEFAABYj8ACAACsR2ABAADWI7AAAADrEVgAAID1CCwAAMB6BBYAAGA9AgsAALAegQUAAFiPwAIAAKxHYAEAANYjsAAAAOsRWAAAgPUILAAAwHoEFgAAYD0CCwAAsB6BBQAAWI/AAgAArEdgAQAA1iOwAAAA6xFYAACA9QgsAADAegQWAABgvaACS05OjgYOHKioqCjFxsYqIyNDu3fvPu96y5YtU8+ePRUeHq7evXtr9erVAcuNMZo5c6YSEhIUERGhtLQ07dmzJ7hOAABAyAoqsBQWFiorK0ubN2/WunXrdOLECQ0bNkw+n++s63z44YcaN26cJk6cqO3btysjI0MZGRnasWOHv2bOnDl64YUXNH/+fG3ZskWRkZFKT0/XsWPH6t8ZAAAIGQ5jjKnvyt98841iY2NVWFio66+/vtaaMWPGyOfzadWqVf5511xzjfr166f58+fLGKPExEQ98MADmj59uiTJ4/EoLi5Oubm5Gjt27HnH4fV65XK55PF4FB0dXd92AFjG55PatTt9u7JSioxs3vEAaFjBvH9f0DksHo9HkhQTE3PWmqKiIqWlpQXMS09PV1FRkSSptLRUbrc7oMblciklJcVf82NVVVXyer0BEwAACF31DizV1dWaOnWqhgwZol69ep21zu12Ky4uLmBeXFyc3G63f/mZeWer+bGcnBy5XC7/lJSUVN82AABAC1DvwJKVlaUdO3YoLy+vIcdTJ9nZ2fJ4PP7pwIEDTT4GAADQdFrXZ6UpU6Zo1apV2rhxozp16nTO2vj4eJWXlwfMKy8vV3x8vH/5mXkJCQkBNf369at1m06nU06nsz5DBwAALVBQR1iMMZoyZYqWL1+u9evXKzk5+bzrpKamKj8/P2DeunXrlJqaKklKTk5WfHx8QI3X69WWLVv8NQAA4KctqCMsWVlZWrJkiVauXKmoqCj/OSYul0sRERGSpMzMTF166aXKycmRJN1///264YYb9Mc//lEjR45UXl6etm3bppdeekmS5HA4NHXqVD3++OPq3r27kpOTNWPGDCUmJiojI6MBWwUAAC1VUIFl3rx5kqShQ4cGzF+0aJEmTJggSdq/f79atfr7gZvBgwdryZIlevTRR/XII4+oe/fuWrFiRcCJug8++KB8Pp/uvvtuVVRU6Nprr9WaNWsUHh5ez7YAAEAouaDrsNiC67AAoYnrsAChrcmuwwIAANAUCCwAAMB6BBYAAGA9AgsAALAegQUAAFiPwAIAAKxHYAEAANYjsAAAAOsRWAAAgPUILAAAwHoEFgAAYD0CCwAAsB6BBQAAWI/AAgAArEdgAQAA1iOwAAAA6xFYAACA9QgsAADAegQWAABgPQILAACwHoEFAABYj8ACAACsR2ABAADWI7AAAADrEVgAAID1CCwAAMB6BBYAAGA9AgsAALAegQUAAFiPwAIAAKxHYAEAANYLOrBs3LhRo0aNUmJiohwOh1asWHHO+gkTJsjhcNSYrrrqKn/N73//+xrLe/bsGXQzAAAgNAUdWHw+n/r27au5c+fWqf75559XWVmZfzpw4IBiYmJ06623BtRdddVVAXWbNm0KdmgAACBEtQ52hREjRmjEiBF1rne5XHK5XP77K1as0N/+9jfdeeedgQNp3Vrx8fHBDgcAAPwENPk5LAsWLFBaWpq6dOkSMH/Pnj1KTEzUZZddpttvv1379+8/6zaqqqrk9XoDJgAAELqaNLAcOnRI77zzjiZNmhQwPyUlRbm5uVqzZo3mzZun0tJSXXfddTpy5Eit28nJyfEfuXG5XEpKSmqK4QMAgGbSpIHl1VdfVfv27ZWRkREwf8SIEbr11lvVp08fpaena/Xq1aqoqNAbb7xR63ays7Pl8Xj804EDB5pg9AAAoLkEfQ5LfRljtHDhQt1xxx1q27btOWvbt2+vK664Qnv37q11udPplNPpbIxhAgAACzXZEZbCwkLt3btXEydOPG9tZWWl9u3bp4SEhCYYGQAAsF3QgaWyslIlJSUqKSmRJJWWlqqkpMR/kmx2drYyMzNrrLdgwQKlpKSoV69eNZZNnz5dhYWF+uKLL/Thhx/qV7/6lcLCwjRu3LhghwcAAEJQ0B8Jbdu2TTfeeKP//rRp0yRJ48ePV25ursrKymp8w8fj8ejNN9/U888/X+s2Dx48qHHjxunw4cPq2LGjrr32Wm3evFkdO3YMdngAACAEOYwxprkHcaG8Xq9cLpc8Ho+io6ObezgAGojPJ7Vrd/p2ZaUUGdm84wHQsIJ5/+a3hAAAgPUILAAAwHoEFgAAYD0CCwAAsB6BBQAAWI/AAgAArEdgAQAA1iOwAAAA6xFYAACA9QgsAADAegQWAABgPQILAACwHoEFAABYj8ACAACsR2ABAADWI7AAAADrEVgAAID1CCwAAMB6BBYAAGA9AgsAALAegQUAAFiPwAIAAKxHYAEAANYjsAAAAOsRWAAAgPUILAAAwHoEFgAAYD0CCwAAsB6BBQAAWI/AAgAArEdgAQAA1gs6sGzcuFGjRo1SYmKiHA6HVqxYcc76goICORyOGpPb7Q6omzt3rrp27arw8HClpKRo69atwQ4NAACEqKADi8/nU9++fTV37tyg1tu9e7fKysr8U2xsrH/Z66+/rmnTpmnWrFn66KOP1LdvX6Wnp+vrr78OdngAACAEtQ52hREjRmjEiBFBP1BsbKzat29f67JnnnlGd911l+68805J0vz58/X2229r4cKFevjhh4N+LAAAEFqa7ByWfv36KSEhQTfffLM++OAD//zjx4+ruLhYaWlpfx9Uq1ZKS0tTUVFRrduqqqqS1+sNmAAAQOhq9MCSkJCg+fPn680339Sbb76ppKQkDR06VB999JEk6dtvv9WpU6cUFxcXsF5cXFyN81zOyMnJkcvl8k9JSUmN3QYAAGhGQX8kFKwePXqoR48e/vuDBw/Wvn379Oyzz+ovf/lLvbaZnZ2tadOm+e97vV5CCwAAIazRA0ttBg0apE2bNkmSLrnkEoWFham8vDygpry8XPHx8bWu73Q65XQ6G32cAADADs1yHZaSkhIlJCRIktq2basBAwYoPz/fv7y6ulr5+flKTU1tjuEBAADLBH2EpbKyUnv37vXfLy0tVUlJiWJiYtS5c2dlZ2frq6++0uLFiyVJzz33nJKTk3XVVVfp2LFjeuWVV7R+/Xq9++67/m1MmzZN48eP19VXX61Bgwbpueeek8/n839rCAAA/LQFHVi2bdumG2+80X//zLkk48ePV25ursrKyrR//37/8uPHj+uBBx7QV199pYsuukh9+vTRe++9F7CNMWPG6JtvvtHMmTPldrvVr18/rVmzpsaJuAAA4KfJYYwxzT2IC+X1euVyueTxeBQdHd3cwwHQQHw+qV2707crK6XIyOYdD4CGFcz7N78lBAAArEdgAQAA1iOwAAAA6xFYAACA9QgsAADAegQWAABgPQILAACwHoEFAABYj8ACAACsR2ABAADWI7AAAADrEVgAAID1CCwAAMB6BBYAAGA9AgsAALAegQUAAFiPwAIAAKxHYAEAANYjsAAAAOsRWAAAgPUILAAAwHoEFgAAYD0CCwAAsB6BBQAAWI/AAgAArEdgAQAA1iOwAAAA6xFYAACA9QgsAADAegQWAABgPQILAACwXtCBZePGjRo1apQSExPlcDi0YsWKc9a/9dZbuvnmm9WxY0dFR0crNTVVa9euDaj5/e9/L4fDETD17Nkz2KEBAIAQFXRg8fl86tu3r+bOnVun+o0bN+rmm2/W6tWrVVxcrBtvvFGjRo3S9u3bA+quuuoqlZWV+adNmzYFOzQAABCiWge7wogRIzRixIg61z/33HMB95944gmtXLlS//M//6P+/fv/fSCtWys+Pj7Y4QAAgJ+AJj+Hpbq6WkeOHFFMTEzA/D179igxMVGXXXaZbr/9du3fv/+s26iqqpLX6w2YAABA6GrywPL000+rsrJSt912m39eSkqKcnNztWbNGs2bN0+lpaW67rrrdOTIkVq3kZOTI5fL5Z+SkpKaavgAAKAZOIwxpt4rOxxavny5MjIy6lS/ZMkS3XXXXVq5cqXS0tLOWldRUaEuXbromWee0cSJE2ssr6qqUlVVlf++1+tVUlKSPB6PoqOjg+4DgJ18Pqldu9O3KyulyMjmHQ+AhuX1euVyuer0/h30OSz1lZeXp0mTJmnZsmXnDCuS1L59e11xxRXau3dvrcudTqecTmdjDBMAAFioST4SWrp0qe68804tXbpUI0eOPG99ZWWl9u3bp4SEhCYYHQAAsF3QR1gqKysDjnyUlpaqpKREMTEx6ty5s7Kzs/XVV19p8eLFkk5/DDR+/Hg9//zzSklJkdvtliRFRETI5XJJkqZPn65Ro0apS5cuOnTokGbNmqWwsDCNGzeuIXoEAAAtXNBHWLZt26b+/fv7v5I8bdo09e/fXzNnzpQklZWVBXzD56WXXtLJkyeVlZWlhIQE/3T//ff7aw4ePKhx48apR48euu2223TxxRdr8+bN6tix44X2BwAAQsAFnXRri2BO2gHQcnDSLRDagnn/5reEAACA9QgsAADAegQWAABgPQILAACwHoEFAABYj8ACAACsR2ABAADWI7AAAADrEVgAAID1CCwAAMB6BBYAAGA9AgsAALAegQUAAFiPwAIAAKxHYAEAANYjsAAAAOsRWAAAgPUILAAAwHoEFgAAYD0CCwAAsB6BBQAAWI/AAgAArEdgAQAA1iOwAAAA6xFYAACA9QgsAADAegQWAABgPQILAACwHoEFAABYj8ACAACsR2ABAADWCzqwbNy4UaNGjVJiYqIcDodWrFhx3nUKCgr085//XE6nU926dVNubm6Nmrlz56pr164KDw9XSkqKtm7dGuzQAABAiAo6sPh8PvXt21dz586tU31paalGjhypG2+8USUlJZo6daomTZqktWvX+mtef/11TZs2TbNmzdJHH32kvn37Kj09XV9//XWwwwMAACHIYYwx9V7Z4dDy5cuVkZFx1pqHHnpIb7/9tnbs2OGfN3bsWFVUVGjNmjWSpJSUFA0cOFB/+tOfJEnV1dVKSkrSfffdp4cffvi84/B6vXK5XPJ4PIqOjq5vOwAs4/NJ7dqdvl1ZKUVGNu94ADSsYN6/G/0clqKiIqWlpQXMS09PV1FRkSTp+PHjKi4uDqhp1aqV0tLS/DU/VlVVJa/XGzABAIDQ1eiBxe12Ky4uLmBeXFycvF6vvv/+e3377bc6depUrTVut7vWbebk5MjlcvmnpKSkRhs/AABofi3yW0LZ2dnyeDz+6cCBA809JACN4KKLTn8UVFl5+jaAn67Wjf0A8fHxKi8vD5hXXl6u6OhoRUREKCwsTGFhYbXWxMfH17pNp9Mpp9PZaGMGYAeHg/NWAJzW6EdYUlNTlZ+fHzBv3bp1Sk1NlSS1bdtWAwYMCKiprq5Wfn6+vwYAAPy0BR1YKisrVVJSopKSEkmnv7ZcUlKi/fv3Szr9cU1mZqa//t5779Xnn3+uBx98UJ999pn+/Oc/64033tBvf/tbf820adP08ssv69VXX9Wnn36qyZMny+fz6c4777zA9gAAQCgI+iOhbdu26cYbb/TfnzZtmiRp/Pjxys3NVVlZmT+8SFJycrLefvtt/fa3v9Xzzz+vTp066ZVXXlF6erq/ZsyYMfrmm280c+ZMud1u9evXT2vWrKlxIi4AAPhpuqDrsNiC67AAANDyWHUdFgAAgAtFYAEAANYjsAAAAOsRWAAAgPUILAAAwHoEFgAAYD0CCwAAsB6BBQAAWI/AAgAArNfov9bcFM5crNfr9TbzSAAAQF2ded+uy0X3QyKwHDlyRJKUlJTUzCMBAADBOnLkiFwu1zlrQuK3hKqrq3Xo0CFFRUXJ4XA06La9Xq+SkpJ04MCBkPydolDvTwr9Humv5Qv1HkO9Pyn0e2ys/owxOnLkiBITE9Wq1bnPUgmJIyytWrVSp06dGvUxoqOjQ/JJeEao9yeFfo/01/KFeo+h3p8U+j02Rn/nO7JyBifdAgAA6xFYAACA9Qgs5+F0OjVr1iw5nc7mHkqjCPX+pNDvkf5avlDvMdT7k0K/Rxv6C4mTbgEAQGjjCAsAALAegQUAAFiPwAIAAKxHYAEAANYL6cCyceNGjRo1SomJiXI4HFqxYsV515k7d66uvPJKRUREqEePHlq8eHGNmmXLlqlnz54KDw9X7969tXr16oDlxhjNnDlTCQkJioiIUFpamvbs2dNQbfk1Rn8vv/yyrrvuOnXo0EEdOnRQWlqatm7dGlAzYcIEORyOgGn48OEN2ZqkxukvNze3xtjDw8MDappq/0mN0+PQoUNr9OhwODRy5Eh/TVPtw5ycHA0cOFBRUVGKjY1VRkaGdu/efd71GuI19t133+n2229XdHS02rdvr4kTJ6qystL6/k6cOKGHHnpIvXv3VmRkpBITE5WZmalDhw4FbKNr16419uHs2bMbtL/G6lGq23Owpe5DSbW+Bh0Oh5566il/TVPsw/r0t3PnTv3617/2j++5556rtW7u3Lnq2rWrwsPDlZKSUuO94tixY8rKytLFF1+sdu3a6de//rXKy8vr34wJYatXrzb/9m//Zt566y0jySxfvvyc9X/+859NVFSUycvLM/v27TNLly417dq1M//93//tr/nggw9MWFiYmTNnjtm1a5d59NFHTZs2bcwnn3zir5k9e7ZxuVxmxYoV5n//93/NLbfcYpKTk833339vfX///M//bObOnWu2b99uPv30UzNhwgTjcrnMwYMH/TXjx483w4cPN2VlZf7pu+++a9DeGqu/RYsWmejo6ICxu93ugO001f5rrB4PHz4c0N+OHTtMWFiYWbRokb+mqfZhenq6WbRokdmxY4cpKSkxv/zlL03nzp1NZWXlWddpqNfY8OHDTd++fc3mzZvN+++/b7p162bGjRtnfX8VFRUmLS3NvP766+azzz4zRUVFZtCgQWbAgAEB2+nSpYv5wx/+ELAPz/W4NvVoTN2egy11HxpjAvoqKyszCxcuNA6Hw+zbt89f0xT7sD79bd261UyfPt0sXbrUxMfHm2effbZGTV5enmnbtq1ZuHCh2blzp7nrrrtM+/btTXl5ub/m3nvvNUlJSSY/P99s27bNXHPNNWbw4MH17iWkA8sP1eXNIDU11UyfPj1g3rRp08yQIUP892+77TYzcuTIgJqUlBRzzz33GGOMqa6uNvHx8eapp57yL6+oqDBOp9MsXbr0Ars4u4bq78dOnjxpoqKizKuvvuqfN378eDN69OgLGW7QGqq/RYsWGZfLddZtNNf+M6bx9uGzzz5roqKiAv5ANcc+NMaYr7/+2kgyhYWFZ61piNfYrl27jCTz17/+1V/zzjvvGIfDYb766quGbClAQ/RXm61btxpJ5ssvv/TP69KlS61vJI2toXo833Mw1Pbh6NGjzS9+8YuAec2xD+vS3w+dbYyDBg0yWVlZ/vunTp0yiYmJJicnxxhz+jXZpk0bs2zZMn/Np59+aiSZoqKieo09pD8SClZVVVWNjwciIiK0detWnThxQpJUVFSktLS0gJr09HQVFRVJkkpLS+V2uwNqXC6XUlJS/DXNpS79/djRo0d14sQJxcTEBMwvKChQbGysevToocmTJ+vw4cONNu66qmt/lZWV6tKli5KSkjR69Gjt3LnTv8zm/SfVbx8uWLBAY8eOVWRkZMD85tiHHo9Hkmo8n36oIV5jRUVFat++va6++mp/TVpamlq1aqUtW7Y0WD8/1hD9nW27DodD7du3D5g/e/ZsXXzxxerfv7+eeuopnTx5sv6Dr6OG7PFcz8FQ2ofl5eV6++23NXHixBrLmnof1qW/8zl+/LiKi4sD/g1atWqltLQ0/79BcXGxTpw4EVDTs2dPde7cud5/SwksP5Cenq5XXnlFxcXFMsZo27ZteuWVV3TixAl9++23kiS32624uLiA9eLi4uR2u/3Lz8w7W01zqUt/P/bQQw8pMTEx4Ek3fPhwLV68WPn5+XryySdVWFioESNG6NSpU03VSq3q0l+PHj20cOFCrVy5Uq+99pqqq6s1ePBgHTx4UJLd+08Kfh9u3bpVO3bs0KRJkwLmN8c+rK6u1tSpUzVkyBD16tXrrHUN8Rpzu92KjY0NWN66dWvFxMQ02n5sqP5+7NixY3rooYc0bty4gB+d+9d//Vfl5eVpw4YNuueee/TEE0/owQcfbJhmzqIhezzfczCU9uGrr76qqKgo/eM//mPA/Kbeh3Xt73y+/fZbnTp16ryvwbZt29YI2RfytzQkfq25ocyYMUNut1vXXHONjDGKi4vT+PHjNWfOnPP+7HVLEGx/s2fPVl5engoKCgL+Vz927Fj/7d69e6tPnz66/PLLVVBQoJtuuqlJeqlNXfpLTU1Vamqqf53Bgwfryiuv1IsvvqjHHnusuYZeZ8HuwwULFqh3794aNGhQwPzm2IdZWVnasWOHNm3a1Cjbb26N0d+JEyd02223yRijefPmBSybNm2a/3afPn3Utm1b3XPPPcrJyWm0y6c3ZI82/h1prOfowoULdfvtt9c4OtrU+7ClvwZb/rtwA4qIiNDChQt19OhRffHFF9q/f7+6du2qqKgodezYUZIUHx9f4yzn8vJyxcfH+5efmXe2muZSl/7OePrppzV79my9++676tOnzzm3e9lll+mSSy7R3r17G3P45xVMf2e0adNG/fv394/d5v0nBdejz+dTXl5erYehf6yx9+GUKVO0atUqbdiwQZ06dTpnbUO8xuLj4/X1118HLD958qS+++67RtmPDdnfGWfCypdffql169YFHF2pTUpKik6ePKkvvviiXj2cT2P0+EM/fg6Gwj6UpPfff1+7d++ucZSzNo25D4Pp73wuueQShYWFnfc1ePz4cVVUVJy1JlgEllq0adNGnTp1UlhYmPLy8vQP//APAf9Dz8/PD6hft26d/3/tycnJio+PD6jxer3asmVLwP/sm9O5+pOkOXPm6LHHHtOaNWsCPj8+m4MHD+rw4cNKSEhozGHX2fn6+6FTp07pk08+8Y+9Jew/qW49Llu2TFVVVfrNb35z3u011j40xmjKlClavny51q9fr+Tk5POu0xCvsdTUVFVUVKi4uNhfs379elVXVyslJaUhWpPUOP1Jfw8re/bs0XvvvaeLL774vNstKSlRq1atanyMcqEaq8cf+/FzsKXvwzMWLFigAQMGqG/fvufdbmPsw/r0dz5t27bVgAEDAv4NqqurlZ+f7/83GDBggNq0aRNQs3v3bu3fv7/+f0vrdapuC3HkyBGzfft2s337diPJPPPMM2b79u3+M+0ffvhhc8cdd/jrd+/ebf7yl7+Y//u//zNbtmwxY8aMMTExMaa0tNRf88EHH5jWrVubp59+2nz66adm1qxZtX7lsn379mblypXm448/NqNHj26Ur8U2Rn+zZ882bdu2Nf/1X/8V8FW7I0eO+B9z+vTppqioyJSWlpr33nvP/PznPzfdu3c3x44ds76/f//3fzdr1641+/btM8XFxWbs2LEmPDzc7Ny5M+DfoCn2X2P1eMa1115rxowZU+tjNtU+nDx5snG5XKagoCDg+XT06FF/zR133GEefvhh//2Geo0NHz7c9O/f32zZssVs2rTJdO/evcG/EtsY/R0/ftzccsstplOnTqakpCRgu1VVVcYYYz788EPz7LPPmpKSErNv3z7z2muvmY4dO5rMzMwG7a+xeqzrc7Cl7sMzPB6Pueiii8y8efNqPG5T7cP69FdVVeX/u5SQkGCmT59utm/fbvbs2eOvycvLM06n0+Tm5ppdu3aZu+++27Rv3z7gMhH33nuv6dy5s1m/fr3Ztm2bSU1NNampqfXuJaQDy4YNG4ykGtP48eONMae/VnfDDTf463ft2mX69etnIiIiTHR0tBk9erT57LPPamz3jTfeMFdccYVp27atueqqq8zbb78dsLy6utrMmDHDxMXFGafTaW666Saze/fuFtFfly5dat3mrFmzjDHGHD161AwbNsx07NjRtGnTxnTp0sXcddddNa5lYmt/U6dONZ07dzZt27Y1cXFx5pe//KX56KOPAmqaav81Vo/GGPPZZ58ZSebdd9+tsawp92FtvUkKuCbMDTfc4O/3jIZ4jR0+fNiMGzfOtGvXzkRHR5s777zTH7xt7q+0tPSs292wYYMxxpji4mKTkpJiXC6XCQ8PN1deeaV54oknGjxwNlaPdX0OttR9eMaLL75oIiIiTEVFRY1lTbUP69Pf2Z6DP/xbZIwx//mf/+n/ezpo0CCzefPmgOXff/+9+Zd/+RfToUMHc9FFF5lf/epXpqysrN69OP5/QwAAANbiHBYAAGA9AgsAALAegQUAAFiPwAIAAKxHYAEAANYjsAAAAOsRWAAAgPUILAAAwHoEFgAAYD0CCwAAsB6BBQAAWI/AAgAArPf/AHQlBelcujxTAAAAAElFTkSuQmCC", "text/plain": [ "
" ] @@ -127,7 +201,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 12, "id": "07738b78-0491-48e7-bf29-46599371b926", "metadata": {}, "outputs": [ @@ -137,7 +211,7 @@ "2" ] }, - "execution_count": 13, + "execution_count": 12, "metadata": {}, "output_type": "execute_result" } @@ -151,32 +225,33 @@ "execution_count": 18, "id": "73e9ee8c-4109-445e-999f-1275f155fdc3", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "1" - ] - }, - "execution_count": 18, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ - "x_test = np.array([[2]])\n", - "len(x_test)" + "# x_test = np.array([[2]])\n", + "# len(x_test)\n", + "# x_test.shape\n", + "# # *x_test.shape == 1" ] }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 14, "id": "5c55c689-70a7-4151-999f-32cc2079c4a0", "metadata": {}, + "outputs": [], + "source": [ + "# plot_intervals(x_test, y_i[2])" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "4336c600-e35a-4e5d-b387-2479f8449e95", + "metadata": {}, "outputs": [ { "data": { - "image/png": "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fydOnNBDDz2k3r17KzIyUomJicrMzNShQ4cCttG1a9ca+3D27NkN2l9j9SjV7TnYUvehpFpfgw6HQ0899ZS/pin2YX3627lzp37961/7x/fcc8/VWjd37lx17dpV4eHhSklJqfFecezYMWVlZeniiy9Wu3bt9Otf/1rl5eX1b8aEsNWrV5t/+7d/M2+99ZaRZJYvX37O+j//+c8mKirK5OXlmX379pmlS5eadu3amf/+7//213zwwQcmLCzMzJkzx+zatcs8+uijpk2bNuaTTz7x18yePdu4XC6zYsUK87//+7/mlltuMcnJyeb777+3vr9//ud/NnPnzjXbt283n376qZkwYYJxuVzm4MGD/prx48eb4cOHm7KyMv/03XffNWhvjdXfokWLTHR0dMDY3W53wHaaav81Vo+HDx8O6G/Hjh0mLCzMLFq0yF/TVPswPT3dLFq0yOzYscOUlJSYX/7yl6Zz586msrLyrOs01Gts+PDhpm/fvmbz5s3m/fffN926dTPjxo2zvr+KigqTlpZmXn/9dfPZZ5+ZoqIiM2jQIDNgwICA7XTp0sX84Q9/CNiH53pcm3o0pm7PwZa6D40xAX2VlZWZhQsXGofDYfbt2+evaYp9WJ/+tm7daqZPn26WLl1q4uPjzbPPPlujJi8vz7Rt29YsXLjQ7Ny509x1112mffv2pry83F9z7733mqSkJJOfn2+2bdtmrrnmGjN48OB69xLSgeWH6vJmkJqaaqZPnx4wb9q0aWbIkCH++7fddpsZOXJkQE1KSoq55557jDHGVFdXm/j4ePPUU0/5l1dUVBin02mWLl16gV2cXUP192MnT540UVFR5tVXX/XPGz9+vBk9evSFDDdoDdXfokWLjMvlOus2mmv/GdN4+/DZZ581UVFRAX+gmmMfGmPM119/bSSZwsLCs9Y0xGts165dRpL561//6q955513jMPhMF999VVDthSgIfqrzdatW40k8+WXX/rndenSpdY3ksbWUD2e7zkYavtw9OjR5he/+EXAvObYh3Xp74fONsZBgwaZrKws//1Tp06ZxMREk5OTY4w5/Zps06aNWbZsmb/m008/NZJMUVFRvcYe0h8JBauqqqrGxwMRERHaunWrTpw4IUkqKipSWlpaQE16erqKiookSaWlpXK73QE1LpdLKSkp/prmUpf+fuzo0aM6ceKE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", + "image/png": "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/QoGg/J4PBHbPR5Pt68/+3w+W+sHi54cq/Hjx+vZZ5/VP//5T61YsUKhUEhTpkzRf//731iMPKB097gKBAL65ptvDE3VP6Wmpmrp0qV69dVX9eqrr8rr9erSSy9VfX296dFiKhQK6a677tKFF16o9PT0btcN1eesH4r2WA3l56ytW7fqpJNOktPp1O23367Vq1drwoQJXa419ZgaEP+1F/1Pbm5uRFlPmTJF55xzjv7617/qoYceMjgZBrLx48dr/Pjx4a+nTJmizz77TE888YT+/ve/G5wstubMmaNt27bpvffeMz1KvxftsRrKz1njx49XQ0OD/H6/XnnlFRUXF+vdd9/tNkhMGLRnRkaNGqX4+Hi1tLREbG9paVFKSkqX+6SkpNhaP1j05Fj92PDhwzVx4kTt2rWrL0Yc0Lp7XCUmJuqEE04wNNXAkZ2dPaQeV3fccYfeeOMNvfPOOxo7duwx1w7V56wj7ByrHxtKz1kJCQk688wzlZWVpYqKCmVkZOjJJ5/scq2px9SgjZGEhARlZWWpuro6vC0UCqm6urrb18pyc3Mj1kvSW2+91e36waInx+rHgsGgtm7dqtTU1L4ac8Aaqo+r3tLQ0DAkHleWZemOO+7Q6tWrtWHDBo0bN+64+wzVx1ZPjtWPDeXnrFAopI6Oji6/Z+wx1advjzVs5cqVltPptJYvX259/PHH1m233WadfPLJls/nsyzLsm644QartLQ0vP7999+3hg0bZj322GPW9u3brfLycmv48OHW1q1bTf0KMWP3WC1YsMBav3699dlnn1l1dXXWddddZ7lcLuujjz4y9SvETFtbm7VlyxZry5YtliRr4cKF1pYtW6wvvvjCsizLKi0ttW644Ybw+t27d1snnnii9bvf/c7avn27VVlZacXHx1tVVVWmfoWYsXusnnjiCWvNmjXWp59+am3dutWaO3euFRcXZ7399tumfoWYmT17tuV2u62NGzdazc3N4dvXX38dXsNz1mE9OVZD9TmrtLTUevfdd63GxkbrP//5j1VaWmo5HA7rzTfftCyr/zymBnWMWJZl/eUvf7FOPfVUKyEhwcrOzrY+/PDD8PcuueQSq7i4OGL9Sy+9ZJ111llWQkKCde6551pr166N8cTm2DlWd911V3itx+Oxrr76aqu+vt7A1LF35OOnP74dOT7FxcXWJZdcctQ+mZmZVkJCgnX66adbzz33XMznNsHusXr00UetM844w3K5XFZSUpJ16aWXWhs2bDAzfIx1dZwkRTxWeM46rCfHaqg+Z910003WaaedZiUkJFinnHKKdfnll4dDxLL6z2PKYVmW1bfnXgAAALo3aN8zAgAABgZiBAAAGEWMAAAAo4gRAABgFDECAACMIkYAAIBRxAgAADCKGAEAAEYRIwAAwChiBAAAGEWMAAAAo4gRAABg1P8DuWcTxtU00uYAAAAASUVORK5CYII=", "text/plain": [ "
" ] @@ -186,13 +261,13 @@ } ], "source": [ - "plot_intervals(x_test, y_i[2])" + "plot_lower_bound(x, y_i)" ] }, { "cell_type": "code", "execution_count": null, - "id": "4336c600-e35a-4e5d-b387-2479f8449e95", + "id": "147f11e7-a859-449e-ac5d-3bcc2aefdbe8", "metadata": {}, "outputs": [], "source": [] From 5f9499a0d81aa942f5536dc224d3f3c2c3a3e420 Mon Sep 17 00:00:00 2001 From: leslieDLcy Date: Mon, 8 Apr 2024 09:16:00 +0100 Subject: [PATCH 06/11] change file names --- tests/calculator.ipynb | 131 ------------------ tests/{plotting.ipynb => test_plotting.ipynb} | 0 2 files changed, 131 deletions(-) delete mode 100644 tests/calculator.ipynb rename tests/{plotting.ipynb => test_plotting.ipynb} (100%) diff --git a/tests/calculator.ipynb b/tests/calculator.ipynb deleted file mode 100644 index 74a30e0..0000000 --- a/tests/calculator.ipynb +++ /dev/null @@ -1,131 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 1, - "id": "70aa6699-4f90-487e-be4a-3b9638cfc595", - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "50a9457f-56c6-4cb6-9b98-b0855fb9ac54", - "metadata": {}, - "outputs": [], - "source": [ - "a = np.array([[1, 2], [3, 4]])" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "e15e1fd0-ee8a-4f9c-9deb-3561b184d5ac", - "metadata": {}, - "outputs": [], - "source": [ - "b = np.array([[5, 6], [7, 8]])" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "ceee93f9-530b-4298-b6e2-445257d9417f", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([[ 5, 12],\n", - " [21, 32]])" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# \n", - "\n", - "a * b" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "67aa6025-28a8-4663-b3b0-2546b9b4abb2", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([[19, 22],\n", - " [43, 50]])" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "a @ b" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "0765a2a9-1c63-41d9-83a8-93d246f84cef", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "array([[19, 22],\n", - " [43, 50]])" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "np.matmul(a, b)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "fd42d615-865f-4e79-8190-9da9054ac956", - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "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.13" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/tests/plotting.ipynb b/tests/test_plotting.ipynb similarity index 100% rename from tests/plotting.ipynb rename to tests/test_plotting.ipynb From ff7b37f3ea8388866ff21d3bf014e71a38e05895 Mon Sep 17 00:00:00 2001 From: leslieDLcy Date: Mon, 8 Apr 2024 09:22:08 +0100 Subject: [PATCH 07/11] modify plotting --- intervals/plotting.py | 1 - 1 file changed, 1 deletion(-) diff --git a/intervals/plotting.py b/intervals/plotting.py index 28dae5b..507431c 100644 --- a/intervals/plotting.py +++ b/intervals/plotting.py @@ -1,7 +1,6 @@ from __future__ import annotations import numpy as np import matplotlib.pyplot as plt -from intervals.number import Interval """ -------------------------- From 39af4832ca3dfa43c5e4618c913c08fcc29797a3 Mon Sep 17 00:00:00 2001 From: leslieDLcy Date: Mon, 8 Apr 2024 09:38:31 +0100 Subject: [PATCH 08/11] add plotting --- intervals/plotting.py | 50 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/intervals/plotting.py b/intervals/plotting.py index ca4b39f..507431c 100644 --- a/intervals/plotting.py +++ b/intervals/plotting.py @@ -1,15 +1,53 @@ +from __future__ import annotations +import numpy as np +import matplotlib.pyplot as plt + """ -------------------------- -Created Feb 2022 -Marco De Angelis -github.com/marcodeangelis +Editted by Leslie Feb 2024 MIT License -------------------------- """ -from __future__ import annotations -import matplotlib.pyplot as pyplot +def plot_intervals(x, y_i, **kwargs): + """ plot intervals vertically + + args: + x: array-like precise values + x-axis coordinates + y_i: array-like Interval objects + array of intervals + """ + + fig, ax = plt.subplots() + + def basic_plot(x, y_i, **kwargs): + ax.plot([x, x], [y_i.hi, y_i.lo], 'blue', **kwargs) + if np.any(y_i.lo == y_i.hi): + sc_x = x[y_i.lo == y_i.hi] + sc_y = y_i[y_i.lo == y_i.hi].lo + ax.scatter(sc_x, sc_y, c='blue', **kwargs) + + if len(x.shape) > 1: + for xx, interval in zip(x, y_i): + basic_plot([xx, xx], [interval.hi, interval.lo]) + else: + basic_plot(x, y_i) + return ax + -from intervals.number import Interval +def plot_lower_bound(x, y_i, **kwargs): + """ plot lower bound of intervals + + args: + x: array-like + x-axis coordinates + y_i: array-like + array of intervals + """ + + fig, ax = plt.subplots() + ax.scatter(x, y_i.lo, label='lower bound', **kwargs) + ax.legend() From 0b71a5132071dd4508e397d8e8de1c6f75df6ae5 Mon Sep 17 00:00:00 2001 From: leslieDLcy Date: Wed, 10 Apr 2024 16:52:59 +0100 Subject: [PATCH 09/11] marco's new `matmul` suceeds --- intervals/mat_features.py | 2 +- intervals/methods.py | 186 +++- tests/matrix_multiplication_marco.ipynb | 1072 +++++++++++++++++++++++ 3 files changed, 1249 insertions(+), 11 deletions(-) create mode 100644 tests/matrix_multiplication_marco.ipynb diff --git a/intervals/mat_features.py b/intervals/mat_features.py index f6616c7..34424d1 100644 --- a/intervals/mat_features.py +++ b/intervals/mat_features.py @@ -18,7 +18,7 @@ def consume_interval(low, high): """ a_matrix = np.stack([low, high], axis=0) - return intervalise(a_matrix, index=0) + return intervalise(a_matrix) def create_interval(matrix, half_width=0.1): diff --git a/intervals/methods.py b/intervals/methods.py index 7f49a83..65d0af1 100644 --- a/intervals/methods.py +++ b/intervals/methods.py @@ -30,7 +30,7 @@ from itertools import product import numpy -from numpy import (ndarray,asarray,transpose,vstack,linspace,zeros,argmax) +from numpy import (ndarray,asarray,vstack,linspace,zeros,argmax) from intervals.number import (Interval, MACHINE_EPS) @@ -46,6 +46,7 @@ # numpy_cot = numpy.cotang numpy_pi = numpy.pi numpy_inf = numpy.Inf +numpy_transpose = numpy.transpose # Properties or maybe attributes of the interval class. These apply to all interval-like objects. @@ -485,7 +486,7 @@ def intersect_vector(x_:Interval,y_:Interval): # parser.py ##################################################################################### # Universal parser -def intervalise(x_: Any, index = -1) -> Union[Interval,Any]: +def intervalise(x_: Any, interval_index = -1) -> Union[Interval,Any]: """ This function casts an array-like structure into an Interval structure. All array-like structures will be first coerced into an ndarray of floats. @@ -500,7 +501,7 @@ def intervalise(x_: Any, index = -1) -> Union[Interval,Any]: (*) an ndarray of shape (2,3,7) will be cast as an Interval of shape (3,7). - (*) an ndarray of shape (2,3,7,2) will be cast as an Interval of shape (2,3,7). + (*) an ndarray of shape (2,3,7,2) will be cast as an Interval of shape (2,3,7) if interval_index is set to -1. If an ndarray has shape with multiple dimensions having size 2, then the last dimension is intervalised. So, an ndarray of shape (7,2,2) will be cast as an Interval of shape (7,2) with the last dimension intervalised. @@ -534,15 +535,18 @@ def treat_list(xx): if x_.__class__.__name__=='list': return treat_list(x_) # attempt to turn a n-list of intervals into a (n,...)-interval s = x.shape two=[si==2 for si in s] - if all(two): return Interval(lo=transpose(x)[0],hi=transpose(x)[1]) + # if all(two): return Interval(lo=numpy_transpose(x)[0],hi=numpy_transpose(x)[1]) + if all(two): return Interval(lo=x[...,0],hi=x[...,1]) elif any(two): - if two[-1]: return Interval(lo=transpose(x)[0],hi=transpose(x)[1]) # the last dimension has size 2 - elif two[0]: return Interval(lo=x[0],hi=x[1]) + # if two[-1]: return Interval(lo=numpy_transpose(x)[0],hi=numpy_transpose(x)[1]) # the last dimension has size 2 + if two[-1]: return Interval(lo=x[...,0],hi=x[...,1]) # last dimension has size 2 + elif two[0]: return Interval(lo=x[0],hi=x[1]) # first dimension has size 2 elif (two[-1]) & (two[0]): # this is the ambiguous case (2,3,5,2) - if index == 0: return Interval(lo=x[0],hi=x[1]) # first dimension gets intervalised - elif index == -1: return Interval(lo=transpose(x)[0],hi=transpose(x)[1]) + if interval_index == 0: return Interval(lo=x[0],hi=x[1]) # first dimension gets intervalised + # elif index == -1: return Interval(lo=numpy_transpose(x)[0],hi=numpy_transpose(x)[1]) + elif interval_index == -1: return Interval(lo=x[...,0],hi=x[...,1]) # if (sum(two)==1) & (two[0]): return Interval(lo=x[0],hi=x[1])# there is only one dimension of size 2 and is the first one - print('Array-like structure must have last dimension (or first) of size 2, for it to be coerced to Interval.') + print('Array-like structure must have the last (or first) dimension of size 2, for it to be coerced to Interval.') return Interval(lo=x) else: return Interval(lo=x) @@ -644,4 +648,166 @@ def bisect(x_:Interval,i:int=None): ##################################################################################### # Interval to bool methods, Unary. def is_Interval(x:Any) -> bool: return x.__class__.__name__ == 'Interval' -def is_not_Interval(x:Any) -> bool: return x.__class__.__name__ != 'Interval' \ No newline at end of file +def is_not_Interval(x:Any) -> bool: return x.__class__.__name__ != 'Interval' + +##################################################################################### +################################# neural_networks.py ################################ +##################################################################################### +def dot(x:Interval,y:Interval): return sum(x*y) +def rowcol_old(W,x): + ''' + (m,n) x (n,1) -> (m,1) + (m,n) x (n,p) -> (m,p) + (1,n) x (n,1) -> (1,1) + ''' + s = W.shape + x_shape = x.shape + if x_shape[0]==1: # x is row and must be either squeezed or transposed + x_ = x[0,:] + if x_shape[1]==1: # this is the correct shape + x_ = x[:,0] + if len(x_shape)==1: # x can be row or column (n,) + x_ = x + y=[] + for i in range(s[0]): + y.append(dot(W[i],x_)) + return intervalise(y) + +def rowcol_W_x(W,x): + ''' + Row by column multiplication between a matrix W and a column vector x. + + (m,n) x (n,1) -> (m,1) + (1,n) x (n,1) -> (1,1) + The following cases are also accepted even though mathematically impossible + (m,n) x (n,) -> (m,1) + (1,n) x (n,1) -> (1,1) + (1,n) x (1,n) -> (1,1) + ''' + m,n = W.shape + x_shape = x.shape + if not((n==x_shape[0]) | (n==x_shape[1])): + raise ValueError(f'Incompatible shapes ({m},{n}) x ({x_shape[0]},1) -> (?,?). Inner sizes must be same, {x_shape[1]} is different from {n}.') + if x_shape[0]==1: # x is row and must be either squeezed or transposed + x_ = x[0,:] + if x_shape[1]==1: # this is the correct shape + x_ = x[:,0] + if len(x_shape)==1: # x can be row or column (n,) + x_ = x + y=numpy.empty((m,2)) + for i in range(m): + inner_product = dot(W[i],x_) + y[i,0] = inner_product.lo + y[i,1] = inner_product.hi + ylo = numpy.expand_dims(y[...,0],axis=1) + yhi = numpy.expand_dims(y[...,1],axis=1) + return Interval(ylo,yhi) + +def rowcol_xT_WT(x,W): + ''' + Row by column multiplication between the row vector xT and the matrix transpose WT. + (1,n) x (n,m) -> (1,m) + (1,n) x (n,1) -> (1,1) + The following cases are also accepted even though mathematically impossible + (,n) x (n,m) -> (1,m) + (n,1) x (n,m) -> (1,1) + ''' + n,m = W.shape + x_shape = x.shape + if not((n==x_shape[0]) | (n==x_shape[1])): + raise ValueError(f'Incompatible shapes (1,{x_shape[1]}) x ({n},{m}) -> (?,?). Inner sizes must be same, {x_shape[1]} is different from {n}.') + if x_shape[0]==1: # this is the correct shape + x_ = x[0,:] + if x_shape[1]==1: # x is row and must be either squeezed or transposed + x_ = x[:,0] + if len(x_shape)==1: # x can be row or column (n,) + x_ = x + y=numpy.empty((m,2)) + for i in range(m): + inner_product = dot(x_,W[...,i]) + y[i,0] = inner_product.lo + y[i,1] = inner_product.hi + ylo = numpy.expand_dims(y[...,0],axis=0) + yhi = numpy.expand_dims(y[...,1],axis=0) + return Interval(ylo,yhi) + +def matmul(A,B): + ''' + (m,n) x (n,p) -> (m,p) + (1,n) x (n,1) -> (1,1) + ''' + m,na = A.shape + nb,p = B.shape + if na!=nb: raise ValueError(f'Incompatible shapes ({m},{na}) x ({nb},{p}) -> (?,?). Inner sizes must be same, {na} is different from {nb}.') + C = numpy.empty((m,p,2)) + for i in range(m): + for j in range(p): + inner_product = dot(A[i],B[...,j]) + C[i,j,0] = inner_product.lo + C[i,j,1] = inner_product.hi + return intervalise(C) + +def transpose(x:Interval): # not efficient it creates a new object in memory + ''' + Input an interval of shape (m,n) returns an interval of shape (n,m). + ''' + return Interval(x.val[...,0], x.val[...,1]) + +def squeeze(x:Interval): # not efficient it creates a new object in memory + return Interval(numpy.squeeze(x.lo),numpy.squeeze(x.hi)) + +################################ activation_functions.py ############################# + +def relu_nointerval(x:ndarray): + positive = x>0 + output = numpy.zeros(x.shape) + output[positive]=x[positive] + return output + +def relu_deriv(x:ndarray): + positive = x>0 + output = numpy.zeros(x.shape) + output[positive]=1 + return output + +def relu(x:Interval): + if is_not_Interval(x): return relu_nointerval(x) + case_1 = x.hi<0 + x_lo = x.val[...,0].T + x_hi = x.val[...,1].T + x_lo[case_1] = 0 + x_hi[case_1] = 0 + case_3 = (x_lo<0) & (numpy.logical_not(case_1)) + x_lo[case_3] = 0 + relu_x = Interval(lo=x_lo, hi=x_hi) + return relu_x + +def relu_deriv_interval(x:Interval): + if is_not_Interval(x): return relu_deriv(x) + x_lo = x.val[...,0].T + x_hi = x.val[...,1].T + case_1 = x_hi<0 + d_lo = numpy.zeros(x_lo.shape) + d_hi = numpy.ones(x_hi.shape) + d_hi[case_1] = 0 + # case_3 = (x_lo<0) & (np.logical_not(case_1)) + case_2 = x_lo>0 + d_lo[case_2] = 1 + d_relu_x = Interval(lo=d_lo, hi=d_hi) + return d_relu_x + +def sigmoid(x): return 1/(1+exp(-x)) +def sigmoid_deriv(x): return sigmoid(x)*(1-sigmoid(x)) + +# def tanh_(x): return np.tanh(x) +def tanh(x:Interval): return (exp(2*x)-1)/(exp(2*x)+1) +def tanh(x:Interval): + r = -1 + s = 1 + u = 1 + t = 1 + return s/u - (s*t/u**2 - r/u)/(t/u + exp(2*x)) +# def cot(x): return 1/np.tan(x) +# def tanh(x): return -(1/(cot(np.arctan(x)/2)**2)) +def cosh(x:Interval): return (1+exp(-2*x))/(2*exp(-x)) +def tanh_deriv(x:Interval): return (1/cosh(x))**2 \ No newline at end of file diff --git a/tests/matrix_multiplication_marco.ipynb b/tests/matrix_multiplication_marco.ipynb new file mode 100644 index 0000000..3f5b925 --- /dev/null +++ b/tests/matrix_multiplication_marco.ipynb @@ -0,0 +1,1072 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "bb67a0bf-f22e-4fde-9a2e-4c524333920c", + "metadata": { + "tags": [] + }, + "source": [ + "# interval matrix `calculation` test\n", + "\n", + "- test with simple 3 by 3 case\n", + "- current workflow will work as long as there is no shape as 2" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "f6e8b17c-ae64-4d94-9ed7-0628ebcc22dd", + "metadata": {}, + "outputs": [], + "source": [ + "from intervals.number import Interval as I\n", + "from intervals.methods import (lo,hi,mid,rad,width,intervalise, exp)\n", + "from intervals.random import uniform_endpoints \n", + "from intervals.mat_features import consume_interval, create_interval, dot, rowcol, rowcol2, intvl_matmul, consume_list" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "4f11a1ef-1a8e-4bd8-a9ae-a4e18cd94628", + "metadata": {}, + "outputs": [], + "source": [ + "from intervals.methods import *" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "7778e3c6-c484-49d6-ad56-7d8f4b1fc45a", + "metadata": {}, + "outputs": [], + "source": [ + "from intervals.activation import sigmoid, tanh" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "eb56342b-b2d3-4fd7-85e1-a45f64e12b44", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "95064f3d-8f26-403a-97f2-ffc944bd4e5f", + "metadata": {}, + "outputs": [], + "source": [ + "%load_ext autoreload\n", + "%autoreload 2" + ] + }, + { + "cell_type": "markdown", + "id": "bd29348b-91be-43b7-800b-741a918336b3", + "metadata": { + "tags": [] + }, + "source": [ + "#### mat @ mat" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "4d151557-6451-4e1e-8bf9-2d57c4d7950d", + "metadata": {}, + "outputs": [], + "source": [ + "a = np.arange(9).reshape(3,3)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "79da63ed-bd11-4117-8a7d-0826d873a200", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[0. 0.] [0.9 1.1] [1.8 2.2]\n", + "[2.7 3.3] [3.6 4.4] [4.5 5.5]\n", + "[5.4 6.6] [6.3 7.7] [7.2 8.8]" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "v1 = create_interval(matrix=a, half_width=0.1)\n", + "v1" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "aa4e3c4d-7163-4ad3-8f17-2ab8f5b8039e", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[12.15 18.15] [34.02 50.82] [55.89 83.49]\n", + "[14.58 21.78] [43.74 65.34] [ 72.9 108.9]\n", + "[17.01 25.41] [53.46 79.86] [ 89.91 134.31]" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "mat_mul_test = intvl_matmul(v1, v1)\n", + "mat_mul_test" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "ec6c2d24-ec3f-460f-9937-fb0f375b22a7", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[12.15 18.15] [14.58 21.78] [17.01 25.41]\n", + "[34.02 50.82] [43.74 65.34] [53.46 79.86]\n", + "[55.89 83.49] [ 72.9 108.9] [ 89.91 134.31]" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "''' double check with Marco's version '''\n", + "\n", + "matmul(v1, v1)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "c8760ce1-ae39-46d7-a44f-9df0cadebd72", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[ True, True, True],\n", + " [ True, True, True],\n", + " [ True, True, True]])" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "mat_mul_test == matmul(v1, v1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d9ea9be0-17f8-4e3a-8feb-f3fda24b2549", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "f5e18d79-62f4-462b-80ca-50b947a7fe84", + "metadata": { + "tags": [] + }, + "source": [ + "#### row @ mat" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "dadc30a0-8f0b-4cce-b3fa-f82cf86612cc", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(3,)\n" + ] + }, + { + "data": { + "text/plain": [ + "[0.9,1.1]\n", + "[2.7,3.3000000000000003]\n", + "[4.5,5.5]" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "vec = create_interval(matrix=np.array([1, 3, 5]))\n", + "print(vec.shape)\n", + "vec" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "bb37117e-7156-4273-8f68-c373dfb289fe", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(3,)" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "vec.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "dda27fcf-29cc-4454-926f-b2bd7bb70715", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[0.9,1.1]" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "vec[0]" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "f9ed7783-218a-4757-ad14-e9dd7a04c850", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "x shall be a 2 dimensional array\n", + "x shall be a 2 dimensional array\n", + "x shall be a 2 dimensional array\n" + ] + }, + { + "data": { + "text/plain": [ + "[nan,nan]\n", + "[nan,nan]\n", + "[nan,nan]" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "intvl_matmul(vec, v1)" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "68ae81db-9b26-4bbb-bc03-ef0f524cf659", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "x shall be a 2 dimensional array\n" + ] + } + ], + "source": [ + "rowcol2(vec, v1)" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "4eff5388-d7b3-4202-a34b-6dcc102a8ce9", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(1, 3)\n" + ] + }, + { + "data": { + "text/plain": [ + "[0.9 1.1] [2.7 3.3] [4.5 5.5]" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "row_vec = create_interval(matrix=np.array([[1, 3, 5]]))\n", + "print(row_vec.shape)\n", + "row_vec" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f5995b3c-6f73-4f13-b299-160d83ddcf7b", + "metadata": {}, + "outputs": [], + "source": [ + "# In theory, (1 by 3) @ (3 by 3) = (1, 3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9a2c2999-2a7d-4376-b0fd-70089a4f519c", + "metadata": {}, + "outputs": [], + "source": [ + "# what if we explicitly write down the row vector as (1 by 3)" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "f19a824e-afbf-44dc-9f4b-5ebe114a1419", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(3, 1)\n" + ] + }, + { + "data": { + "text/plain": [ + "[31.59 47.19]\n", + "[38.88 58.08]\n", + "[46.17 68.97]" + ] + }, + "execution_count": 22, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "tt = intvl_matmul(row_vec, v1)\n", + "print(tt.shape)\n", + "tt" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bf7c771f-e297-46b5-8af8-71ba14ed430b", + "metadata": {}, + "outputs": [], + "source": [ + "def reshape(interval):\n", + " length = len(interval)\n", + " new = I(lo=np.squeeze(interval.lo), hi=np.squeeze(interval.hi))\n", + " return new[np.newaxis, :]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5dfbe597-4ba6-4669-a6f1-8b4d3400c0a1", + "metadata": {}, + "outputs": [], + "source": [ + "new_rowmat_test = reshape(tt)\n", + "print(new_rowmat_test.shape)\n", + "new" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "1c9c2e95-a4a3-4041-a828-524bfba0305b", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[31.59 47.19] [38.88 58.08] [46.17 68.97]" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "''' double check with Marco's version '''\n", + "\n", + "rowcol_xT_WT(row_vec, v1)" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "93d79e7e-57be-454b-97f1-96c708454bd9", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[31.59 47.19] [38.88 58.08] [46.17 68.97]" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "matmul(row_vec, v1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "3c759931-61dd-4462-ace9-7c1c5ac8bf9b", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "896f6f13-ac6b-4db1-9e35-c041226abeab", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "70d232da-a898-449b-aa13-b6696272d2c2", + "metadata": { + "tags": [] + }, + "source": [ + "#### mat @ col_vec" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "6db7d27c-3493-45af-bf03-6fd3ac53bfe8", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[0. 0.] [0.9 1.1] [1.8 2.2]\n", + "[2.7 3.3] [3.6 4.4] [4.5 5.5]\n", + "[5.4 6.6] [6.3 7.7] [7.2 8.8]" + ] + }, + "execution_count": 25, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# given a matrix\n", + "v1" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "eb667504-afbb-4be1-886e-d757f0535d6c", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[10.53,15.730000000000002]\n", + "[32.4,48.400000000000006]\n", + "[54.269999999999996,81.07000000000002]" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "intvl_matmul(v1, vec)" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "2e8f7dfa-338d-4c1c-8401-1d98ef4d1427", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(3, 1)" + ] + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "vec = create_interval(matrix=np.array([1, 3, 5]))\n", + "vec.shape\n", + "\n", + "col_vec = vec[:, np.newaxis]\n", + "col_vec.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 36, + "id": "9876da08-d5b1-401a-9d58-89d6054d9f44", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[10.53,15.730000000000002]\n", + "[32.4,48.400000000000006]\n", + "[54.269999999999996,81.07000000000002]" + ] + }, + "execution_count": 36, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "intvl_matmul(v1, col_vec)" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "77879741-133a-4ef2-94bd-d0d75650aea3", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "\" test with marco's old code, which has been updated I guess \"" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "''' test with marco's old code, which has been updated I guess '''\n", + "\n", + "# # therefore, marco's rowvec works when the latter vec is just a vector\n", + "\n", + "# test_marco = rowcol2(v1, vec)\n", + "# print(test_marco.shape)\n", + "# test_marco\n", + "\n", + "# # what if we explicitly express a col vector\n", + "\n", + "# col_vec = col_vec[:, np.newaxis]\n", + "# print(col_vec.shape)\n", + "# col_vec\n", + "\n", + "# intvl_matmul(v1, col_vec)" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "id": "c835a252-6aed-43fb-91a2-3fe62307ed12", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[10.53 15.73]\n", + "[32.4 48.4]\n", + "[54.27 81.07]\n", + "test the universal \"matmul\" function:\n", + "[10.53 15.73]\n", + "[32.4 48.4]\n", + "[54.27 81.07]\n" + ] + } + ], + "source": [ + "''' test with marco's new code '''\n", + "\n", + "print(rowcol_W_x(v1, col_vec))\n", + "\n", + "print('test the universal \"matmul\" function:')\n", + "print(matmul(v1, col_vec))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "55846437-7298-43c7-92f9-a49d85da66a8", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6fe6ff32-de12-45ee-95f4-95a8b4d27385", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cff4877d-0a67-4e0a-9804-911231fba552", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a8b747e4-4f00-46a4-a527-ac17234d9b79", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "63eb993c-1d64-4fe0-851f-6fc3cc90d31f", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "ea3e169a-88cf-4645-b613-fc513f686bd1", + "metadata": { + "tags": [] + }, + "source": [ + "#### vector @ matrix" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "67ede585-d4b3-4979-b111-8c191117a226", + "metadata": {}, + "outputs": [], + "source": [ + "# create a row vector \n", + "\n", + "row_vec = create_interval(matrix=np.array([1, 3, 5]))\n", + "print(row_vec.shape)\n", + "row_vec" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f75a5aaf-9013-4951-bb84-88a09d50b270", + "metadata": {}, + "outputs": [], + "source": [ + "# sigmoid(row_vec)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0631a1bf-dd74-4b0e-88df-a102c073c9eb", + "metadata": {}, + "outputs": [], + "source": [ + "# sigmoid(v1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9e8d317c-7655-40eb-9f38-407d6310b66f", + "metadata": {}, + "outputs": [], + "source": [ + "# ''' add one more dimension succeeded '''\n", + "\n", + "# added_dim = row_vec[np.newaxis,:]\n", + "# print(added_dim.shape)\n", + "# added_dim" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9a58174a-49e1-48f6-af8c-2bc8efb98259", + "metadata": {}, + "outputs": [], + "source": [ + "''' lower dimension failed '''\n", + "\n", + "# np.ravel(added_dim)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f8f0f97d-86b1-416c-866c-1c5c2cbeb445", + "metadata": {}, + "outputs": [], + "source": [ + "# matrix which is v1\n", + "'''\n", + "(3, ) @ (3,3)\n", + "\n", + "'''\n", + "\n", + "result = rowcol2(x=row_vec, W=v1)\n", + "result" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5863a47b-c797-473b-8be0-1aa806af23b8", + "metadata": {}, + "outputs": [], + "source": [ + "result.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e8c73ff7-1ade-47d1-b7be-7bcffc17569f", + "metadata": {}, + "outputs": [], + "source": [ + "result_ = intvl_matmul(x=row_vec, W=v1)\n", + "type(result_)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8d928b16-c5c8-4131-9e0d-deedd67484ba", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "5668b7ad-298b-486a-a034-c98515a5c4b9", + "metadata": { + "jp-MarkdownHeadingCollapsed": true, + "tags": [] + }, + "source": [ + "#### scaler @ vector" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c065ed91-870d-4bce-82fa-781036536cc1", + "metadata": {}, + "outputs": [], + "source": [ + "# scalar\n", + "x = 3\n", + "x_intvl = create_interval(matrix=x)\n", + "x_intvl" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "57d11069-0ecf-4266-8798-6b5e4e71923b", + "metadata": {}, + "outputs": [], + "source": [ + "# a vector\n", + "W1 = np.array([[1, 3, 5]])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f3643fdb-387d-40dc-a1c6-6e8ee738a3ac", + "metadata": {}, + "outputs": [], + "source": [ + "W1_intvl = create_interval(matrix=W1)\n", + "W1_intvl" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b8ddeda1-0d4c-4994-aef8-89c677a7f009", + "metadata": {}, + "outputs": [], + "source": [ + "W1_intvl.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ea3b0076-545a-4014-a01c-a7b00bdfad00", + "metadata": {}, + "outputs": [], + "source": [ + "''' \n", + "(3, ) @ (1, 3)\n", + "'''\n", + "\n", + "h1 = x_intvl * W1_intvl\n", + "h1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c5b06fc9-177b-4c6f-a03f-cf78b506e4a7", + "metadata": {}, + "outputs": [], + "source": [ + "h1.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "2c8056b0-c95e-4048-b6b9-b1fc54dd7e83", + "metadata": {}, + "outputs": [], + "source": [ + "'''\n", + "a further test where if (I) a scalar * interval vector matches with (II) scalar interval * interval vector\n", + "'''" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "90868753-32eb-48d9-a2cc-eb5caad50a95", + "metadata": {}, + "outputs": [], + "source": [ + "x = np.array([3.2])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c049bfdf-eb62-4d37-958d-34e8642f639a", + "metadata": {}, + "outputs": [], + "source": [ + "# scaler * interval vector\n", + "x2 = I(3.2, 3.2)\n", + "x2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "90d81cb1-8b19-4ee4-9429-460805f63f1d", + "metadata": {}, + "outputs": [], + "source": [ + "3.2 * h1 == x2 * h1 " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9f8f1d70-c66e-4003-b58c-f253f5b24a08", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "bb1a50bc-00b0-4a98-bbb9-c5bdb4de1f0a", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "3f04e74c-3d22-4588-90bd-0895933a5b9d", + "metadata": { + "tags": [] + }, + "source": [ + "#### vector @ vector\n", + "\n", + "> to mimic the second layer propagation, from h1 to output\n", + "\n", + "> (1 by 3) * (3 by 1)\n", + "\n", + "> y = hidden_tensor * W2_int" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "55848810-9cfc-4328-b2d2-497f3c24de94", + "metadata": {}, + "outputs": [], + "source": [ + "# consider a column vector\n", + "\n", + "W2 = np.array([1, 3, 5])[:, np.newaxis]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "343ea692-fea7-4650-a45c-42b108dd8aed", + "metadata": {}, + "outputs": [], + "source": [ + "W2_intvl = create_interval(matrix=W2)\n", + "print(W2_intvl.shape)\n", + "W2_intvl" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5f9e63cf-80b8-434d-bcb2-f1aac363a127", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "136c2bd5-81ad-41dc-aa56-aaeef7270828", + "metadata": {}, + "outputs": [], + "source": [ + "y_hat = intvl_matmul(x=h1, W=W2_intvl)\n", + "y_hat" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f0ee30f5-1951-4bb1-a1c6-59adcb9b4219", + "metadata": {}, + "outputs": [], + "source": [ + "y_hat2 = intvl_matmul(x=h1, W=v1)\n", + "y_hat2" + ] + }, + { + "cell_type": "markdown", + "id": "66e3bc0f-eb3c-452a-b7ac-2dba3a898270", + "metadata": {}, + "source": [ + "# activation function" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5c7d91b8-31e2-46f3-b4b6-02223ded3d7a", + "metadata": {}, + "outputs": [], + "source": [ + "# sigmoid(x_intvl)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "transformer", + "language": "python", + "name": "transformer" + }, + "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.11.4" + }, + "toc-autonumbering": true + }, + "nbformat": 4, + "nbformat_minor": 5 +} From 6c71471db6d651af36453262de1db8fe83306dfa Mon Sep 17 00:00:00 2001 From: leslieDLcy Date: Fri, 12 Apr 2024 21:27:47 +0100 Subject: [PATCH 10/11] interval to pbox test not finished --- intervals/activation.py | 9 +- intervals/mat_features.py | 4 +- intervals/plotting.py | 1 + tests/activation_test.ipynb | 382 +++++++++++ tests/intervals_to_pbox.ipynb | 196 ++++++ tests/matrix_multiplication_marco.ipynb | 859 ++++++++++++++---------- 6 files changed, 1111 insertions(+), 340 deletions(-) create mode 100644 tests/activation_test.ipynb create mode 100644 tests/intervals_to_pbox.ipynb diff --git a/intervals/activation.py b/intervals/activation.py index f30dc98..f217550 100644 --- a/intervals/activation.py +++ b/intervals/activation.py @@ -1,8 +1,15 @@ from intervals.number import Interval from intervals.methods import exp +import numpy as np ''' a series of popular activation functions for interval arithmetic ''' def sigmoid(x:Interval): return 1/(1 + exp(-x)) -def tanh(x:Interval): return (exp(2*x)-1)/(exp(2*x)+1) \ No newline at end of file +def tanh(x:Interval): return (exp(2*x)-1)/(exp(2*x)+1) + + +def relu(x): + xs=x.shape + x0=np.zeros(xs) + return np.maximum(x0,x) \ No newline at end of file diff --git a/intervals/mat_features.py b/intervals/mat_features.py index 34424d1..5279e98 100644 --- a/intervals/mat_features.py +++ b/intervals/mat_features.py @@ -24,8 +24,8 @@ def consume_interval(low, high): def create_interval(matrix, half_width=0.1): """ mannually create an interval matrix from a numpy array """ - low = matrix * (1 - half_width) - high = matrix * (1 + half_width) + low = matrix - half_width + high = matrix + half_width return consume_interval(low, high) diff --git a/intervals/plotting.py b/intervals/plotting.py index 507431c..f883ab2 100644 --- a/intervals/plotting.py +++ b/intervals/plotting.py @@ -36,6 +36,7 @@ def basic_plot(x, y_i, **kwargs): return ax + def plot_lower_bound(x, y_i, **kwargs): """ plot lower bound of intervals diff --git a/tests/activation_test.ipynb b/tests/activation_test.ipynb new file mode 100644 index 0000000..7d526ca --- /dev/null +++ b/tests/activation_test.ipynb @@ -0,0 +1,382 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 17, + "id": "340b20c6-58ae-4175-a4cf-757905bb8c47", + "metadata": {}, + "outputs": [], + "source": [ + "from intervals.number import Interval as I\n", + "from intervals.methods import (lo,hi,mid,rad,width,intervalise, exp)\n", + "from intervals.random import uniform_endpoints \n", + "from intervals.plotting import plot_intervals, plot_lower_bound\n", + "from intervals.mat_features import create_interval\n", + "from intervals.activation import sigmoid, tanh" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "808b0878-876e-42b3-b603-b41b4b941407", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "38fea7d5-233c-409d-8cf8-a5ff3bf1b95e", + "metadata": {}, + "outputs": [], + "source": [ + "%load_ext autoreload\n", + "%autoreload 2" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "725c8f94-a582-4a44-8296-ca9de529dad3", + "metadata": {}, + "outputs": [], + "source": [ + "x = np.arange(4)\n", + "y = np.arange(4)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "957cbb39-6781-4bdc-b546-8fddd0ba2a54", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[0.0,0.0]\n", + "[0.5,1.5]\n", + "[1.0,3.0]\n", + "[1.5,4.5]" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "y_i = create_interval(matrix=y, half_width=0.5)\n", + "y_i" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "933a61b0-ab3b-4084-9e50-6ff99a41ec66", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "009bae25-a281-47bf-8330-556878ffcdb8", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjcAAAGwCAYAAABVdURTAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAABGQklEQVR4nO3deXxU1f3/8ffMJJmQHQhJCIQdwh4QJAYVqqQiKmhtLaIVRJRq0ar4awW/CkWrUBekKhW1rlUrblUrFJRNRCIIiOz7FiAJhJCFbJPM3N8fSQYiISQhyZ3MvJ6Pxzxm5t5zJ5/LdZK39557jsUwDEMAAABewmp2AQAAAPWJcAMAALwK4QYAAHgVwg0AAPAqhBsAAOBVCDcAAMCrEG4AAIBX8TO7gMbmcrl09OhRhYaGymKxmF0OAACoAcMwlJeXp9jYWFmt1Z+b8blwc/ToUcXFxZldBgAAqIPU1FS1bdu22jY+F25CQ0Mllf3jhIWFmVwNAACoidzcXMXFxbn/jlfH58JNxaWosLAwwg0AAE1MTbqU0KEYAAB4FcINAADwKoQbAADgVQg3AADAqxBuAACAVyHcAAAAr0K4AQAAXoVwAwAAvArhBgAAeBXCDQAA8CqmhpuVK1dq5MiRio2NlcVi0WeffXbebVasWKGLLrpIdrtdXbp00VtvvdXgdQIAgKbD1HCTn5+vhIQEzZ07t0bt9+/fr2uvvVZXXHGFNm7cqAceeEB33nmnFi9e3MCVAgCApsLUiTNHjBihESNG1Lj9vHnz1LFjRz333HOSpB49emjVqlV6/vnnNXz48IYqEwCARmEYhgxDMiS53K/Ln898XdFWZctllG9fvl463eb069NtKtrr9Kbu9ZXqKV975mdWVfPPBfhZFRUaWOP9rm9NalbwlJQUJScnV1o2fPhwPfDAA+fcpri4WMXFxe73ubm5DVUeAMBkLpehghKnCopLVeBwqsDhVGFJ2euiEpeKSpwqLj39XFzqlKPU5X6UOF1yOA2VOF1nPAyVOl0qdZUtd7oMlbqMsmdn2bPTMOQqfy51GjKMstdOV1lIcZWvN4yK96fDS8X6MwNIU3dRuwh9+odLTfv5TSrcpKenKzo6utKy6Oho5ebmqrCwUM2aNTtrm5kzZ2rGjBmNVSIAoB4UlTiVeapYmaccOpnvUFa+QycLyp5zCkuUW1Ra9lxYotyiEuUXl+pUUakKSpxeExAaisVS/lxpmaXSMssZKy2VWv5sw3Ms8reZe79Skwo3dTF16lRNnjzZ/T43N1dxcXEmVgQAvq3E6dLhk4U6lFWgo9mFSssu1JHsIqXlFOpYXrGO5xUrp7Dkgn6G1SIFBfipWYBNzfxtCgqwye5vU6CfVYH+NgX6W2X3synAzyq7n1UB5Q+7zSp/m1X+fuXPNov8rFb52Szys1rkZ7PK32qRzWqRn80im9Uqm6XsfdlDslrKtrFYJJvVIqvl9PKKh8WiSustkmSRbBaLLBaLrJbyUFHerqKNpXx5pfBxxrKyNpZKIcViqSKNeLkmFW5iYmKUkZFRaVlGRobCwsKqPGsjSXa7XXa7vTHKAwCcIbvAoV0Zp7QzI0+7M/K0PzNfB08U6Eh2oZyu859eCbBZFRkSoBYhAWoeFKAWwWXP4c38Fd7MX2HN/BUW6KfQQH+FBvopxO6nYLufQgP9ZPez+uQfdZRpUuEmKSlJCxcurLTs66+/VlJSkkkVAQAkKSvfoZ8OZ+un1LLHtrRcZeQWn7N9oL9V7VsEKzYiUK0jmqlNRDO1Dg9UTFigWoXaFRUaqLBmfgQU1Imp4ebUqVPas2eP+/3+/fu1ceNGtWjRQu3atdPUqVN15MgRvfPOO5Kku+++Wy+99JL+/Oc/64477tCyZcv04YcfasGCBWbtAgD4pKPZhUrZe0Ip+05o7f4sHcoqqLJdm4hm6hYdom7RoercKkTtWwapQ2SwokLtBBc0GFPDzbp163TFFVe431f0jRk3bpzeeustpaWl6dChQ+71HTt21IIFC/Tggw/q73//u9q2bat//vOf3AYOAA2suNSplL0n9PW2DK3ak6mDJ84OM51bBSuhbYT6tg1Xn7bh6hYdqtBAfxOqha+zGFXdoO7FcnNzFR4erpycHIWFhZldDgB4rPziUn29LUNfb8vQip3HlO9wutfZrBb1bhOupE4tldS5pfq3i1AYQQYNqDZ/v5tUnxsAQMNyuQx9v++EPt5wWP/bnK7CktOBJirUruSe0RrWPUqDOrbgrAw8FuEGAKDMU8V69/uD+mjdYR3JLnQv7xgZrGv6xOiXPWPUt024rFb6ycDzEW4AwIftOXZKr6/ap082HJGj1CVJCg3008iEWP36ora6qF0EHX/R5BBuAMAH/ZSarReW7tbSHcfcyxLiInTHpR00vFeMAv1tJlYHXBjCDQD4kIMn8vXM4p36clOapLIRbJN7RGvikE4a2L45Z2ngFQg3AOADTpwq1ovL9ui9NQdV4jRksUi/6t9G917RRZ1ahZhdHlCvCDcA4MUMw9BH6w7riQXblFdUKkka0q2VplzdXT1jGQ4D3olwAwBe6vDJAk39dLO+3Z0pSerZOkyPXNNDl3WNNLkyoGERbgDAy7hcht5bc1Cz/rdD+Q6n7H5WPXRVN91xaUf52axmlwc0OMINAHiRk/kO/fGDH91nay7u0Fx/+3Vf+tXApxBuAMBLbDmSo9//a72OZBcq0N+qqSN66LZL2jPwHnwO4QYAvMBH61L16GdbVFzqUvuWQXrltgHqHkOHYfgmwg0ANGElTpdm/Her3v3+kCRpWPcozR7dT+HNmPcJvotwAwBNVFGJU/e+v0FLth+TxSI9MKyb7ruyC5eh4PMINwDQBJ0qLtVdb69Tyr4TsvtZ9dItF+mXPaPNLgvwCIQbAGhisgscGvfmD/opNVvBATa9fvvFuqRTS7PLAjwG4QYAmpBjuUW67fW12pmRp4ggf709fpAS4iLMLgvwKIQbAGgiTuY7NOa177X3eL6iQu16985EdYsONbsswOMQbgCgCSh0ODXh7R+093i+WocHav7EJLVrGWR2WYBHYhxuAPBwpU6X7vv3Bm04lK3wZv56545BBBugGoQbAPBghmHo0c+2aMn2Y7L7WfX6uIHqyqUooFqEGwDwYM8v2a0PfkiV1SK9MKa/BnZoYXZJgMcj3ACAh/rPj4f1wtLdkqTHr++t4b1iTK4IaBoINwDggXZl5OmRT7dIkiZd0Vm/u6S9yRUBTQfhBgA8TH5xqf7w3gYVljh1WZdITf5lvNklAU0K4QYAPIhhGHrkP5u159gpRYfZNefmfrIxVxRQK4QbAPAg/16bqs83HpXNatFLt1ykyBC72SUBTQ7hBgA8xJYjOfrLf7dKkv48PF4Xc2cUUCeEGwDwAIUOp+59f4McpS4l94jSXZd3MrskoMki3ACAB3h+yS4dOFGg1uGBeu6mfrLSzwaoM8INAJjsp9Rs/fPbfZKkJ3/VW+FB/iZXBDRthBsAMJGj1KWHP9kklyHd0C9WV3aPNrskoMkj3ACAiV5esVc70vPUIjhA00b2MrscwCsQbgDAJLsy8vTS8rLpFaaP7KkWwQEmVwR4B8INAJjA6TL05483qcRpaFj3KI1KiDW7JMBrEG4AwATvfn9QG1OzFWL3019/1VsWC3dHAfWFcAMAjSynsERzluySJP356ni1Dm9mckWAdyHcAEAjm7t8j04WlKhLVIhuGdTO7HIAr0O4AYBGlJpVoLe+OyBJeuSa7vKz8WsYqG98qwCgEc1atEMOp0uXdmmpK+KjzC4H8EqEGwBoJOsPntSCTWmyWKT/u6YnnYiBBkK4AYBGYBiG/rpgmyTpNxe1Vc/YMJMrArwX4QYAGsHCzen68VC2mvnb9P+Gx5tdDuDVCDcA0MBKnC79bdEOSdLEIZ0UHRZockWAdyPcAEAD+8+GIzqUVaDIELsmDulkdjmA1yPcAEADKnW69I8VeyRJE4d0VLDdz+SKAO9HuAGABrRgc5oOnChQ8yB/3ZrY3uxyAJ9AuAGABuJyGXppWdlZmwmXcdYGaCyEGwBoIF9tS9fuY6cUGuinsYM7mF0O4DMINwDQAAzD0IvlZ21uH9xBYYH+JlcE+A7CDQA0gOU7j2nr0VwFBdg0/tKOZpcD+BTCDQDUM8Mw9MLSsrM2v7ukvVoEB5hcEeBbCDcAUM9W7z2hjanZsvtZdeflnLUBGhvhBgDq2Ssr90mSbr44TlGhjEYMNDbCDQDUo73HT2nlruOyWKQJlzEaMWAGwg0A1KN3Vh+QJA3rHqV2LYPMLQbwUaaHm7lz56pDhw4KDAxUYmKi1q5dW237OXPmKD4+Xs2aNVNcXJwefPBBFRUVNVK1AHBueUUl+nj9YUnSOMa1AUxjariZP3++Jk+erOnTp2vDhg1KSEjQ8OHDdezYsSrbv//++5oyZYqmT5+u7du36/XXX9f8+fP1yCOPNHLlAHC2T9YfVr7Dqc6tgnVZl0izywF8lqnhZvbs2brrrrs0fvx49ezZU/PmzVNQUJDeeOONKtuvXr1al156qW655RZ16NBBV111lcaMGXPesz0A0NBcLkPvpByUVHbWxmKxmFwR4LtMCzcOh0Pr169XcnLy6WKsViUnJyslJaXKbQYPHqz169e7w8y+ffu0cOFCXXPNNef8OcXFxcrNza30AID69u2eTO3LzFeo3U83XtTW7HIAn2baLG6ZmZlyOp2Kjo6utDw6Olo7duyocptbbrlFmZmZuuyyy2QYhkpLS3X33XdXe1lq5syZmjFjRr3WDgA/93Z5R+LfDGyrECbIBExleofi2lixYoWeeuop/eMf/9CGDRv06aefasGCBXriiSfOuc3UqVOVk5PjfqSmpjZixQB8wcET+Vq+s6yv4NikDuYWA8C8MzeRkZGy2WzKyMiotDwjI0MxMTFVbvPYY4/ptttu05133ilJ6tOnj/Lz8zVx4kT93//9n6zWs7Oa3W6X3W6v/x0AgHLvpByUYUi/iG+ljpHBZpcD+DzTztwEBARowIABWrp0qXuZy+XS0qVLlZSUVOU2BQUFZwUYm80mqWwuFwBobAWOUn24ruyMMLd/A57B1AvDkydP1rhx4zRw4EANGjRIc+bMUX5+vsaPHy9JGjt2rNq0aaOZM2dKkkaOHKnZs2erf//+SkxM1J49e/TYY49p5MiR7pADAI1pwaY05RWVqn3LIA3t2srscgDI5HAzevRoHT9+XNOmTVN6err69eunRYsWuTsZHzp0qNKZmkcffVQWi0WPPvqojhw5olatWmnkyJF68sknzdoFAD7uo/JB+347ME5WK7d/A57AYvjY9Zzc3FyFh4crJydHYWFhZpcDoAk7eCJfQ59ZIatF+m7KlWod3szskgCvVZu/303qbikA8CQVUy1c1rUVwQbwIIQbAKgDp8vQJ+Xh5qYBDNoHeBLCDQDUwXd7MnU0p0jhzfz1y57R598AQKMh3ABAHVR0JL6+X6wC/blbE/AkhBsAqKWcghIt3pouSbppQJzJ1QD4OcINANTSF5uOylHqUveYUPVuw12XgKch3ABALX1cPiLxbwa0lcXC2DaApyHcAEAt7EzP00+Hc+RntehX/duYXQ6AKhBuAKAWPio/a3Nl9yi1DGFSXsATEW4AoIacLkNf/HRUUtklKQCeiXADADX0w4EsHcsrVlign4bGM0km4KkINwBQQ/8tP2szvFeM7H6MbQN4KsINANRAqdOl/20pG9tmZEKsydUAqA7hBgBqYPXeE8rKd6hFcIAGd25pdjkAqkG4AYAaqLgkdU2fGPnZ+NUJeDK+oQBwHsWlTi0qn25hZF8uSQGejnADAOfx7a5M5RWVKjrMros7tDC7HADnQbgBgPP476ayS1LX9Y2V1cp0C4CnI9wAQDUKHU59vS1DknRd39YmVwOgJgg3AFCNZTuOqcDhVNvmzdQvLsLscgDUAOEGAKrxZfklqZEJscwADjQRhBsAOIe8ohIt23FMEndJAU0J4QYAzmHZjmMqLnWpU6tg9WgdanY5AGqIcAMA5/DV1rKOxCN6x3BJCmhCCDcAUIWiEqdW7Cy7JHVVzxiTqwFQG4QbAKjC6r2Zync41To8UH3bhptdDoBaINwAQBUWbym7JHVVz2guSQFNDOEGAH7G6TK0ZHt5uOnFJSmgqSHcAMDPrD94UifyHQpv5q9BHZlLCmhqCDcA8DNflc8APqx7lPxt/JoEmhq+tQBwBsMwtHhbWbjhkhTQNBFuAOAM29PylJpVKLufVUO6RZpdDoA6INwAwBm+Kj9rM6RbKwUF+JlcDYC6INwAwBkWbz19CziApolwAwDlUrMKtD0tVzarRck9CDdAU0W4AYByi8vvkhrUoYWaBweYXA2AuiLcAEC5r7ZVDNzHWRugKSPcAICknIISrT94UpK4JAU0cYQbAJD0ze7jcroMdYsOUVyLILPLAXABCDcAIGlZ+VxSV3bnrA3Q1BFuAPg8p8vQN7uOS5Ku7B5lcjUALhThBoDP25h6UicLShTezF8XtYswuxwAF4hwA8DnLd1+TFLZqMR+TJQJNHl8iwH4vGU7ysLNMC5JAV6BcAPApx3NLtSO9DxZLdLQbq3MLgdAPSDcAPBpy3eWnbXp3645oxIDXoJwA8CnLSvvb8NdUoD3INwA8FlFJU59tzdTEuEG8CaEGwA+K2XfCRWVuNQ6PFDdY0LNLgdAPSHcAPBZy8vvkrqie5QsFovJ1QCoL4QbAD7JMAz3+DbcAg54F8INAJ+0+9gpHckulN3PqsGdI80uB0A9ItwA8Ekrym8BT+rcUs0CbCZXA6A+EW4A+KSKiTIZuA/wPoQbAD6nwFGqH/aflES4AbwR4QaAz/l+3wk5nC7FtWimjpHBZpcDoJ4RbgD4nG92ll2SGtK1FbeAA17I9HAzd+5cdejQQYGBgUpMTNTatWurbZ+dna1JkyapdevWstvt6tatmxYuXNhI1QLwBit3l41KzCUpwDv5mfnD58+fr8mTJ2vevHlKTEzUnDlzNHz4cO3cuVNRUWePO+FwOPTLX/5SUVFR+vjjj9WmTRsdPHhQERERjV88gCbp4Il87c/Ml5/VoqTOLc0uB0ADqFO4KS4u1po1a3Tw4EEVFBSoVatW6t+/vzp27Firz5k9e7buuusujR8/XpI0b948LViwQG+88YamTJlyVvs33nhDWVlZWr16tfz9/SVJHTp0OG+txcXF7ve5ubm1qhGAd1lZfpfUgPbNFRrob3I1ABpCrS5Lfffdd/rtb3+riIgIXXnllXrggQf0xBNP6He/+526dOmirl276plnnlFeXt55P8vhcGj9+vVKTk4+XYzVquTkZKWkpFS5zRdffKGkpCRNmjRJ0dHR6t27t5566ik5nc5z/pyZM2cqPDzc/YiLi6vNLgPwMt/sKr8kFc8lKcBb1TjcjBo1SqNHj1aHDh301VdfKS8vTydOnNDhw4dVUFCg3bt369FHH9XSpUvVrVs3ff3119V+XmZmppxOp6Kjoystj46OVnp6epXb7Nu3Tx9//LGcTqcWLlyoxx57TM8995z++te/nvPnTJ06VTk5Oe5HampqTXcZgJdxlLqUUj4L+JCuhBvAW9X4stS1116rTz75xH056Oc6deqkTp06ady4cdq2bZvS0tLqrcgKLpdLUVFRevXVV2Wz2TRgwAAdOXJEzzzzjKZPn17lNna7XXa7vd5rAdD0rD94UvkOpyJD7OrZOszscgA0kBqHm9///vc1/tCePXuqZ8+e1baJjIyUzWZTRkZGpeUZGRmKiYmpcpvWrVvL399fNtvpodJ79Oih9PR0ORwOBQQE1LhGAL6nYlTiIV0jZbVyCzjgrWrV52bJkiXVrne5XNVeIjpTQECABgwYoKVLl1bafunSpUpKSqpym0svvVR79uyRy+VyL9u1a5dat25NsAFwXu4pF+hvA3i1WoWba665Rvfee68KCgrOWrdlyxZdfPHFevnll2v8eZMnT9Zrr72mt99+W9u3b9c999yj/Px8991TY8eO1dSpU93t77nnHmVlZen+++/Xrl27tGDBAj311FOaNGlSbXYDgA86lluk7Wm5sliky7owCzjgzWoVbr799lstXbpUCQkJ+u677ySdPlszYMAAxcfHa8uWLTX+vNGjR+vZZ5/VtGnT1K9fP23cuFGLFi1ydzI+dOhQpb47cXFxWrx4sX744Qf17dtXf/zjH3X//fdXeds4AJypYuC+Pm3C1TKEfniAN7MYhmHUZoOioiJNmTJF//jHPzRx4kR9//33Sk1N1csvv6wbb7yxoeqsN7m5uQoPD1dOTo7CwuhQCPiKP/77R33x01Hdd2UXPXRVvNnlAKil2vz9rvUgfoGBgXr++ed17Ngx/eMf/1BwcLDWrVun+Hh+WQDwTC6XoW93l3cmZsoFwOvVem6pvXv3asiQIVq2bJnmzZun3r176xe/+IU+//zzhqgPAC7Y1qO5OllQolC7n/rFRZhdDoAGVqtw89JLLykhIUFRUVHavHmzJk6cqO+++04PPPCAbr75Zt12223Kzs5uoFIBoG5Wlp+1uaRzS/nbTJ8vGEADq9W3fNq0aXrllVf0ySefqFWrslO7VqtVDz/8sNatW6ft27erV69eDVIoANTVqvLOxJd35S4pwBfUqs/N1q1b1bp16yrX9erVS2vWrNFTTz1VL4UBQH0ocJRq3cEsSdLlTLkA+IRanbk5V7CpYLPZ9Nhjj11QQQBQn9bsz1KJ01CbiGbq0DLI7HIANIIah5sPPvigxh+amprqHgcHAMz0bfks4EO6RcpiYcoFwBfUONy8/PLL6tGjh55++mlt3779rPU5OTlauHChbrnlFl100UU6ceJEvRYKAHWxak9ZZ+LLunBJCvAVNe5z88033+iLL77Qiy++qKlTpyo4OFjR0dEKDAzUyZMnlZ6ersjISN1+++3asmWLe5RhADBLek6RdmWcksUiDe7c0uxyADSSWnUoHjVqlEaNGqXMzEytWrVKBw8eVGFhoSIjI9W/f3/1799fViu3WQLwDKv2lF2S6tsmXM2DmVwX8BW1HqFYkiIjI3XDDTfUcykAUL9WlY9vcxm3gAM+hdMsALySy2W4z9xwCzjgW2p85qZ58+Y1vtMgKyurzgUBQH3YkZ6nzFMOBQXYdFG75maXA6AR1TjczJkzx/36xIkT+utf/6rhw4crKSlJkpSSkqLFixczzg0Aj1AxUeYlnVoqwI+T1IAvqXG4GTdunPv1r3/9az3++OO699573cv++Mc/6qWXXtKSJUv04IMP1m+VAFBLFZekLutCfxvA19Tpf2cWL16sq6+++qzlV199tZYsWXLBRQHAhSgqcWrN/oopFwg3gK+pU7hp2bKlPv/887OWf/7552rZkrEkAJjrhwNZcpS6FBMWqC5RIWaXA6CR1elW8BkzZujOO+/UihUrlJiYKElas2aNFi1apNdee61eCwSA2qqYBfyyrky5APiiOoWb22+/XT169NALL7ygTz/9VJLUo0cPrVq1yh12AMAs3+6uuAWcS1KAL6pTuJGkxMREvffee/VZCwBcsMxTxdqWlitJupTOxIBPqnG4yc3NVVhYmPt1dSraAUBj+678LqkercMUGWI3uRoAZqjVIH5paWmKiopSREREldexDcOQxWKR0+ms1yIBoKa+c98Czs0NgK+qcbhZtmyZWrRoIUlavnx5gxUEAHVlGMYZnYmZcgHwVTUON0OHDq3yNQB4in2Z+TqaU6QAm1WDOrQwuxwAJqlzh+Ls7Gy9/vrr2r59uySpV69euuOOOxQeHl5vxQFAbVSctRnYobmaBdhMrgaAWeo0iN+6devUuXNnPf/888rKylJWVpZmz56tzp07a8OGDfVdIwDUSMUt4NwlBfi2Op25efDBBzVq1Ci99tpr8vMr+4jS0lLdeeedeuCBB7Ry5cp6LRIAzqfU6dL3+05IYnwbwNfVKdysW7euUrCRJD8/P/35z3/WwIED6604AKipnw5n61RxqSKC/NUrlsvjgC+r02WpsLAwHTp06KzlqampCg0NveCiAKC23JekOkfKZmXKBcCX1SncjB49WhMmTND8+fOVmpqq1NRUffDBB7rzzjs1ZsyY+q4RAM5rFf1tAJSr02WpZ599VhaLRWPHjlVpaakkyd/fX/fcc49mzZpVrwUCwPnkFZXox9RsSfS3AVDHcBMQEKC///3vmjlzpvbu3StJ6ty5s4KCguq1OACoiTX7suR0GWrfMkhxLfg9BPi6Oo9zI0lBQUHq06dPfdUCAHWyyj3lAmdtANQx3BQVFenFF1/U8uXLdezYMblcrkrrGesGQGP6dvdxSVySAlCmTuFmwoQJ+uqrr/Sb3/xGgwYNqnISTQBoDGk5hdp7PF9Wi5TUiXADoI7h5ssvv9TChQt16aWX1nc9AFArFbeA920bofAgf5OrAeAJ6nQreJs2bRjPBoBHqAg3XJICUKFO4ea5557Tww8/rIMHD9Z3PQBQYy6Xoe/2VISbViZXA8BT1Omy1MCBA1VUVKROnTopKChI/v6VTwVnZWXVS3EAUJ1tabnKyncoOMCm/u0izC4HgIeoU7gZM2aMjhw5oqeeekrR0dF0KAZgiopLUkmdW8rfVqcT0QC8UJ3CzerVq5WSkqKEhIT6rgcAamzVnrJbwBnfBsCZ6vS/Ot27d1dhYWF91wIANVbocOqH/SclSZd3o78NgNPqFG5mzZqlhx56SCtWrNCJEyeUm5tb6QEADW3tgSw5nC7FhgeqU2Sw2eUA8CB1uix19dVXS5KGDRtWablhGLJYLHI6nRdeGQBU49tdFaMSt6LfH4BK6hRuli9fXt91AECtuOeTYnwbAD9Tp3AzdOjQ+q4DAGrsWG6RdqTnyWKRLqUzMYCfqVO42bRpU5XLLRaLAgMD1a5dO9nt9gsqDADOpeKsTe/YcLUIDjC5GgCepk7hpl+/ftVe4/b399fo0aP1yiuvKDAwsM7FAUBVmHIBQHXqdLfUf/7zH3Xt2lWvvvqqNm7cqI0bN+rVV19VfHy83n//fb3++utatmyZHn300fquF4CPMwzDHW7obwOgKnU6c/Pkk0/q73//u4YPH+5e1qdPH7Vt21aPPfaY1q5dq+DgYD300EN69tln661YANiRnqfMU8Vq5m/TgPbNzS4HgAeq05mbzZs3q3379mctb9++vTZv3iyp7NJVWlrahVUHAD+zqvysTWKnFrL72UyuBoAnqvMIxbNmzZLD4XAvKykp0axZs9S9e3dJ0pEjRxQdHV0/VQJAuZW7T49vAwBVqdNlqblz52rUqFFq27at+vbtK6nsbI7T6dSXX34pSdq3b5/+8Ic/1F+lAHxeocOpNfuzJElDmXIBwDnUKdwMHjxY+/fv13vvvaddu3ZJkm666SbdcsstCg0NlSTddttt9VclAEj6fv8JOUpdahPRTJ1bMeUCgKrVKdxIUmhoqO6+++76rAUAqvXNzrJLUkO6MeUCgHOrcbj54osvNGLECPn7++uLL76otu2oUaMuuDAA+LmK/jZckgJQnRqHmxtuuEHp6emKiorSDTfccM52dZk4c+7cuXrmmWeUnp6uhIQEvfjiixo0aNB5t/vggw80ZswYXX/99frss89q9TMBNC2pWQXadzxfNqtFg7u0NLscAB6sxndLuVwuRUVFuV+f61HbYDN//nxNnjxZ06dP14YNG5SQkKDhw4fr2LFj1W534MAB/b//9/90+eWX1+rnAWiaKs7aDGjXXGGB/iZXA8CT1epW8JSUFPfdUBXeeecddezYUVFRUZo4caKKi4trVcDs2bN11113afz48erZs6fmzZunoKAgvfHGG+fcxul06tZbb9WMGTPUqVOnWv08AE3T6f42jEoMoHq1CjePP/64tm7d6n6/efNmTZgwQcnJyZoyZYr++9//aubMmTX+PIfDofXr1ys5Ofl0QVarkpOTlZKSUm0dUVFRmjBhwnl/RnFxsXJzcys9ADQtJU6XVu89IUka2i3K5GoAeLpahZuNGzdq2LBh7vcffPCBEhMT9dprr2ny5Ml64YUX9OGHH9b48zIzM+V0Os8a7C86Olrp6elVbrNq1Sq9/vrreu2112r0M2bOnKnw8HD3Iy4ursb1AfAMGw6e1KniUrUMDlCv2DCzywHg4WoVbk6ePFkpiHzzzTcaMWKE+/3FF1+s1NTU+qvuZ/Ly8nTbbbfptddeU2RkzU5NT506VTk5Oe5HQ9YHoGF8s6tiVOJIWa3cAg6gerUa5yY6Olr79+9XXFycHA6HNmzYoBkzZrjX5+Xlyd+/5h39IiMjZbPZlJGRUWl5RkaGYmJizmq/d+9eHThwQCNHjnQvc7lcZTvi56edO3eqc+fOlbax2+2y2+01rgmA53HfAh7PLeAAzq9WZ26uueYaTZkyRd9++62mTp2qoKCgSncrbdq06axwUZ2AgAANGDBAS5cudS9zuVxaunSpkpKSzmrfvXt3bd68WRs3bnQ/Ro0apSuuuEIbN27kkhPghY7nFWvLkbK+cswnBaAmanXm5oknntCNN96ooUOHKiQkRG+//bYCAgLc69944w1dddVVtSpg8uTJGjdunAYOHKhBgwZpzpw5ys/P1/jx4yVJY8eOVZs2bTRz5kwFBgaqd+/elbaPiIiQpLOWA/AO35aftendJkyRIZyFBXB+tQo3kZGRWrlypXJychQSEiKbzVZp/UcffaSQkJBaFTB69GgdP35c06ZNU3p6uvr166dFixa5+/YcOnRIVmudJi8H4AVW7mJUYgC1YzEMwzC7iMaUm5ur8PBw5eTkKCyMuy4AT+ZyGRr45BJl5Ts0f+IlSuzEyMSAr6rN329OiQDwWJuP5Cgr36EQu58uat/c7HIANBGEGwAea9mOsmlYLu8aKX8bv64A1Ay/LQB4rOU7y8LNFd0ZlRhAzRFuAHikY7lF2nQ4R5L0C8a3AVALhBsAHmlF+USZCW3DFRUaaHI1AJoSwg0Aj1TR34ZLUgBqi3ADwOM4Sl3uwfuuJNwAqCXCDQCPs3Z/lvIdTkWG2NU7NtzscgA0MYQbAB6n4pLUld1bMQs4gFoj3ADwOBW3gHNJCkBdEG4AeJR9x09pf2a+/G0WXcYs4ADqgHADwKNUXJIa1LGFQuy1mtsXACQRbgB4mNOXpKJNrgRAU0W4AeAx8opKtHZ/liT62wCoO8INAI+xanemSpyGOkYGq2NksNnlAGiiCDcAPIZ7VOJ4ztoAqDvCDQCP4HQZWloebob1INwAqDvCDQCPsO5AlrLyHQpv5q9BHVuYXQ6AJoxwA8AjLN6aIansrI2/jV9NAOqO3yAATGcYhr7ali5JuqpnjMnVAGjqCDcATLctLVeHTxYq0N+qod0YlRjAhSHcADDdV+WXpIZ0baVmATaTqwHQ1BFuAJhu8dbyS1K9uCQF4MIRbgCY6tCJAu1Iz5PNatEwRiUGUA8INwBMVdGReFCHFmoeHGByNQC8AeEGgKkq+tsM78VEmQDqB+EGgGkyTxXrh4NlE2X+kv42AOoJ4QaAaZZsy5BhSH3ahKtNRDOzywHgJQg3AEzz1bayS1JX9eSSFID6Q7gBYIpTxaVatTtTkjS8N5ekANQfwg0AUyzbcUwOp0sdWgapa1SI2eUA8CKEGwCm+O9PRyVJ1/WNlcViMbkaAN6EcAOg0eUUluibncclSdcltDa5GgDehnADoNF9vS1DDqdLXaNCFB8danY5ALwM4QZAo6u4JDUygUtSAOof4QZAo8rKd2jVnrK7pK7ryyUpAPWPcAOgUf1vS5qcLkO924SpUyvukgJQ/wg3ABrVmXdJAUBDINwAaDQZuUVas79sLqlr+3BJCkDDINwAaDQLNqXJMKSL2kUorkWQ2eUA8FKEGwCN5stNp++SAoCGQrgB0ChSswq04VC2LBYuSQFoWIQbAI1iweY0SdIlHVsqKizQ5GoAeDPCDYBG8fnG8rukmG4BQAMj3ABocFuO5Gh7Wq4CbFZd05twA6BhEW4ANLiP1x+WJP2yZ7SaBweYXA0Ab0e4AdCgikud+mzjEUnSbwa2NbkaAL6AcAOgQS3dfkzZBSWKDrNrSNdWZpcDwAcQbgA0qI/WpUqSbryorWxWZgAH0PAINwAaTEZukb7ZdVySdNMALkkBaByEGwAN5pMNh+UypIHtmzMDOIBGQ7gB0CAMw9DH68rukrqJjsQAGhHhBkCD2HDopPZl5quZv03X9mUuKQCNh3ADoEF8VH7WZkSfGIXY/UyuBoAvIdwAqHcFjlJ9ualsLqmbBsSZXA0AX0O4AVDvFmxK06niUrVrEaTEji3MLgeAj/GIcDN37lx16NBBgYGBSkxM1Nq1a8/Z9rXXXtPll1+u5s2bq3nz5kpOTq62PYDGZRiG3k45IEm6eVCcrIxtA6CRmR5u5s+fr8mTJ2v69OnasGGDEhISNHz4cB07dqzK9itWrNCYMWO0fPlypaSkKC4uTldddZWOHDnSyJUDqMqGQye15UiuAvysuvnidmaXA8AHWQzDMMwsIDExURdffLFeeuklSZLL5VJcXJzuu+8+TZky5bzbO51ONW/eXC+99JLGjh173va5ubkKDw9XTk6OwsLCLrh+AJXd9+8f9d+fjuqmAW31zE0JZpcDwEvU5u+3qWduHA6H1q9fr+TkZPcyq9Wq5ORkpaSk1OgzCgoKVFJSohYtqr6uX1xcrNzc3EoPAA0jI7dI/9tc1pF43OAO5hYDwGeZGm4yMzPldDoVHR1daXl0dLTS09Nr9BkPP/ywYmNjKwWkM82cOVPh4eHuR1wcd24ADeW97w+q1GVoYPvm6t0m3OxyAPgo0/vcXIhZs2bpgw8+0H/+8x8FBgZW2Wbq1KnKyclxP1JTUxu5SsA3FJc69f7aQ5Kk2y/tYG4xAHyaqSNrRUZGymazKSMjo9LyjIwMxcTEVLvts88+q1mzZmnJkiXq27fvOdvZ7XbZ7fZ6qRfAuS3cnKbMUw7FhAVqeK/qv78A0JBMPXMTEBCgAQMGaOnSpe5lLpdLS5cuVVJS0jm3e/rpp/XEE09o0aJFGjhwYGOUCuA83lp9UJJ0a2I7+dua9ElhAE2c6WOiT548WePGjdPAgQM1aNAgzZkzR/n5+Ro/frwkaezYsWrTpo1mzpwpSfrb3/6madOm6f3331eHDh3cfXNCQkIUEsKsw4AZfjx0Uj+lZivAZtWYRG7/BmAu08PN6NGjdfz4cU2bNk3p6enq16+fFi1a5O5kfOjQIVmtp/8v8OWXX5bD4dBvfvObSp8zffp0/eUvf2nM0gGUe3v1AUnSdX1bKzKEy8AAzGX6ODeNjXFugPp1JLtQQ59erlKXoc8nXaqEuAizSwLghZrMODcAmr55K/aq1GVocOeWBBsAHoFwA6DOMnKLNH9d2fAK913Z1eRqAKAM4QZAnb22cp8cpS4NbN9cl3Ri9m8AnoFwA6BOTpwq1ntrygbtu/fKLrJYmP0bgGcg3ACokze+26/CEqf6tAnX0G6tzC4HANwINwBqLaegRG+XD9rHWRsAnoZwA6DW3k45oFPFpYqPDtUve0SffwMAaESEGwC1cqq4VG98t19S2Vkbq5WzNgA8C+EGQK28vfqAsgtK1CkyWNf0aW12OQBwFsINgBrLPFWsl1fslST9cVhX2ThrA8ADEW4A1NjzX+/SqeJS9W0brlEJsWaXAwBVItwAqJHdGXn699qycW0evbYnfW0AeCzCDYAaeWrhdrkMaXivaA3qyGjEADwX4QbAea3ananlO4/Lz2rRw1d3N7scAKgW4QZAtZwuQ39dsE2S9LtL2qtTqxCTKwKA6hFuAFTrk/WHtSM9T2GBfrp/GDN/A/B8hBsA55RbVKJnv9opSbrvyq5qHhxgckUAcH6EGwDnNHPhDh3LK1aHlkEaO7i92eUAQI0QbgBUafXeTPet37N+3Vd2P5vJFQFAzRBuAJyl0OHU1E83S5JuTWynSzq1NLkiAKg5wg2Aszy/ZJcOnihQ6/BATRnBrd8AmhbCDYBKfkrN1j+/3SdJevJXvRUa6G9yRQBQO4QbAG6OUpce/mSTXIZ0fb9YXdk92uySAKDWCDcA3F5ctls70vPUIjhA067raXY5AFAnhBsAkqSVu47rpeV7JEkzRvVSyxC7yRUBQN0QbgAoLadQD8zfKMOQbklsp5EJsWaXBAB1RrgBfFyJ06X73v9RWfkO9YoN43IUgCaPcAP4uGcW79S6gycVavfTP269SIH+DNYHoGkj3AA+7Kut6Xp1Zdlt38/c1FftWwabXBEAXDjCDeCjdmfk6aGPfpIkTbiso67u3drkigCgfhBuAB+UllOocW+sVV5RqQa2b84oxAC8CuEG8DE5BSW6/Y0fdDSnSJ1aBeu1sQPlb+NXAQDvwW80wIcUlTh11zvrtDMjT1Ghdr1zxyA1Dw4wuywAqFeEG8BHOF2GHvhgo9YeyFKo3U9v3zFIbZsHmV0WANQ7wg3gA5wuQ498ulmLtqYrwGbVK2MHqEfrMLPLAoAG4Wd2AQAalqPUpQc/3KgFm9JktUizRydocOdIs8sCgAZDuAG8WKHDqXveW68VO4/L32bRnNH9dW1fbvkG4N0IN4CXyisq0YS312nt/iwF+ls173cD9Iv4KLPLAoAGR7gBvFBGbpHufHudNh/JUajdT2+Mv1gXd2hhdlkA0CgIN4CXWbs/S394b4MyTxWrRXCA3rljkHq3CTe7LABoNIQbwEsYhqE3vzugpxZuV6nLUHx0qF65bYA6RDJfFADfQrgBvECBo1RTP92szzcelSSNSojVrF/3UVAAX3EAvofffEATt+5Alv78ySbtO54vm9Wi/7umh8Zf2kEWi8Xs0gDAFIQboIkqcJTqmcU79dbqAzIMKSrUrhfH9Fdip5ZmlwYApiLcAE3Q6j2ZevjTTUrNKpQk3TSgrR69tqfCg/xNrgwAzEe4AZqQ/Zn5embxDi3cnC5JahPRTE/d2EdDu7UyuTIA8ByEG6AJyDxVrBeW7tb7aw6p1GXIYpF+l9heD4/orhA7X2MAOBO/FQEPlnmqWO+sPqDXV+1XvsMpSboivpUeHtFd3WOY+BIAqkK4ATzQ3uOn9M9v9+vTDYdVXOqSJPVpE66p13Rn0ksAOA/CDeAhSp0urdx9XO+vOaQl24+5lye0DdfEIZ01oneMrFZu7waA8yHcACbbkZ6rj9cd1mcbjyrzVLEkyWKRhnWP1sQhnXRxh+aMWQMAtUC4ARqZYRjaciRXX29L11fbMrQjPc+9rmVwgK7v10a3XtJOnVuFmFglADRdhBugEeQUlOj7/Se0anemlmzPUFpOkXudv82iYd2j9ZsBbTU0vpX8bVYTKwWApo9wAzSAY7lF+ulwjtbsO6GUfSe0LS1XhnF6fVCATUO6ttIve0bryu5Rah4cYF6xAOBlCDfABTAMQ2k5RdqZkaftabnalJqjnw5nVzozU6Fzq2AldW6pK7tHaXDnSAX620yoGAC8H+EGqIH84lIdPFGggyfydaD8efexU9qVnqe84tKz2lstUteoUF3UPkKXdGqppE4tFRUWaELlAOB7PCLczJ07V88884zS09OVkJCgF198UYMGDTpn+48++kiPPfaYDhw4oK5du+pvf/ubrrnmmkasGN7C5TJ0ssCh46eKdTyv7HEsr1hp2YU6mlOktJxCHc0uUla+45yf4We1qFOrYHWLDlXftuFKaBuh3m3CFczIwQBgCtN/+86fP1+TJ0/WvHnzlJiYqDlz5mj48OHauXOnoqKizmq/evVqjRkzRjNnztR1112n999/XzfccIM2bNig3r17m7AHMIthGCoqcanAUaoCh1OFJU6dKi7VqaJS5ReXKq/8dW5RiXILy55zCkuUXeBQVr5DJwvKXruM8/8sSWoe5K/2LYPVoWWQ2rUMVpeoEMVHh6pjZLAC/OgEDACewmIYRg1/tTeMxMREXXzxxXrppZckSS6XS3Fxcbrvvvs0ZcqUs9qPHj1a+fn5+vLLL93LLrnkEvXr10/z5s0778/Lzc1VeHi4cnJyFBZWf8PXF5c6dTyv+KzlP//Xrepf29DZCyvaGe73hvv96c8wKrU7/fqM5cbp95Vel3/m6e0MuYyyMxmGJFd5I5dR9tpllG1X9rr82WXIaZzezlnx/sxnl6HSnz87XSqpeHYaKnW5VFJqqMTpksPpKnsuLXtdXFL27Ch1qajEqaISl4pKne7X9aVFcIBahdjVKrTsERMeqNjwQMVGNFPr8GZqE9GMGbcBwES1+ftt6pkbh8Oh9evXa+rUqe5lVqtVycnJSklJqXKblJQUTZ48udKy4cOH67PPPquyfXFxsYqLT4eO3NzcCy+8CluP5urGf6xukM/G+QX6WxUU4Kdgu03BAX4Ksfsp2O6nkEA/hTfzV3gzf4UF+is00E8tggPUPCig7DnYX82DArj9GgC8iKnhJjMzU06nU9HR0ZWWR0dHa8eOHVVuk56eXmX79PT0KtvPnDlTM2bMqJ+Cq2G1WBToX/UfSIsqjy5b1WCzFvc6y1nLKl5U2cZSebnF/fmWSuvLni1nvC9/Xb7cajm9vSxl+2Mtf65YbrOeblexzmq1yGaxyGote28rf2+zlj2sVov8rRbZrFb5Vby3WeRntcrfVtbGz2aV3a/svb/NWvbeZlWAX9nDXv4c6G9ToJ9Ngf7lr/1tCgqwqZm/jWkJAABupve5aWhTp06tdKYnNzdXcXFx9f5z+sVFaMcTI+r9cwEAQO2YGm4iIyNls9mUkZFRaXlGRoZiYmKq3CYmJqZW7e12u+x2e/0UDAAAPJ6pHQ0CAgI0YMAALV261L3M5XJp6dKlSkpKqnKbpKSkSu0l6euvvz5newAA4FtMvyw1efJkjRs3TgMHDtSgQYM0Z84c5efna/z48ZKksWPHqk2bNpo5c6Yk6f7779fQoUP13HPP6dprr9UHH3ygdevW6dVXXzVzNwAAgIcwPdyMHj1ax48f17Rp05Senq5+/fpp0aJF7k7Dhw4dktV6+gTT4MGD9f777+vRRx/VI488oq5du+qzzz5jjBsAACDJA8a5aWwNNc4NAABoOLX5+83gHgAAwKsQbgAAgFch3AAAAK9CuAEAAF6FcAMAALwK4QYAAHgVwg0AAPAqhBsAAOBVCDcAAMCrmD79QmOrGJA5NzfX5EoAAEBNVfzdrsnECj4XbvLy8iRJcXFxJlcCAABqKy8vT+Hh4dW28bm5pVwul44eParQ0FBZLJZ6/ezc3FzFxcUpNTXVK+et8vb9k7x/H9m/ps/b95H9a/oaah8Nw1BeXp5iY2MrTahdFZ87c2O1WtW2bdsG/RlhYWFe+x+t5P37J3n/PrJ/TZ+37yP71/Q1xD6e74xNBToUAwAAr0K4AQAAXoVwU4/sdrumT58uu91udikNwtv3T/L+fWT/mj5v30f2r+nzhH30uQ7FAADAu3HmBgAAeBXCDQAA8CqEGwAA4FUINwAAwKsQbmrhySef1ODBgxUUFKSIiIgq2xw6dEjXXnutgoKCFBUVpT/96U8qLS2t9nOzsrJ06623KiwsTBEREZowYYJOnTrVAHtQOytWrJDFYqny8cMPP5xzu1/84hdntb/77rsbsfKa69Chw1m1zpo1q9ptioqKNGnSJLVs2VIhISH69a9/rYyMjEaquHYOHDigCRMmqGPHjmrWrJk6d+6s6dOny+FwVLudJx/DuXPnqkOHDgoMDFRiYqLWrl1bbfuPPvpI3bt3V2BgoPr06aOFCxc2UqW1N3PmTF188cUKDQ1VVFSUbrjhBu3cubPabd56662zjlVgYGAjVVw7f/nLX86qtXv37tVu05SOn1T17xSLxaJJkyZV2d7Tj9/KlSs1cuRIxcbGymKx6LPPPqu03jAMTZs2Ta1bt1azZs2UnJys3bt3n/dza/s9ri3CTS04HA7ddNNNuueee6pc73Q6de2118rhcGj16tV6++239dZbb2natGnVfu6tt96qrVu36uuvv9aXX36plStXauLEiQ2xC7UyePBgpaWlVXrceeed6tixowYOHFjttnfddVel7Z5++ulGqrr2Hn/88Uq13nfffdW2f/DBB/Xf//5XH330kb755hsdPXpUN954YyNVWzs7duyQy+XSK6+8oq1bt+r555/XvHnz9Mgjj5x3W088hvPnz9fkyZM1ffp0bdiwQQkJCRo+fLiOHTtWZfvVq1drzJgxmjBhgn788UfdcMMNuuGGG7Rly5ZGrrxmvvnmG02aNEnff/+9vv76a5WUlOiqq65Sfn5+tduFhYVVOlYHDx5spIprr1evXpVqXbVq1TnbNrXjJ0k//PBDpf37+uuvJUk33XTTObfx5OOXn5+vhIQEzZ07t8r1Tz/9tF544QXNmzdPa9asUXBwsIYPH66ioqJzfmZtv8d1YqDW3nzzTSM8PPys5QsXLjSsVquRnp7uXvbyyy8bYWFhRnFxcZWftW3bNkOS8cMPP7iX/e9//zMsFotx5MiReq/9QjgcDqNVq1bG448/Xm27oUOHGvfff3/jFHWB2rdvbzz//PM1bp+dnW34+/sbH330kXvZ9u3bDUlGSkpKA1RY/55++mmjY8eO1bbx1GM4aNAgY9KkSe73TqfTiI2NNWbOnFll+9/+9rfGtddeW2lZYmKi8fvf/75B66wvx44dMyQZ33zzzTnbnOv3kSeaPn26kZCQUOP2Tf34GYZh3H///Ubnzp0Nl8tV5fqmdPwkGf/5z3/c710ulxETE2M888wz7mXZ2dmG3W43/v3vf5/zc2r7Pa4LztzUo5SUFPXp00fR0dHuZcOHD1dubq62bt16zm0iIiIqnQlJTk6W1WrVmjVrGrzm2vjiiy904sQJjR8//rxt33vvPUVGRqp3796aOnWqCgoKGqHCupk1a5Zatmyp/v3765lnnqn2MuL69etVUlKi5ORk97Lu3burXbt2SklJaYxyL1hOTo5atGhx3naedgwdDofWr19f6d/earUqOTn5nP/2KSkpldpLZd/JpnSsJJ33eJ06dUrt27dXXFycrr/++nP+vvEEu3fvVmxsrDp16qRbb71Vhw4dOmfbpn78HA6H3n33Xd1xxx3VTtTclI7fmfbv36/09PRKxyg8PFyJiYnnPEZ1+R7Xhc9NnNmQ0tPTKwUbSe736enp59wmKiqq0jI/Pz+1aNHinNuY5fXXX9fw4cPPO/HoLbfcovbt2ys2NlabNm3Sww8/rJ07d+rTTz9tpEpr7o9//KMuuugitWjRQqtXr9bUqVOVlpam2bNnV9k+PT1dAQEBZ/W5io6O9rjjVZU9e/boxRdf1LPPPlttO088hpmZmXI6nVV+x3bs2FHlNuf6TjaFY+VyufTAAw/o0ksvVe/evc/ZLj4+Xm+88Yb69u2rnJwcPfvssxo8eLC2bt3a4JME11ZiYqLeeustxcfHKy0tTTNmzNDll1+uLVu2KDQ09Kz2Tfn4SdJnn32m7Oxs3X777eds05SO389VHIfaHKO6fI/rwufDzZQpU/S3v/2t2jbbt28/b6e3pqQu+3z48GEtXrxYH3744Xk//8z+Qn369FHr1q01bNgw7d27V507d6574TVUm/2bPHmye1nfvn0VEBCg3//+95o5c6ZHD49el2N45MgRXX311brpppt01113Vbut2ccQ0qRJk7Rly5Zq+6RIUlJSkpKSktzvBw8erB49euiVV17RE0880dBl1sqIESPcr/v27avExES1b99eH374oSZMmGBiZQ3j9ddf14gRIxQbG3vONk3p+DUlPh9uHnrooWpTtSR16tSpRp8VExNzVo/virtoYmJizrnNzztRlZaWKisr65zbXKi67PObb76pli1batSoUbX+eYmJiZLKzho0xh/GCzmmiYmJKi0t1YEDBxQfH3/W+piYGDkcDmVnZ1c6e5ORkdFgx6sqtd3Ho0eP6oorrtDgwYP16quv1vrnNfYxrEpkZKRsNttZd6ZV928fExNTq/ae4t5773XfXFDb/3v39/dX//79tWfPngaqrv5ERESoW7du56y1qR4/STp48KCWLFlS67OdTen4VRyHjIwMtW7d2r08IyND/fr1q3KbunyP66Teeu/4kPN1KM7IyHAve+WVV4ywsDCjqKioys+q6FC8bt0697LFixd7VIdil8tldOzY0XjooYfqtP2qVasMScZPP/1Uz5XVv3fffdewWq1GVlZWlesrOhR//PHH7mU7duzw6A7Fhw8fNrp27WrcfPPNRmlpaZ0+w1OO4aBBg4x7773X/d7pdBpt2rSptkPxddddV2lZUlKSx3ZIdblcxqRJk4zY2Fhj165ddfqM0tJSIz4+3njwwQfrubr6l5eXZzRv3tz4+9//XuX6pnb8zjR9+nQjJibGKCkpqdV2nnz8dI4Oxc8++6x7WU5OTo06FNfme1ynWuvtk3zAwYMHjR9//NGYMWOGERISYvz444/Gjz/+aOTl5RmGUfYfZe/evY2rrrrK2Lhxo7Fo0SKjVatWxtSpU92fsWbNGiM+Pt44fPiwe9nVV19t9O/f31izZo2xatUqo2vXrsaYMWMaff/OZcmSJYYkY/v27WetO3z4sBEfH2+sWbPGMAzD2LNnj/H4448b69atM/bv3298/vnnRqdOnYwhQ4Y0dtnntXr1auP55583Nm7caOzdu9d49913jVatWhljx451t/n5/hmGYdx9991Gu3btjGXLlhnr1q0zkpKSjKSkJDN24bwOHz5sdOnSxRg2bJhx+PBhIy0tzf04s01TOYYffPCBYbfbjbfeesvYtm2bMXHiRCMiIsJ9h+Jtt91mTJkyxd3+u+++M/z8/Ixnn33W2L59uzF9+nTD39/f2Lx5s1m7UK177rnHCA8PN1asWFHpWBUUFLjb/HwfZ8yYYSxevNjYu3evsX79euPmm282AgMDja1bt5qxC9V66KGHjBUrVhj79+83vvvuOyM5OdmIjIw0jh07ZhhG0z9+FZxOp9GuXTvj4YcfPmtdUzt+eXl57r91kozZs2cbP/74o3Hw4EHDMAxj1qxZRkREhPH5558bmzZtMq6//nqjY8eORmFhofszrrzySuPFF190vz/f97g+EG5qYdy4cYaksx7Lly93tzlw4IAxYsQIo1mzZkZkZKTx0EMPVUruy5cvNyQZ+/fvdy87ceKEMWbMGCMkJMQICwszxo8f7w5MnmDMmDHG4MGDq1y3f//+Sv8Ghw4dMoYMGWK0aNHCsNvtRpcuXYw//elPRk5OTiNWXDPr1683EhMTjfDwcCMwMNDo0aOH8dRTT1U6y/bz/TMMwygsLDT+8Ic/GM2bNzeCgoKMX/3qV5XCgid58803q/xv9syTtk3tGL744otGu3btjICAAGPQoEHG999/7143dOhQY9y4cZXaf/jhh0a3bt2MgIAAo1evXsaCBQsaueKaO9exevPNN91tfr6PDzzwgPvfIzo62rjmmmuMDRs2NH7xNTB69GijdevWRkBAgNGmTRtj9OjRxp49e9zrm/rxq7B48WJDkrFz586z1jW141fxN+vnj4p9cLlcxmOPPWZER0cbdrvdGDZs2Fn73b59e2P69OmVllX3Pa4PFsMwjPq7yAUAAGAuxrkBAABehXADAAC8CuEGAAB4FcINAADwKoQbAADgVQg3AADAqxBuAACAVyHcAAAAr0K4AQAAXoVwAwAAvArhBgAAeBXCDYAm7/jx44qJidFTTz3lXrZ69WoFBARo6dKlJlYGwAxMnAnAKyxcuFA33HCDVq9erfj4ePXr10/XX3+9Zs+ebXZpABoZ4QaA15g0aZKWLFmigQMHavPmzfrhhx9kt9vNLgtAIyPcAPAahYWF6t27t1JTU7V+/Xr16dPH7JIAmIA+NwC8xt69e3X06FG5XC4dOHDA7HIAmIQzNwC8gsPh0KBBg9SvXz/Fx8drzpw52rx5s6KioswuDUAjI9wA8Ap/+tOf9PHHH+unn35SSEiIhg4dqvDwcH355ZdmlwagkXFZCkCTt2LFCs2ZM0f/+te/FBYWJqvVqn/961/69ttv9fLLL5tdHoBGxpkbAADgVThzAwAAvArhBgAAeBXCDQAA8CqEGwAA4FUINwAAwKsQbgAAgFch3AAAAK9CuAEAAF6FcAMAALwK4QYAAHgVwg0AAPAq/x/DBOfe9DPvkQAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# draw up a regular sigmoid function\n", + "\n", + "# Import matplotlib, numpy and math \n", + "import matplotlib.pyplot as plt \n", + "import numpy as np \n", + "import math \n", + "\n", + "x = np.linspace(-10, 10, 100) \n", + "\n", + "def regu_logistic(x): \n", + " z = 1/(1 + np.exp(-x)) \n", + " return z\n", + "\n", + "plt.plot(x, z) \n", + "plt.xlabel(\"x\") \n", + "plt.ylabel(\"Sigmoid(X)\") \n", + "\n", + "plt.show() \n" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "f956853f-12a2-4973-b7de-9d54c1972fb2", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "afa9ec48-fc3a-42b1-a4b5-11b90f4d39d1", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(-2.5, 0.07585818002124355)\n" + ] + } + ], + "source": [ + "x0 = -2.5\n", + "y0 = regu_logistic(x=x0)\n", + "print(f'({x0}, {y0})')" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "id": "6fe4466a-4b27-4705-b0ff-d435a57ddd11", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "(2.5, 0.9241418199787566)\n" + ] + } + ], + "source": [ + "x0 = 2.5\n", + "y0 = regu_logistic(x=x0)\n", + "print(f'({x0}, {y0})')" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "061df87e-d1a0-4f75-889c-4d4a76d333dc", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[-2.5,2.5]" + ] + }, + "execution_count": 24, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "test_i = I(-2.5, 2.5)\n", + "test_i" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "d6c33165-f954-4e74-ac20-114594397625", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[0.07585818002124355,0.9241418199787566]" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "y_test_i = sigmoid(test_i)\n", + "y_test_i" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0f17d3f8-39e0-408f-9a72-b189e86c22d2", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 27, + "id": "b856e442-7ec7-4b6c-81f7-c4437c9e1005", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "base vector with shape (3,)\n" + ] + }, + { + "data": { + "text/plain": [ + "[0.9,1.1]\n", + "[2.7,3.3000000000000003]\n", + "[4.5,5.5]" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "vec = create_interval(matrix=np.array([1, 3, 5]))\n", + "print(\"base vector with shape\", vec.shape)\n", + "vec" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "5c735ddc-5896-4926-9adf-6a1072936e1d", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0.7109495026250039,0.7502601055951177]\n", + "[0.9370266439430035,0.9644288107273639]\n", + "[0.9890130573694068,0.995929862284104]\n" + ] + } + ], + "source": [ + "print(sigmoid(vec))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9fcdd40c-e078-4da2-b20f-4dec852ec8aa", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f78d252b-3a50-4ecf-9997-2ae3076bd44b", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7e90f111-71e3-498c-8315-29232eecdcfb", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a83d3079-122f-4025-9fdd-d5a563354c83", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "18307e47-7967-4ad6-9178-d667e3590eb3", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAhYAAAGdCAYAAABO2DpVAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAAAWeElEQVR4nO3df2zcdf3A8Ve30Svb2srEje3bwlDiEHBDFlgKQQYMFiSEhRjRr8EFMQophGWJuv3jQvyjGI18iSxIQJlRyRBwkKAwcbBNEQJ0WxxIiOCCRfZDEtNunSmk/Xz/aFYtrKPXvdrrrY9Hcll7fV/vtXc+uT7zueu1piiKIgAAEkyq9AAAwLFDWAAAaYQFAJBGWAAAaYQFAJBGWAAAaYQFAJBGWAAAaaaM9R329fXF22+/HfX19VFTUzPWdw8AjEBRFLF///6YM2dOTJo09HmJMQ+Lt99+O5qbm8f6bgGABB0dHdHU1DTk18c8LOrr6yOif7CGhoaxvnsAYAS6urqiubl54Of4UMY8LA49/dHQ0CAsAKDKfNjLGLx4EwBIIywAgDTCAgBIIywAgDTCAgBIIywAgDTCAgBIIywAgDTCAgBIIywAgDTCAgBIM+Z/KwQAyFcUEQcP9n88dWrEh/xJj1HjjAUAHAMOHoyYPr3/cigwKkFYAABphAUAkEZYAABphAUAkEZYAABphAUAkEZYAABphAUAkEZYAABphAUAkEZYAABphAUAkEZYAABphAUAkEZYAABphAUAkEZYAABphAUAkEZYAABphAUAkEZYAABphAUAkEZYAABphAUAkEZYAABphAUAkEZYAABphAUAkEZYAABphAUAkEZYAABphAUAkEZYAABphAUAkOaowuL222+PmpqaWLFiRdI4AEA1G3FYvPjii3HPPffE/PnzM+cBAKrYiMLiwIED8eUvfznuvffeOOGEE7JnAgCq1IjCorW1Na688spYsmTJh67t6emJrq6uQRcA4Ng0pdwbrF+/PrZt2xYvvvjisNa3tbXFbbfdVvZgAED1KeuMRUdHR9x6663xy1/+Murq6oZ1m9WrV0dnZ+fApaOjY0SDAgDjX1lnLNrb22Pfvn1xzjnnDFzX29sbW7dujbvuuit6enpi8uTJg25TKpWiVCrlTAsAjGtlhcWll14aO3fuHHTd9ddfH6effnp8+9vf/kBUAAATS1lhUV9fH2edddag66ZNmxYf/ehHP3A9ADDxeOdNACBN2b8V8n6bN29OGAMAOBY4YwEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApBEWAEAaYQEApCkrLO6+++6YP39+NDQ0RENDQ7S0tMQTTzwxWrMBAFWmrLBoamqK22+/Pdrb2+Oll16KSy65JK6++up45ZVXRms+AKCK1BRFURzNN5gxY0Z8//vfjxtuuGFY67u6uqKxsTE6OzujoaHhaO4aoCoVRcTBg/0fT50aUVNT2Xk4NnR3R0yf3v/xgQMR06blfv/h/vyeMtI76O3tjYceeii6u7ujpaVlyHU9PT3R09MzaDCAiezgwdH9AQCVVPaLN3fu3BnTp0+PUqkUN954Y2zYsCHOOOOMIde3tbVFY2PjwKW5ufmoBgYAxq+ynwp599134+9//3t0dnbGww8/HPfdd19s2bJlyLg43BmL5uZmT4UAE9Zon7JmYqrap0Jqa2vjtNNOi4iIhQsXxosvvhh33nln3HPPPYddXyqVolQqlXs3AEAVOur3sejr6xt0RgIAmLjKOmOxevXquOKKK+Lkk0+O/fv3xwMPPBCbN2+OjRs3jtZ8AEAVKSss9u3bF1/5yldi9+7d0djYGPPnz4+NGzfGZZddNlrzAQBVpKyw+MlPfjJacwAAxwB/KwQASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0wgIASCMsAIA0ZYVFW1tbnHvuuVFfXx8zZ86MZcuWxWuvvTZaswEAVaassNiyZUu0trbG888/H0899VS89957cfnll0d3d/dozQcAVJEp5Sx+8sknB32+bt26mDlzZrS3t8dnP/vZ1MEAgOpTVli8X2dnZ0REzJgxY8g1PT090dPTM/B5V1fX0dwlADCOjfjFm319fbFixYq44IIL4qyzzhpyXVtbWzQ2Ng5cmpubR3qXAMA4N+KwaG1tjZdffjnWr19/xHWrV6+Ozs7OgUtHR8dI7xIAGOdG9FTIzTffHI8//nhs3bo1mpqajri2VCpFqVQa0XAAQHUpKyyKoohbbrklNmzYEJs3b45TTz11tOYCAKpQWWHR2toaDzzwQDz22GNRX18fe/bsiYiIxsbGOP7440dlQACgepT1Gou77747Ojs7Y/HixTF79uyBy4MPPjha8wEAVaTsp0IAAIbib4UAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQZkqlB4DxqigiDh7s/3jq1IiamsrOA1ANnLGAIRw8GDF9ev/lUGAAcGTCAgBI46kQADgGTJ0aceDAfz6uFGEBAMeAmpqIadMqPYWnQgCARMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgjLACANMICAEgjLACANGWHxdatW+Oqq66KOXPmRE1NTTz66KOjMBYAUI3KDovu7u5YsGBBrF27djTmAQCq2JRyb3DFFVfEFVdcMRqzAABVruywKFdPT0/09PQMfN7V1TXadwkAVMiov3izra0tGhsbBy7Nzc2jfZcAQIWMelisXr06Ojs7By4dHR2jfZcA49rUqREHDvRfpk6t9DSQa9SfCimVSlEqlUb7bgCqRk1NxLRplZ4CRof3sQAA0pR9xuLAgQPx+uuvD3y+a9eu2LFjR8yYMSNOPvnk1OEAgOpSdli89NJLcfHFFw98vnLlyoiIWL58eaxbty5tMACg+pQdFosXL46iKEZjFgCgynmNBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQRlgAAGmEBQCQZkqlB4DxaurUiAMH/vMxAB9OWMAQamoipk2r9BQA1cVTIQBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAGmEBAKQRFgBAmimVHiBDb2/EH/4QsXt3xOzZERdeGDF5cqWnAoCJZ0RnLNauXRtz586Nurq6WLRoUbzwwgvZcw3br38dMXduxMUXR/zv//b/O3du//UAwNgqOywefPDBWLlyZaxZsya2bdsWCxYsiKVLl8a+fftGY74j+vWvIz7/+Yi33hp8/T/+0X+9uACAsVVTFEVRzg0WLVoU5557btx1110REdHX1xfNzc1xyy23xKpVqz709l1dXdHY2BidnZ3R0NAwsqmj/+mPuXM/GBWH1NRENDVF7NrlaREAOFrD/fld1hmLd999N9rb22PJkiX/+QaTJsWSJUviueeeO+xtenp6oqura9Alwx/+MHRUREQURURHR/86AGBslBUW77zzTvT29sasWbMGXT9r1qzYs2fPYW/T1tYWjY2NA5fm5uaRT/tfdu/OXQcAHL1R/3XT1atXR2dn58Clo6Mj5fvOnp27DgA4emX9uumJJ54YkydPjr179w66fu/evXHSSScd9jalUilKpdLIJxzChRf2v4biH//of9rj/Q69xuLCC9PvGgAYQllnLGpra2PhwoWxadOmgev6+vpi06ZN0dLSkj7ckUyeHHHnnf0f19QM/tqhz//v/7xwEwDGUtlPhaxcuTLuvffe+NnPfhavvvpq3HTTTdHd3R3XX3/9aMx3RNdcE/HwwxH/8z+Dr29q6r/+mmvGfCQAmNDKfufNa6+9Nv75z3/Gd77zndizZ0+cffbZ8eSTT37gBZ1j5ZprIq6+2jtvAsB4UPb7WBytrPexAADGzqi8jwUAwJEICwAgjbAAANIICwAgjbAAANIICwAgjbAAANIICwAgjbAAANKU/ZbeR+vQG312dXWN9V0DACN06Of2h71h95iHxf79+yMiorm5eazvGgA4Svv374/GxsYhvz7mfyukr68v3n777aivr4+a9/+986PQ1dUVzc3N0dHR4W+QfAh7NXz2qjz2a/js1fDZq+Ebzb0qiiL2798fc+bMiUmThn4lxZifsZg0aVI0NTWN2vdvaGhw4A2TvRo+e1Ue+zV89mr47NXwjdZeHelMxSFevAkApBEWAECaYyYsSqVSrFmzJkqlUqVHGffs1fDZq/LYr+GzV8Nnr4ZvPOzVmL94EwA4dh0zZywAgMoTFgBAGmEBAKQRFgBAmqoKi7Vr18bcuXOjrq4uFi1aFC+88MIR1z/00ENx+umnR11dXXz605+O3/72t2M0aeWVs1fr1q2LmpqaQZe6uroxnLZytm7dGldddVXMmTMnampq4tFHH/3Q22zevDnOOeecKJVKcdppp8W6detGfc7xoNy92rx58weOq5qamtizZ8/YDFxBbW1tce6550Z9fX3MnDkzli1bFq+99tqH3m4iPmaNZK8m6mPW3XffHfPnzx9486uWlpZ44oknjnibShxTVRMWDz74YKxcuTLWrFkT27ZtiwULFsTSpUtj3759h13/pz/9Kb70pS/FDTfcENu3b49ly5bFsmXL4uWXXx7jycdeuXsV0f8ubbt37x64vPnmm2M4ceV0d3fHggULYu3atcNav2vXrrjyyivj4osvjh07dsSKFSvia1/7WmzcuHGUJ628cvfqkNdee23QsTVz5sxRmnD82LJlS7S2tsbzzz8fTz31VLz33ntx+eWXR3d395C3maiPWSPZq4iJ+ZjV1NQUt99+e7S3t8dLL70Ul1xySVx99dXxyiuvHHZ9xY6pokqcd955RWtr68Dnvb29xZw5c4q2trbDrv/CF75QXHnllYOuW7RoUfGNb3xjVOccD8rdq/vvv79obGwco+nGr4goNmzYcMQ13/rWt4ozzzxz0HXXXnttsXTp0lGcbPwZzl4988wzRUQU//rXv8ZkpvFs3759RUQUW7ZsGXLNRH7M+m/D2SuPWf9xwgknFPfdd99hv1apY6oqzli8++670d7eHkuWLBm4btKkSbFkyZJ47rnnDnub5557btD6iIilS5cOuf5YMZK9iog4cOBAnHLKKdHc3HzEAp7oJupxdTTOPvvsmD17dlx22WXx7LPPVnqciujs7IyIiBkzZgy5xrHVbzh7FeExq7e3N9avXx/d3d3R0tJy2DWVOqaqIizeeeed6O3tjVmzZg26ftasWUM+X7tnz56y1h8rRrJX8+bNi5/+9Kfx2GOPxS9+8Yvo6+uL888/P956662xGLmqDHVcdXV1xb///e8KTTU+zZ49O3784x/HI488Eo888kg0NzfH4sWLY9u2bZUebUz19fXFihUr4oILLoizzjpryHUT9THrvw13rybyY9bOnTtj+vTpUSqV4sYbb4wNGzbEGWeccdi1lTqmxvyvmzL+tLS0DCre888/Pz71qU/FPffcE9/97ncrOBnVbN68eTFv3ryBz88///x444034o477oif//znFZxsbLW2tsbLL78cf/zjHys9yrg33L2ayI9Z8+bNix07dkRnZ2c8/PDDsXz58tiyZcuQcVEJVXHG4sQTT4zJkyfH3r17B12/d+/eOOmkkw57m5NOOqms9ceKkezV+x133HHxmc98Jl5//fXRGLGqDXVcNTQ0xPHHH1+hqarHeeedN6GOq5tvvjkef/zxeOaZZ6KpqemIayfqY9Yh5ezV+02kx6za2to47bTTYuHChdHW1hYLFiyIO++887BrK3VMVUVY1NbWxsKFC2PTpk0D1/X19cWmTZuGfG6ppaVl0PqIiKeeemrI9ceKkezV+/X29sbOnTtj9uzZozVm1Zqox1WWHTt2TIjjqiiKuPnmm2PDhg3x9NNPx6mnnvqht5mox9ZI9ur9JvJjVl9fX/T09Bz2axU7pkb1paGJ1q9fX5RKpWLdunXFX/7yl+LrX/968ZGPfKTYs2dPURRFcd111xWrVq0aWP/ss88WU6ZMKX7wgx8Ur776arFmzZriuOOOK3bu3Fmp/8KYKXevbrvttmLjxo3FG2+8UbS3txdf/OIXi7q6uuKVV16p1H9hzOzfv7/Yvn17sX379iIiih/+8IfF9u3bizfffLMoiqJYtWpVcd111w2s/9vf/lZMnTq1+OY3v1m8+uqrxdq1a4vJkycXTz75ZKX+C2Om3L264447ikcffbT461//WuzcubO49dZbi0mTJhW///3vK/VfGDM33XRT0djYWGzevLnYvXv3wOXgwYMDazxm9RvJXk3Ux6xVq1YVW7ZsKXbt2lX8+c9/LlatWlXU1NQUv/vd74qiGD/HVNWERVEUxY9+9KPi5JNPLmpra4vzzjuveP755we+dtFFFxXLly8ftP5Xv/pV8clPfrKora0tzjzzzOI3v/nNGE9cOeXs1YoVKwbWzpo1q/jc5z5XbNu2rQJTj71DvxL5/suh/Vm+fHlx0UUXfeA2Z599dlFbW1t8/OMfL+6///4xn7sSyt2r733ve8UnPvGJoq6urpgxY0axePHi4umnn67M8GPscPsUEYOOFY9Z/UayVxP1MeurX/1qccoppxS1tbXFxz72seLSSy8diIqiGD/HlD+bDgCkqYrXWAAA1UFYAABphAUAkEZYAABphAUAkEZYAABphAUAkEZYAABphAUAkEZYAABphAUAkEZYAABp/h9M/2u+nRF6fgAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# plot a vector interval\n", + "_ = plot_intervals(x, y_i)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "7ad57e12-fcd2-4279-bd3e-7864dd355870", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAiwAAAGdCAYAAAAxCSikAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAAAufUlEQVR4nO3de3QUZZ7/8U8ToBND0hAlNwkQBcGR6yDEgBccI4FhkczOKrCOAQ94YYMrg4waV2B2dA2i422HAS9AZDwQZRXYRQQxkCAaYIhkFVAWMApIOipOukkj4ZLn9wc/emwTIB1yedK+X+fUOd1V36p+vlR3+kN1dbXDGGMEAABgsVbNPQAAAIDzIbAAAADrEVgAAID1CCwAAMB6BBYAAGA9AgsAALAegQUAAFiPwAIAAKzXurkH0BCqq6t16NAhRUVFyeFwNPdwAABAHRhjdOTIESUmJqpVq3MfQwmJwHLo0CElJSU19zAAAEA9HDhwQJ06dTpnTUgElqioKEmnG46Ojm7m0QAAgLrwer1KSkryv4+fS0gEljMfA0VHRxNYAABoYepyOgcn3QIAAOsRWAAAgPUILAAAwHoEFgAAYD0CCwAAsB6BBQAAWI/AAgAArEdgAQAA1iOwAAAA6wUVWObNm6c+ffr4ryibmpqqd95555zrLFu2TD179lR4eLh69+6t1atXByw3xmjmzJlKSEhQRESE0tLStGfPnuA7AQAAISuowNKpUyfNnj1bxcXF2rZtm37xi19o9OjR2rlzZ631H374ocaNG6eJEydq+/btysjIUEZGhnbs2OGvmTNnjl544QXNnz9fW7ZsUWRkpNLT03Xs2LEL6wwAAIQMhzHGXMgGYmJi9NRTT2nixIk1lo0ZM0Y+n0+rVq3yz7vmmmvUr18/zZ8/X8YYJSYm6oEHHtD06dMlSR6PR3FxccrNzdXYsWPrNAav1yuXyyWPx8NvCQEhxBjp6NHTty+6SKrDz40AaEGCef+u9zksp06dUl5ennw+n1JTU2utKSoqUlpaWsC89PR0FRUVSZJKS0vldrsDalwul1JSUvw1tamqqpLX6w2YAISeo0eldu1OT2eCC4CfpqADyyeffKJ27drJ6XTq3nvv1fLly/Wzn/2s1lq32624uLiAeXFxcXK73f7lZ+adraY2OTk5crlc/ikpKSnYNgAAQAsSdGDp0aOHSkpKtGXLFk2ePFnjx4/Xrl27GmNsZ5WdnS2Px+OfDhw40KSPDwAAmlbrYFdo27atunXrJkkaMGCA/vrXv+r555/Xiy++WKM2Pj5e5eXlAfPKy8sVHx/vX35mXkJCQkBNv379zjoGp9Mpp9MZ7NABAEALdcHXYamurlZVVVWty1JTU5Wfnx8wb926df5zXpKTkxUfHx9Q4/V6tWXLlrOeFwMAAH56gjrCkp2drREjRqhz5846cuSIlixZooKCAq1du1aSlJmZqUsvvVQ5OTmSpPvvv1833HCD/vjHP2rkyJHKy8vTtm3b9NJLL0mSHA6Hpk6dqscff1zdu3dXcnKyZsyYocTERGVkZDRspwAAoMUKKrB8/fXXyszMVFlZmVwul/r06aO1a9fq5ptvliTt379frVr9/aDN4MGDtWTJEj366KN65JFH1L17d61YsUK9evXy1zz44IPy+Xy6++67VVFRoWuvvVZr1qxReHh4A7UIAABaugu+DosNuA4LEJp8vtNfaZakykopMrJ5xwOgYTXJdVgAAACaCoEFAABYj8ACAACsR2ABAADWI7AAAADrEVgAAID1CCwAAMB6BBYAAGA9AgsAALAegQUAAFiPwAIAAKxHYAEAANYjsAAAAOsRWAAAgPUILAAAwHoEFgAAYD0CCwAAsB6BBQAAWI/AAgAArEdgAQAA1iOwAAAA6xFYAACA9QgsAADAegQWAABgPQILAACwHoEFAABYj8ACAACsR2ABAADWI7AAAADrEVgAAID1CCwAAMB6QQWWnJwcDRw4UFFRUYqNjVVGRoZ27959znWGDh0qh8NRYxo5cqS/ZsKECTWWDx8+vH4dAQCAkNM6mOLCwkJlZWVp4MCBOnnypB555BENGzZMu3btUmRkZK3rvPXWWzp+/Lj//uHDh9W3b1/deuutAXXDhw/XokWL/PedTmcwQwMAACEsqMCyZs2agPu5ubmKjY1VcXGxrr/++lrXiYmJCbifl5eniy66qEZgcTqdio+PD2Y4AADgJ+KCzmHxeDySaoaSc1mwYIHGjh1b44hMQUGBYmNj1aNHD02ePFmHDx8+6zaqqqrk9XoDJgAAELrqHViqq6s1depUDRkyRL169arTOlu3btWOHTs0adKkgPnDhw/X4sWLlZ+fryeffFKFhYUaMWKETp06Vet2cnJy5HK5/FNSUlJ92wAAAC2Awxhj6rPi5MmT9c4772jTpk3q1KlTnda55557VFRUpI8//vicdZ9//rkuv/xyvffee7rppptqLK+qqlJVVZX/vtfrVVJSkjwej6Kjo4NrBIC1fD6pXbvTtysrpbOcKgeghfJ6vXK5XHV6/67XEZYpU6Zo1apV2rBhQ53Dis/nU15eniZOnHje2ssuu0yXXHKJ9u7dW+typ9Op6OjogAkAAISuoE66Ncbovvvu0/Lly1VQUKDk5OQ6r7ts2TJVVVXpN7/5zXlrDx48qMOHDyshISGY4QEAgBAV1BGWrKwsvfbaa1qyZImioqLkdrvldrv1/fff+2syMzOVnZ1dY90FCxYoIyNDF198ccD8yspK/e53v9PmzZv1xRdfKD8/X6NHj1a3bt2Unp5ez7YAAEAoCeoIy7x58ySdvhjcDy1atEgTJkyQJO3fv1+tWgXmoN27d2vTpk169913a2wzLCxMH3/8sV599VVVVFQoMTFRw4YN02OPPca1WAAAgKQLOOnWJsGctAOg5eCkWyC0NfpJtwAAAE2JwAIAAKxHYAEAANYjsAAAAOsRWAAAgPUILAAAwHoEFgAAYD0CCwAAsB6BBQAAWI/AAgAArEdgAQAA1iOwAAAA6xFYAACA9QgsAADAegQWAABgPQILAACwHoEFAABYj8ACAACsR2ABAADWI7AAAADrEVgAAID1CCwAAMB6BBYAAGA9AgsAALAegQUAAFiPwAIAAKxHYAEAANYjsAAAAOsRWAAAgPUILAAAwHoEFgAAYL2gAktOTo4GDhyoqKgoxcbGKiMjQ7t37z7nOrm5uXI4HAFTeHh4QI0xRjNnzlRCQoIiIiKUlpamPXv2BN8NAAAISUEFlsLCQmVlZWnz5s1at26dTpw4oWHDhsnn851zvejoaJWVlfmnL7/8MmD5nDlz9MILL2j+/PnasmWLIiMjlZ6ermPHjgXfEQAACDmtgyles2ZNwP3c3FzFxsaquLhY119//VnXczgcio+Pr3WZMUbPPfecHn30UY0ePVqStHjxYsXFxWnFihUaO3ZsMEMEAAAh6ILOYfF4PJKkmJiYc9ZVVlaqS5cuSkpK0ujRo7Vz507/stLSUrndbqWlpfnnuVwupaSkqKioqNbtVVVVyev1BkwAACB01TuwVFdXa+rUqRoyZIh69ep11roePXpo4cKFWrlypV577TVVV1dr8ODBOnjwoCTJ7XZLkuLi4gLWi4uL8y/7sZycHLlcLv+UlJRU3zYAAEALUO/AkpWVpR07digvL++cdampqcrMzFS/fv10ww036K233lLHjh314osv1vehlZ2dLY/H458OHDhQ720BAAD7BXUOyxlTpkzRqlWrtHHjRnXq1Cmoddu0aaP+/ftr7969kuQ/t6W8vFwJCQn+uvLycvXr16/WbTidTjmdzvoMHQAAtEBBHWExxmjKlClavny51q9fr+Tk5KAf8NSpU/rkk0/84SQ5OVnx8fHKz8/313i9Xm3ZskWpqalBbx8AAISeoI6wZGVlacmSJVq5cqWioqL855i4XC5FRERIkjIzM3XppZcqJydHkvSHP/xB11xzjbp166aKigo99dRT+vLLLzVp0iRJp79BNHXqVD3++OPq3r27kpOTNWPGDCUmJiojI6MBWwUAAC1VUIFl3rx5kqShQ4cGzF+0aJEmTJggSdq/f79atfr7gZu//e1vuuuuu+R2u9WhQwcNGDBAH374oX72s5/5ax588EH5fD7dfffdqqio0LXXXqs1a9bUuMAcAAD4aXIYY0xzD+JCeb1euVwueTweRUdHN/dwADQQn09q1+707cpKKTKyeccDoGEF8/7NbwkBAADrEVgAAID1CCwAAMB6BBYAAGA9AgsAALAegQUAAFiPwAIAAKxHYAEAANYjsAAAAOsRWAAAgPUILAAAwHoEFgAAYD0CCwAAsB6BBQAAWI/AAgAArEdgAQAA1iOwAAAA6xFYAACA9QgsAADAegQWAABgPQILAACwHoEFAABYj8ACAACsR2ABAADWI7AAAADrEVgAAID1CCwAAMB6BBYAAGA9AgsAALAegQUAAFiPwAIAAKwXVGDJycnRwIEDFRUVpdjYWGVkZGj37t3nXOfll1/Wddddpw4dOqhDhw5KS0vT1q1bA2omTJggh8MRMA0fPjz4bgAAQEgKKrAUFhYqKytLmzdv1rp163TixAkNGzZMPp/vrOsUFBRo3Lhx2rBhg4qKipSUlKRhw4bpq6++CqgbPny4ysrK/NPSpUvr1xEAAAg5DmOMqe/K33zzjWJjY1VYWKjrr7++TuucOnVKHTp00J/+9CdlZmZKOn2EpaKiQitWrKjXOLxer1wulzwej6Kjo+u1DQD28fmkdu1O366slCIjm3c8ABpWMO/fF3QOi8fjkSTFxMTUeZ2jR4/qxIkTNdYpKChQbGysevToocmTJ+vw4cNn3UZVVZW8Xm/ABAAAQle9A0t1dbWmTp2qIUOGqFevXnVe76GHHlJiYqLS0tL884YPH67FixcrPz9fTz75pAoLCzVixAidOnWq1m3k5OTI5XL5p6SkpPq2AQAAWoB6fyQ0efJkvfPOO9q0aZM6depUp3Vmz56tOXPmqKCgQH369Dlr3eeff67LL79c7733nm666aYay6uqqlRVVeW/7/V6lZSUxEdCQIjhIyEgtDX6R0JTpkzRqlWrtGHDhjqHlaefflqzZ8/Wu+++e86wIkmXXXaZLrnkEu3du7fW5U6nU9HR0QETAAAIXa2DKTbG6L777tPy5ctVUFCg5OTkOq03Z84c/cd//IfWrl2rq6+++rz1Bw8e1OHDh5WQkBDM8AAAQIgK6ghLVlaWXnvtNS1ZskRRUVFyu91yu936/vvv/TWZmZnKzs7233/yySc1Y8YMLVy4UF27dvWvU1lZKUmqrKzU7373O23evFlffPGF8vPzNXr0aHXr1k3p6ekN1CYAAGjJggos8+bNk8fj0dChQ5WQkOCfXn/9dX/N/v37VVZWFrDO8ePH9U//9E8B6zz99NOSpLCwMH388ce65ZZbdMUVV2jixIkaMGCA3n//fTmdzgZqEwAAtGQXdB0WW3AdFiA0cdItENqa7DosAAAATYHAAgAArEdgAQAA1iOwAAAA6xFYAACA9QgsAADAegQWAABgPQILAACwHoEFAABYj8ACAACsR2ABAADWI7AAAADrEVgAAID1CCwAAMB6BBYAAGA9AgsAALAegQUAAFiPwAIAAKxHYAEAANYjsAAAAOsRWAAAgPUILAAAwHoEFgAAYD0CCwAAsB6BBQAAWI/AAgAArEdgAQAA1iOwAAAA6xFYAACA9QgsAADAegQWAABgvaACS05OjgYOHKioqCjFxsYqIyNDu3fvPu96y5YtU8+ePRUeHq7evXtr9erVAcuNMZo5c6YSEhIUERGhtLQ07dmzJ7hOAABAyAoqsBQWFiorK0ubN2/WunXrdOLECQ0bNkw+n++s63z44YcaN26cJk6cqO3btysjI0MZGRnasWOHv2bOnDl64YUXNH/+fG3ZskWRkZFKT0/XsWPH6t8ZAAAIGQ5jjKnvyt98841iY2NVWFio66+/vtaaMWPGyOfzadWqVf5511xzjfr166f58+fLGKPExEQ98MADmj59uiTJ4/EoLi5Oubm5Gjt27HnH4fV65XK55PF4FB0dXd92AFjG55PatTt9u7JSioxs3vEAaFjBvH9f0DksHo9HkhQTE3PWmqKiIqWlpQXMS09PV1FRkSSptLRUbrc7oMblciklJcVf82NVVVXyer0BEwAACF31DizV1dWaOnWqhgwZol69ep21zu12Ky4uLmBeXFyc3G63f/mZeWer+bGcnBy5XC7/lJSUVN82AABAC1DvwJKVlaUdO3YoLy+vIcdTJ9nZ2fJ4PP7pwIEDTT4GAADQdFrXZ6UpU6Zo1apV2rhxozp16nTO2vj4eJWXlwfMKy8vV3x8vH/5mXkJCQkBNf369at1m06nU06nsz5DBwAALVBQR1iMMZoyZYqWL1+u9evXKzk5+bzrpKamKj8/P2DeunXrlJqaKklKTk5WfHx8QI3X69WWLVv8NQAA4KctqCMsWVlZWrJkiVauXKmoqCj/OSYul0sRERGSpMzMTF166aXKycmRJN1///264YYb9Mc//lEjR45UXl6etm3bppdeekmS5HA4NHXqVD3++OPq3r27kpOTNWPGDCUmJiojI6MBWwUAAC1VUIFl3rx5kqShQ4cGzF+0aJEmTJggSdq/f79atfr7gZvBgwdryZIlevTRR/XII4+oe/fuWrFiRcCJug8++KB8Pp/uvvtuVVRU6Nprr9WaNWsUHh5ez7YAAEAouaDrsNiC67AAoYnrsAChrcmuwwIAANAUCCwAAMB6BBYAAGA9AgsAALAegQUAAFiPwAIAAKxHYAEAANYjsAAAAOsRWAAAgPUILAAAwHoEFgAAYD0CCwAAsB6BBQAAWI/AAgAArEdgAQAA1iOwAAAA6xFYAACA9QgsAADAegQWAABgPQILAACwHoEFAABYj8ACAACsR2ABAADWI7AAAADrEVgAAID1CCwAAMB6BBYAAGA9AgsAALAegQUAAFiPwAIAAKxHYAEAANYLOrBs3LhRo0aNUmJiohwOh1asWHHO+gkTJsjhcNSYrrrqKn/N73//+xrLe/bsGXQzAAAgNAUdWHw+n/r27au5c+fWqf75559XWVmZfzpw4IBiYmJ06623BtRdddVVAXWbNm0KdmgAACBEtQ52hREjRmjEiBF1rne5XHK5XP77K1as0N/+9jfdeeedgQNp3Vrx8fHBDgcAAPwENPk5LAsWLFBaWpq6dOkSMH/Pnj1KTEzUZZddpttvv1379+8/6zaqqqrk9XoDJgAAELqaNLAcOnRI77zzjiZNmhQwPyUlRbm5uVqzZo3mzZun0tJSXXfddTpy5Eit28nJyfEfuXG5XEpKSmqK4QMAgGbSpIHl1VdfVfv27ZWRkREwf8SIEbr11lvVp08fpaena/Xq1aqoqNAbb7xR63ays7Pl8Xj804EDB5pg9AAAoLkEfQ5LfRljtHDhQt1xxx1q27btOWvbt2+vK664Qnv37q11udPplNPpbIxhAgAACzXZEZbCwkLt3btXEydOPG9tZWWl9u3bp4SEhCYYGQAAsF3QgaWyslIlJSUqKSmRJJWWlqqkpMR/kmx2drYyMzNrrLdgwQKlpKSoV69eNZZNnz5dhYWF+uKLL/Thhx/qV7/6lcLCwjRu3LhghwcAAEJQ0B8Jbdu2TTfeeKP//rRp0yRJ48ePV25ursrKymp8w8fj8ejNN9/U888/X+s2Dx48qHHjxunw4cPq2LGjrr32Wm3evFkdO3YMdngAACAEOYwxprkHcaG8Xq9cLpc8Ho+io6ObezgAGojPJ7Vrd/p2ZaUUGdm84wHQsIJ5/+a3hAAAgPUILAAAwHoEFgAAYD0CCwAAsB6BBQAAWI/AAgAArEdgAQAA1iOwAAAA6xFYAACA9QgsAADAegQWAABgPQILAACwHoEFAABYj8ACAACsR2ABAADWI7AAAADrEVgAAID1CCwAAMB6BBYAAGA9AgsAALAegQUAAFiPwAIAAKxHYAEAANYjsAAAAOsRWAAAgPUILAAAwHoEFgAAYD0CCwAAsB6BBQAAWI/AAgAArEdgAQAA1gs6sGzcuFGjRo1SYmKiHA6HVqxYcc76goICORyOGpPb7Q6omzt3rrp27arw8HClpKRo69atwQ4NAACEqKADi8/nU9++fTV37tyg1tu9e7fKysr8U2xsrH/Z66+/rmnTpmnWrFn66KOP1LdvX6Wnp+vrr78OdngAACAEtQ52hREjRmjEiBFBP1BsbKzat29f67JnnnlGd911l+68805J0vz58/X2229r4cKFevjhh4N+LAAAEFqa7ByWfv36KSEhQTfffLM++OAD//zjx4+ruLhYaWlpfx9Uq1ZKS0tTUVFRrduqqqqS1+sNmAAAQOhq9MCSkJCg+fPn680339Sbb76ppKQkDR06VB999JEk6dtvv9WpU6cUFxcXsF5cXFyN81zOyMnJkcvl8k9JSUmN3QYAAGhGQX8kFKwePXqoR48e/vuDBw/Wvn379Oyzz+ovf/lLvbaZnZ2tadOm+e97vV5CCwAAIazRA0ttBg0apE2bNkmSLrnkEoWFham8vDygpry8XPHx8bWu73Q65XQ6G32cAADADs1yHZaSkhIlJCRIktq2basBAwYoPz/fv7y6ulr5+flKTU1tjuEBAADLBH2EpbKyUnv37vXfLy0tVUlJiWJiYtS5c2dlZ2frq6++0uLFiyVJzz33nJKTk3XVVVfp2LFjeuWVV7R+/Xq9++67/m1MmzZN48eP19VXX61Bgwbpueeek8/n839rCAAA/LQFHVi2bdumG2+80X//zLkk48ePV25ursrKyrR//37/8uPHj+uBBx7QV199pYsuukh9+vTRe++9F7CNMWPG6JtvvtHMmTPldrvVr18/rVmzpsaJuAAA4KfJYYwxzT2IC+X1euVyueTxeBQdHd3cwwHQQHw+qV2707crK6XIyOYdD4CGFcz7N78lBAAArEdgAQAA1iOwAAAA6xFYAACA9QgsAADAegQWAABgPQILAACwHoEFAABYj8ACAACsR2ABAADWI7AAAADrEVgAAID1CCwAAMB6BBYAAGA9AgsAALAegQUAAFiPwAIAAKxHYAEAANYjsAAAAOsRWAAAgPUILAAAwHoEFgAAYD0CCwAAsB6BBQAAWI/AAgAArEdgAQAA1iOwAAAA6xFYAACA9QgsAADAegQWAABgPQILAACwXtCBZePGjRo1apQSExPlcDi0YsWKc9a/9dZbuvnmm9WxY0dFR0crNTVVa9euDaj5/e9/L4fDETD17Nkz2KEBAIAQFXRg8fl86tu3r+bOnVun+o0bN+rmm2/W6tWrVVxcrBtvvFGjRo3S9u3bA+quuuoqlZWV+adNmzYFOzQAABCiWge7wogRIzRixIg61z/33HMB95944gmtXLlS//M//6P+/fv/fSCtWys+Pj7Y4QAAgJ+AJj+Hpbq6WkeOHFFMTEzA/D179igxMVGXXXaZbr/9du3fv/+s26iqqpLX6w2YAABA6GrywPL000+rsrJSt912m39eSkqKcnNztWbNGs2bN0+lpaW67rrrdOTIkVq3kZOTI5fL5Z+SkpKaavgAAKAZOIwxpt4rOxxavny5MjIy6lS/ZMkS3XXXXVq5cqXS0tLOWldRUaEuXbromWee0cSJE2ssr6qqUlVVlf++1+tVUlKSPB6PoqOjg+4DgJ18Pqldu9O3KyulyMjmHQ+AhuX1euVyuer0/h30OSz1lZeXp0mTJmnZsmXnDCuS1L59e11xxRXau3dvrcudTqecTmdjDBMAAFioST4SWrp0qe68804tXbpUI0eOPG99ZWWl9u3bp4SEhCYYHQAAsF3QR1gqKysDjnyUlpaqpKREMTEx6ty5s7Kzs/XVV19p8eLFkk5/DDR+/Hg9//zzSklJkdvtliRFRETI5XJJkqZPn65Ro0apS5cuOnTokGbNmqWwsDCNGzeuIXoEAAAtXNBHWLZt26b+/fv7v5I8bdo09e/fXzNnzpQklZWVBXzD56WXXtLJkyeVlZWlhIQE/3T//ff7aw4ePKhx48apR48euu2223TxxRdr8+bN6tix44X2BwAAQsAFnXRri2BO2gHQcnDSLRDagnn/5reEAACA9QgsAADAegQWAABgPQILAACwHoEFAABYj8ACAACsR2ABAADWI7AAAADrEVgAAID1CCwAAMB6BBYAAGA9AgsAALAegQUAAFiPwAIAAKxHYAEAANYjsAAAAOsRWAAAgPUILAAAwHoEFgAAYD0CCwAAsB6BBQAAWI/AAgAArEdgAQAA1iOwAAAA6xFYAACA9QgsAADAegQWAABgPQILAACwHoEFAABYj8ACAACsR2ABAADWCzqwbNy4UaNGjVJiYqIcDodWrFhx3nUKCgr085//XE6nU926dVNubm6Nmrlz56pr164KDw9XSkqKtm7dGuzQAABAiAo6sPh8PvXt21dz586tU31paalGjhypG2+8USUlJZo6daomTZqktWvX+mtef/11TZs2TbNmzdJHH32kvn37Kj09XV9//XWwwwMAACHIYYwx9V7Z4dDy5cuVkZFx1pqHHnpIb7/9tnbs2OGfN3bsWFVUVGjNmjWSpJSUFA0cOFB/+tOfJEnV1dVKSkrSfffdp4cffvi84/B6vXK5XPJ4PIqOjq5vOwAs4/NJ7dqdvl1ZKUVGNu94ADSsYN6/G/0clqKiIqWlpQXMS09PV1FRkSTp+PHjKi4uDqhp1aqV0tLS/DU/VlVVJa/XGzABAIDQ1eiBxe12Ky4uLmBeXFycvF6vvv/+e3377bc6depUrTVut7vWbebk5MjlcvmnpKSkRhs/AABofi3yW0LZ2dnyeDz+6cCBA809JACN4KKLTn8UVFl5+jaAn67Wjf0A8fHxKi8vD5hXXl6u6OhoRUREKCwsTGFhYbXWxMfH17pNp9Mpp9PZaGMGYAeHg/NWAJzW6EdYUlNTlZ+fHzBv3bp1Sk1NlSS1bdtWAwYMCKiprq5Wfn6+vwYAAPy0BR1YKisrVVJSopKSEkmnv7ZcUlKi/fv3Szr9cU1mZqa//t5779Xnn3+uBx98UJ999pn+/Oc/64033tBvf/tbf820adP08ssv69VXX9Wnn36qyZMny+fz6c4777zA9gAAQCgI+iOhbdu26cYbb/TfnzZtmiRp/Pjxys3NVVlZmT+8SFJycrLefvtt/fa3v9Xzzz+vTp066ZVXXlF6erq/ZsyYMfrmm280c+ZMud1u9evXT2vWrKlxIi4AAPhpuqDrsNiC67AAANDyWHUdFgAAgAtFYAEAANYjsAAAAOsRWAAAgPUILAAAwHoEFgAAYD0CCwAAsB6BBQAAWI/AAgAArNfov9bcFM5crNfr9TbzSAAAQF2ded+uy0X3QyKwHDlyRJKUlJTUzCMBAADBOnLkiFwu1zlrQuK3hKqrq3Xo0CFFRUXJ4XA06La9Xq+SkpJ04MCBkPydolDvTwr9Humv5Qv1HkO9Pyn0e2ys/owxOnLkiBITE9Wq1bnPUgmJIyytWrVSp06dGvUxoqOjQ/JJeEao9yeFfo/01/KFeo+h3p8U+j02Rn/nO7JyBifdAgAA6xFYAACA9Qgs5+F0OjVr1iw5nc7mHkqjCPX+pNDvkf5avlDvMdT7k0K/Rxv6C4mTbgEAQGjjCAsAALAegQUAAFiPwAIAAKxHYAEAANYL6cCyceNGjRo1SomJiXI4HFqxYsV515k7d66uvPJKRUREqEePHlq8eHGNmmXLlqlnz54KDw9X7969tXr16oDlxhjNnDlTCQkJioiIUFpamvbs2dNQbfk1Rn8vv/yyrrvuOnXo0EEdOnRQWlqatm7dGlAzYcIEORyOgGn48OEN2ZqkxukvNze3xtjDw8MDappq/0mN0+PQoUNr9OhwODRy5Eh/TVPtw5ycHA0cOFBRUVGKjY1VRkaGdu/efd71GuI19t133+n2229XdHS02rdvr4kTJ6qystL6/k6cOKGHHnpIvXv3VmRkpBITE5WZmalDhw4FbKNr16419uHs2bMbtL/G6lGq23Owpe5DSbW+Bh0Oh5566il/TVPsw/r0t3PnTv3617/2j++5556rtW7u3Lnq2rWrwsPDlZKSUuO94tixY8rKytLFF1+sdu3a6de//rXKy8vr34wJYatXrzb/9m//Zt566y0jySxfvvyc9X/+859NVFSUycvLM/v27TNLly417dq1M//93//tr/nggw9MWFiYmTNnjtm1a5d59NFHTZs2bcwnn3zir5k9e7ZxuVxmxYoV5n//93/NLbfcYpKTk833339vfX///M//bObOnWu2b99uPv30UzNhwgTjcrnMwYMH/TXjx483w4cPN2VlZf7pu+++a9DeGqu/RYsWmejo6ICxu93ugO001f5rrB4PHz4c0N+OHTtMWFiYWbRokb+mqfZhenq6WbRokdmxY4cpKSkxv/zlL03nzp1NZWXlWddpqNfY8OHDTd++fc3mzZvN+++/b7p162bGjRtnfX8VFRUmLS3NvP766+azzz4zRUVFZtCgQWbAgAEB2+nSpYv5wx/+ELAPz/W4NvVoTN2egy11HxpjAvoqKyszCxcuNA6Hw+zbt89f0xT7sD79bd261UyfPt0sXbrUxMfHm2effbZGTV5enmnbtq1ZuHCh2blzp7nrrrtM+/btTXl5ub/m3nvvNUlJSSY/P99s27bNXHPNNWbw4MH17iWkA8sP1eXNIDU11UyfPj1g3rRp08yQIUP892+77TYzcuTIgJqUlBRzzz33GGOMqa6uNvHx8eapp57yL6+oqDBOp9MsXbr0Ars4u4bq78dOnjxpoqKizKuvvuqfN378eDN69OgLGW7QGqq/RYsWGZfLddZtNNf+M6bx9uGzzz5roqKiAv5ANcc+NMaYr7/+2kgyhYWFZ61piNfYrl27jCTz17/+1V/zzjvvGIfDYb766quGbClAQ/RXm61btxpJ5ssvv/TP69KlS61vJI2toXo833Mw1Pbh6NGjzS9+8YuAec2xD+vS3w+dbYyDBg0yWVlZ/vunTp0yiYmJJicnxxhz+jXZpk0bs2zZMn/Np59+aiSZoqKieo09pD8SClZVVVWNjwciIiK0detWnThxQpJUVFSktLS0gJr09HQVFRVJkkpLS+V2uwNqXC6XUlJS/DXNpS79/djRo0d14sQJxcTEBMwvKChQbGysevToocmTJ+vw4cONNu66qmt/lZWV6tKli5KSkjR69Gjt3LnTv8zm/SfVbx8uWLBAY8eOVWRkZMD85tiHHo9Hkmo8n36oIV5jRUVFat++va6++mp/TVpamlq1aqUtW7Y0WD8/1hD9nW27DodD7du3D5g/e/ZsXXzxxerfv7+eeuopnTx5sv6Dr6OG7PFcz8FQ2ofl5eV6++23NXHixBrLmnof1qW/8zl+/LiKi4sD/g1atWqltLQ0/79BcXGxTpw4EVDTs2dPde7cud5/SwksP5Cenq5XXnlFxcXFMsZo27ZteuWVV3TixAl9++23kiS32624uLiA9eLi4uR2u/3Lz8w7W01zqUt/P/bQQw8pMTEx4Ek3fPhwLV68WPn5+XryySdVWFioESNG6NSpU03VSq3q0l+PHj20cOFCrVy5Uq+99pqqq6s1ePBgHTx4UJLd+08Kfh9u3bpVO3bs0KRJkwLmN8c+rK6u1tSpUzVkyBD16tXrrHUN8Rpzu92KjY0NWN66dWvFxMQ02n5sqP5+7NixY3rooYc0bty4gB+d+9d//Vfl5eVpw4YNuueee/TEE0/owQcfbJhmzqIhezzfczCU9uGrr76qqKgo/eM//mPA/Kbeh3Xt73y+/fZbnTp16ryvwbZt29YI2RfytzQkfq25ocyYMUNut1vXXHONjDGKi4vT+PHjNWfOnPP+7HVLEGx/s2fPVl5engoKCgL+Vz927Fj/7d69e6tPnz66/PLLVVBQoJtuuqlJeqlNXfpLTU1Vamqqf53Bgwfryiuv1IsvvqjHHnusuYZeZ8HuwwULFqh3794aNGhQwPzm2IdZWVnasWOHNm3a1Cjbb26N0d+JEyd02223yRijefPmBSybNm2a/3afPn3Utm1b3XPPPcrJyWm0y6c3ZI82/h1prOfowoULdfvtt9c4OtrU+7ClvwZb/rtwA4qIiNDChQt19OhRffHFF9q/f7+6du2qqKgodezYUZIUHx9f4yzn8vJyxcfH+5efmXe2muZSl/7OePrppzV79my9++676tOnzzm3e9lll+mSSy7R3r17G3P45xVMf2e0adNG/fv394/d5v0nBdejz+dTXl5erYehf6yx9+GUKVO0atUqbdiwQZ06dTpnbUO8xuLj4/X1118HLD958qS+++67RtmPDdnfGWfCypdffql169YFHF2pTUpKik6ePKkvvviiXj2cT2P0+EM/fg6Gwj6UpPfff1+7d++ucZSzNo25D4Pp73wuueQShYWFnfc1ePz4cVVUVJy1JlgEllq0adNGnTp1UlhYmPLy8vQP//APAf9Dz8/PD6hft26d/3/tycnJio+PD6jxer3asmVLwP/sm9O5+pOkOXPm6LHHHtOaNWsCPj8+m4MHD+rw4cNKSEhozGHX2fn6+6FTp07pk08+8Y+9Jew/qW49Llu2TFVVVfrNb35z3u011j40xmjKlClavny51q9fr+Tk5POu0xCvsdTUVFVUVKi4uNhfs379elVXVyslJaUhWpPUOP1Jfw8re/bs0XvvvaeLL774vNstKSlRq1atanyMcqEaq8cf+/FzsKXvwzMWLFigAQMGqG/fvufdbmPsw/r0dz5t27bVgAEDAv4NqqurlZ+f7/83GDBggNq0aRNQs3v3bu3fv7/+f0vrdapuC3HkyBGzfft2s337diPJPPPMM2b79u3+M+0ffvhhc8cdd/jrd+/ebf7yl7+Y//u//zNbtmwxY8aMMTExMaa0tNRf88EHH5jWrVubp59+2nz66adm1qxZtX7lsn379mblypXm448/NqNHj26Ur8U2Rn+zZ882bdu2Nf/1X/8V8FW7I0eO+B9z+vTppqioyJSWlpr33nvP/PznPzfdu3c3x44ds76/f//3fzdr1641+/btM8XFxWbs2LEmPDzc7Ny5M+DfoCn2X2P1eMa1115rxowZU+tjNtU+nDx5snG5XKagoCDg+XT06FF/zR133GEefvhh//2Geo0NHz7c9O/f32zZssVs2rTJdO/evcG/EtsY/R0/ftzccsstplOnTqakpCRgu1VVVcYYYz788EPz7LPPmpKSErNv3z7z2muvmY4dO5rMzMwG7a+xeqzrc7Cl7sMzPB6Pueiii8y8efNqPG5T7cP69FdVVeX/u5SQkGCmT59utm/fbvbs2eOvycvLM06n0+Tm5ppdu3aZu+++27Rv3z7gMhH33nuv6dy5s1m/fr3Ztm2bSU1NNampqfXuJaQDy4YNG4ykGtP48eONMae/VnfDDTf463ft2mX69etnIiIiTHR0tBk9erT57LPPamz3jTfeMFdccYVp27atueqqq8zbb78dsLy6utrMmDHDxMXFGafTaW666Saze/fuFtFfly5dat3mrFmzjDHGHD161AwbNsx07NjRtGnTxnTp0sXcddddNa5lYmt/U6dONZ07dzZt27Y1cXFx5pe//KX56KOPAmqaav81Vo/GGPPZZ58ZSebdd9+tsawp92FtvUkKuCbMDTfc4O/3jIZ4jR0+fNiMGzfOtGvXzkRHR5s777zTH7xt7q+0tPSs292wYYMxxpji4mKTkpJiXC6XCQ8PN1deeaV54oknGjxwNlaPdX0OttR9eMaLL75oIiIiTEVFRY1lTbUP69Pf2Z6DP/xbZIwx//mf/+n/ezpo0CCzefPmgOXff/+9+Zd/+RfToUMHc9FFF5lf/epXpqysrN69OP5/QwAAANbiHBYAAGA9AgsAALAegQUAAFiPwAIAAKxHYAEAANYjsAAAAOsRWAAAgPUILAAAwHoEFgAAYD0CCwAAsB6BBQAAWI/AAgAArPf/AHQlBelcujxTAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# plot scaler interval\n", + "plot_intervals(x[2], y_i[2])" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "transformer", + "language": "python", + "name": "transformer" + }, + "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.11.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/tests/intervals_to_pbox.ipynb b/tests/intervals_to_pbox.ipynb new file mode 100644 index 0000000..ec4d56b --- /dev/null +++ b/tests/intervals_to_pbox.ipynb @@ -0,0 +1,196 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "8f022430-dd8e-4ef8-8a87-d54da67b3367", + "metadata": {}, + "outputs": [], + "source": [ + "from intervals.number import Interval as I\n", + "from intervals.methods import *\n", + "from intervals.random import uniform_endpoints \n", + "from intervals.mat_features import *\n", + "from intervals.activation import sigmoid, tanh\n", + "from intervals.plotting import plot_intervals, plot_lower_bound\n", + "from intervals.methods import matmul\n", + "from intervals.activation import sigmoid, tanh" + ] + }, + { + "cell_type": "markdown", + "id": "ab4f2293-04c1-4171-b1ef-fd07234907bd", + "metadata": {}, + "source": [ + "# collect multiple intervals into a p-box" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "340af6c8-505c-436f-bc9d-e068cda8fe3f", + "metadata": {}, + "outputs": [], + "source": [ + "# p-box initialisation via the mixture method\n", + "n = 7\n", + "\n", + "weights = np.squeeze(np.random.dirichlet(np.ones(7),size=1))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "66c76340-db20-4c76-9516-f6b60cfbb254", + "metadata": {}, + "outputs": [], + "source": [ + "weights" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "065128f7-d1c5-47be-9959-22e4351f478c", + "metadata": {}, + "outputs": [], + "source": [ + "sum(weights)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f14e7aab-2922-4bc3-b1e0-9cc5c5b7f6e8", + "metadata": {}, + "outputs": [], + "source": [ + "data = np.random.uniform(low=0.0, high=1.0, size=(7,2))\n", + "data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0547b681-47d3-486c-92ec-1fc8bd9b9236", + "metadata": {}, + "outputs": [], + "source": [ + "data_sorted = np.sort(data, axis=1)\n", + "data_sorted" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a28c275b-c490-4e64-994c-a7839faa0e0f", + "metadata": {}, + "outputs": [], + "source": [ + "data_i = intervalise(data)\n", + "data_i" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c129db6c-3c49-47c9-bd9d-166c89b0fde4", + "metadata": {}, + "outputs": [], + "source": [ + "_ = plot_intervals(x=np.arange(len(data_i)), y_i = data_i)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "94dc3031-9229-4988-9098-d2a84cb4c0fd", + "metadata": {}, + "outputs": [], + "source": [ + "x = np.linspace(-0.5, 1.5, 1000)\n", + "\n", + "def indicator_func(x, data_interval):\n", + " \"\"\" take a loop over all the extreme points \n", + " \n", + " args:\n", + " x: array, support of the distribution\n", + " data_interval: interval array, \n", + " \"\"\"\n", + " \n", + " lb = []\n", + " ub = []\n", + " \n", + " l_vertice = [*data_interval.lo]\n", + " u_vertice = [*data_interval.hi]\n", + " # vertice_sets = [*data_i.lo] + [*data_i.hi]\n", + " \n", + " for i in x:\n", + " lb.append(sum([*data_interval.lo] <= i))\n", + " ub.append(sum([*data_interval.hi] <= i))\n", + " return lb, ub" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "df363a3f-06e3-44f5-81d0-a45473f00d14", + "metadata": {}, + "outputs": [], + "source": [ + "lb, ub = indicator_func(x, data_i)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4775e660-3f86-4a8d-94b7-9c32fd7ca357", + "metadata": {}, + "outputs": [], + "source": [ + "fig, ax = plt.subplots()\n", + "ax.plot(x, lb, label='lower bound')\n", + "ax.plot(x, ub, label='upper bound')\n", + "ax.set_title('the p-box')\n", + "ax.legend()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1a07b6ab-c26d-4188-8055-5e1a5c503ee7", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "81210e03-61ad-40bb-b023-f2a1533796bf", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/tests/matrix_multiplication_marco.ipynb b/tests/matrix_multiplication_marco.ipynb index 3f5b925..6d0a480 100644 --- a/tests/matrix_multiplication_marco.ipynb +++ b/tests/matrix_multiplication_marco.ipynb @@ -69,36 +69,68 @@ }, { "cell_type": "markdown", - "id": "bd29348b-91be-43b7-800b-741a918336b3", - "metadata": { - "tags": [] - }, + "id": "647b4ac5-080f-46e0-b60b-bd9fd6ca4b49", + "metadata": {}, "source": [ - "#### mat @ mat" + "### prepare the data of various specifications" ] }, { "cell_type": "code", "execution_count": 6, - "id": "4d151557-6451-4e1e-8bf9-2d57c4d7950d", + "id": "bf02e187-cbb6-4f9f-a9c7-c0be07bb0939", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[2.7,3.3000000000000003]" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# scalar\n", + "\n", + "x_scalar = 3\n", + "x_si = create_interval(matrix=x_scalar)\n", + "x_si" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "9bf9840d-3e19-479b-b7e4-2ad3252b006b", "metadata": {}, "outputs": [], "source": [ - "a = np.arange(9).reshape(3,3)" + "# row_vec = create_interval(matrix=np.array([1, 3, 5]))\n", + "# print(\"row vector\", row_vec.shape)\n", + "# row_vec" ] }, { "cell_type": "code", "execution_count": 8, - "id": "79da63ed-bd11-4117-8a7d-0826d873a200", + "id": "353d6976-9c74-41aa-92ba-71cdfd0700ec", "metadata": {}, "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "base vector with shape (3,)\n" + ] + }, { "data": { "text/plain": [ - "[0. 0.] [0.9 1.1] [1.8 2.2]\n", - "[2.7 3.3] [3.6 4.4] [4.5 5.5]\n", - "[5.4 6.6] [6.3 7.7] [7.2 8.8]" + "[0.9,1.1]\n", + "[2.7,3.3000000000000003]\n", + "[4.5,5.5]" ] }, "execution_count": 8, @@ -107,22 +139,30 @@ } ], "source": [ - "v1 = create_interval(matrix=a, half_width=0.1)\n", - "v1" + "# no-shape one-dimensional base vector\n", + "\n", + "vec = create_interval(matrix=np.array([1, 3, 5]))\n", + "print(\"base vector with shape\", vec.shape)\n", + "vec" ] }, { "cell_type": "code", "execution_count": 9, - "id": "aa4e3c4d-7163-4ad3-8f17-2ab8f5b8039e", + "id": "a92cd4bc-51c5-4ecf-962e-a9a73fbd6ee6", "metadata": {}, "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "row vector with shape: (1, 3)\n" + ] + }, { "data": { "text/plain": [ - "[12.15 18.15] [34.02 50.82] [55.89 83.49]\n", - "[14.58 21.78] [43.74 65.34] [ 72.9 108.9]\n", - "[17.01 25.41] [53.46 79.86] [ 89.91 134.31]" + "[0.9 1.1] [2.7 3.3] [4.5 5.5]" ] }, "execution_count": 9, @@ -131,153 +171,218 @@ } ], "source": [ - "mat_mul_test = intvl_matmul(v1, v1)\n", - "mat_mul_test" + "# row vector\n", + "\n", + "row_vec = create_interval(matrix=np.array([[1, 3, 5]]))\n", + "print(\"row vector with shape:\", row_vec.shape)\n", + "row_vec" ] }, { "cell_type": "code", - "execution_count": 14, - "id": "ec6c2d24-ec3f-460f-9937-fb0f375b22a7", + "execution_count": 10, + "id": "22a442bd-185a-49c7-9332-d5e9460e3c89", "metadata": {}, "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "col vector with shape: (3, 1)\n" + ] + }, { "data": { "text/plain": [ - "[12.15 18.15] [14.58 21.78] [17.01 25.41]\n", - "[34.02 50.82] [43.74 65.34] [53.46 79.86]\n", - "[55.89 83.49] [ 72.9 108.9] [ 89.91 134.31]" + "[0.9 1.1]\n", + "[2.7 3.3]\n", + "[4.5 5.5]" ] }, - "execution_count": 14, + "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "''' double check with Marco's version '''\n", + "# col vector\n", "\n", - "matmul(v1, v1)" + "col_vec = vec[:, np.newaxis]\n", + "print(\"col vector with shape:\", col_vec.shape)\n", + "col_vec" ] }, { "cell_type": "code", - "execution_count": 15, - "id": "c8760ce1-ae39-46d7-a44f-9df0cadebd72", + "execution_count": 11, + "id": "6a602ea9-5e2f-4ef7-8214-3cd5a3fa70a8", "metadata": {}, "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "matrix interval with shape: (3, 3)\n" + ] + }, { "data": { "text/plain": [ - "array([[ True, True, True],\n", - " [ True, True, True],\n", - " [ True, True, True]])" + "[0. 0.] [0.9 1.1] [1.8 2.2]\n", + "[2.7 3.3] [3.6 4.4] [4.5 5.5]\n", + "[5.4 6.6] [6.3 7.7] [7.2 8.8]" ] }, - "execution_count": 15, + "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "mat_mul_test == matmul(v1, v1)" + "# matrix \n", + "\n", + "a = np.arange(9).reshape(3,3)\n", + "mat_i = create_interval(matrix=a, half_width=0.1)\n", + "print(\"matrix interval with shape:\", mat_i.shape)\n", + "mat_i" ] }, { "cell_type": "code", "execution_count": null, - "id": "d9ea9be0-17f8-4e3a-8feb-f3fda24b2549", + "id": "9baebab5-4062-4a4d-b30d-7f00428e192a", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", - "id": "f5e18d79-62f4-462b-80ca-50b947a7fe84", + "id": "bd29348b-91be-43b7-800b-741a918336b3", "metadata": { "tags": [] }, "source": [ - "#### row @ mat" + "#### mat @ mat" ] }, { "cell_type": "code", - "execution_count": 16, - "id": "dadc30a0-8f0b-4cce-b3fa-f82cf86612cc", + "execution_count": 12, + "id": "aa4e3c4d-7163-4ad3-8f17-2ab8f5b8039e", "metadata": {}, "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(3,)\n" - ] - }, { "data": { "text/plain": [ - "[0.9,1.1]\n", - "[2.7,3.3000000000000003]\n", - "[4.5,5.5]" + "[12.15 18.15] [34.02 50.82] [55.89 83.49]\n", + "[14.58 21.78] [43.74 65.34] [ 72.9 108.9]\n", + "[17.01 25.41] [53.46 79.86] [ 89.91 134.31]" ] }, - "execution_count": 16, + "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "vec = create_interval(matrix=np.array([1, 3, 5]))\n", - "print(vec.shape)\n", - "vec" + "mat_mul_test = intvl_matmul(mat_i, mat_i)\n", + "mat_mul_test" ] }, { "cell_type": "code", - "execution_count": 17, - "id": "bb37117e-7156-4273-8f68-c373dfb289fe", + "execution_count": 13, + "id": "ec6c2d24-ec3f-460f-9937-fb0f375b22a7", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "(3,)" + "[12.15 18.15] [14.58 21.78] [17.01 25.41]\n", + "[34.02 50.82] [43.74 65.34] [53.46 79.86]\n", + "[55.89 83.49] [ 72.9 108.9] [ 89.91 134.31]" ] }, - "execution_count": 17, + "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "vec.shape" + "''' double check with Marco's version '''\n", + "\n", + "matmul(mat_i, mat_i)" ] }, { "cell_type": "code", - "execution_count": 18, - "id": "dda27fcf-29cc-4454-926f-b2bd7bb70715", + "execution_count": 14, + "id": "c8760ce1-ae39-46d7-a44f-9df0cadebd72", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "[0.9,1.1]" + "array([[ True, False, False],\n", + " [False, True, False],\n", + " [False, False, True]])" ] }, - "execution_count": 18, + "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "vec[0]" + "mat_mul_test == matmul(mat_i, mat_i)" + ] + }, + { + "cell_type": "markdown", + "id": "f5e18d79-62f4-462b-80ca-50b947a7fe84", + "metadata": { + "tags": [] + }, + "source": [ + "#### row @ mat" ] }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 15, + "id": "dadc30a0-8f0b-4cce-b3fa-f82cf86612cc", + "metadata": {}, + "outputs": [], + "source": [ + "# vec = create_interval(matrix=np.array([1, 3, 5]))\n", + "# print(vec.shape)\n", + "# vec" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "bb37117e-7156-4273-8f68-c373dfb289fe", + "metadata": {}, + "outputs": [], + "source": [ + "# vec.shape" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "dda27fcf-29cc-4454-926f-b2bd7bb70715", + "metadata": {}, + "outputs": [], + "source": [ + "# scalar\n", + "# vec[0]" + ] + }, + { + "cell_type": "code", + "execution_count": 18, "id": "f9ed7783-218a-4757-ad14-e9dd7a04c850", "metadata": {}, "outputs": [ @@ -298,18 +403,18 @@ "[nan,nan]" ] }, - "execution_count": 19, + "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "intvl_matmul(vec, v1)" + "intvl_matmul(vec, mat_i)" ] }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 19, "id": "68ae81db-9b26-4bbb-bc03-ef0f524cf659", "metadata": {}, "outputs": [ @@ -322,42 +427,20 @@ } ], "source": [ - "rowcol2(vec, v1)" + "rowcol2(vec, mat_i)" ] }, { "cell_type": "code", - "execution_count": 21, + "execution_count": null, "id": "4eff5388-d7b3-4202-a34b-6dcc102a8ce9", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(1, 3)\n" - ] - }, - { - "data": { - "text/plain": [ - "[0.9 1.1] [2.7 3.3] [4.5 5.5]" - ] - }, - "execution_count": 21, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "row_vec = create_interval(matrix=np.array([[1, 3, 5]]))\n", - "print(row_vec.shape)\n", - "row_vec" - ] + "outputs": [], + "source": [] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 20, "id": "f5995b3c-6f73-4f13-b299-160d83ddcf7b", "metadata": {}, "outputs": [], @@ -367,7 +450,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 21, "id": "9a2c2999-2a7d-4376-b0fd-70089a4f519c", "metadata": {}, "outputs": [], @@ -380,61 +463,41 @@ "execution_count": 22, "id": "f19a824e-afbf-44dc-9f4b-5ebe114a1419", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "(3, 1)\n" - ] - }, - { - "data": { - "text/plain": [ - "[31.59 47.19]\n", - "[38.88 58.08]\n", - "[46.17 68.97]" - ] - }, - "execution_count": 22, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ - "tt = intvl_matmul(row_vec, v1)\n", - "print(tt.shape)\n", - "tt" + "# tt = intvl_matmul(row_vec, mat_i)\n", + "# print(tt.shape)\n", + "# tt" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 23, "id": "bf7c771f-e297-46b5-8af8-71ba14ed430b", "metadata": {}, "outputs": [], "source": [ - "def reshape(interval):\n", - " length = len(interval)\n", - " new = I(lo=np.squeeze(interval.lo), hi=np.squeeze(interval.hi))\n", - " return new[np.newaxis, :]" + "# def reshape(interval):\n", + "# length = len(interval)\n", + "# new = I(lo=np.squeeze(interval.lo), hi=np.squeeze(interval.hi))\n", + "# return new[np.newaxis, :]" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 24, "id": "5dfbe597-4ba6-4669-a6f1-8b4d3400c0a1", "metadata": {}, "outputs": [], "source": [ - "new_rowmat_test = reshape(tt)\n", - "print(new_rowmat_test.shape)\n", - "new" + "# new_rowmat_test = reshape(tt)\n", + "# print(new_rowmat_test.shape)\n", + "# new" ] }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 25, "id": "1c9c2e95-a4a3-4041-a828-524bfba0305b", "metadata": {}, "outputs": [ @@ -444,7 +507,7 @@ "[31.59 47.19] [38.88 58.08] [46.17 68.97]" ] }, - "execution_count": 23, + "execution_count": 25, "metadata": {}, "output_type": "execute_result" } @@ -452,12 +515,12 @@ "source": [ "''' double check with Marco's version '''\n", "\n", - "rowcol_xT_WT(row_vec, v1)" + "rowcol_xT_WT(row_vec, mat_i)" ] }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 26, "id": "93d79e7e-57be-454b-97f1-96c708454bd9", "metadata": {}, "outputs": [ @@ -467,31 +530,15 @@ "[31.59 47.19] [38.88 58.08] [46.17 68.97]" ] }, - "execution_count": 24, + "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "matmul(row_vec, v1)" + "matmul(row_vec, mat_i)" ] }, - { - "cell_type": "code", - "execution_count": null, - "id": "3c759931-61dd-4462-ace9-7c1c5ac8bf9b", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "896f6f13-ac6b-4db1-9e35-c041226abeab", - "metadata": {}, - "outputs": [], - "source": [] - }, { "cell_type": "markdown", "id": "70d232da-a898-449b-aa13-b6696272d2c2", @@ -504,32 +551,31 @@ }, { "cell_type": "code", - "execution_count": 25, - "id": "6db7d27c-3493-45af-bf03-6fd3ac53bfe8", + "execution_count": 27, + "id": "eb667504-afbb-4be1-886e-d757f0535d6c", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "[0. 0.] [0.9 1.1] [1.8 2.2]\n", - "[2.7 3.3] [3.6 4.4] [4.5 5.5]\n", - "[5.4 6.6] [6.3 7.7] [7.2 8.8]" + "[10.53,15.730000000000002]\n", + "[32.4,48.400000000000006]\n", + "[54.269999999999996,81.07000000000002]" ] }, - "execution_count": 25, + "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "# given a matrix\n", - "v1" + "intvl_matmul(mat_i, vec)" ] }, { "cell_type": "code", - "execution_count": 26, - "id": "eb667504-afbb-4be1-886e-d757f0535d6c", + "execution_count": 28, + "id": "9876da08-d5b1-401a-9d58-89d6054d9f44", "metadata": {}, "outputs": [ { @@ -540,86 +586,38 @@ "[54.269999999999996,81.07000000000002]" ] }, - "execution_count": 26, + "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "intvl_matmul(v1, vec)" + "intvl_matmul(mat_i, col_vec)" ] }, { "cell_type": "code", - "execution_count": 34, - "id": "2e8f7dfa-338d-4c1c-8401-1d98ef4d1427", + "execution_count": 29, + "id": "77879741-133a-4ef2-94bd-d0d75650aea3", "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "(3, 1)" + "\" test with marco's old code, which has been updated I guess \"" ] }, - "execution_count": 34, + "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "vec = create_interval(matrix=np.array([1, 3, 5]))\n", - "vec.shape\n", - "\n", - "col_vec = vec[:, np.newaxis]\n", - "col_vec.shape" - ] - }, - { - "cell_type": "code", - "execution_count": 36, - "id": "9876da08-d5b1-401a-9d58-89d6054d9f44", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[10.53,15.730000000000002]\n", - "[32.4,48.400000000000006]\n", - "[54.269999999999996,81.07000000000002]" - ] - }, - "execution_count": 36, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "intvl_matmul(v1, col_vec)" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "id": "77879741-133a-4ef2-94bd-d0d75650aea3", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "\" test with marco's old code, which has been updated I guess \"" - ] - }, - "execution_count": 27, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "''' test with marco's old code, which has been updated I guess '''\n", + "''' test with marco's old code, which has been updated I guess '''\n", "\n", "# # therefore, marco's rowvec works when the latter vec is just a vector\n", "\n", - "# test_marco = rowcol2(v1, vec)\n", + "# test_marco = rowcol2(mat_i, vec)\n", "# print(test_marco.shape)\n", "# test_marco\n", "\n", @@ -629,12 +627,12 @@ "# print(col_vec.shape)\n", "# col_vec\n", "\n", - "# intvl_matmul(v1, col_vec)" + "# intvl_matmul(mat_i, col_vec)" ] }, { "cell_type": "code", - "execution_count": 38, + "execution_count": 30, "id": "c835a252-6aed-43fb-91a2-3fe62307ed12", "metadata": {}, "outputs": [ @@ -655,52 +653,12 @@ "source": [ "''' test with marco's new code '''\n", "\n", - "print(rowcol_W_x(v1, col_vec))\n", + "print(rowcol_W_x(mat_i, col_vec))\n", "\n", "print('test the universal \"matmul\" function:')\n", - "print(matmul(v1, col_vec))" + "print(matmul(mat_i, col_vec))" ] }, - { - "cell_type": "code", - "execution_count": null, - "id": "55846437-7298-43c7-92f9-a49d85da66a8", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6fe6ff32-de12-45ee-95f4-95a8b4d27385", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "cff4877d-0a67-4e0a-9804-911231fba552", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "a8b747e4-4f00-46a4-a527-ac17234d9b79", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "63eb993c-1d64-4fe0-851f-6fc3cc90d31f", - "metadata": {}, - "outputs": [], - "source": [] - }, { "cell_type": "markdown", "id": "ea3e169a-88cf-4645-b613-fc513f686bd1", @@ -713,21 +671,18 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 31, "id": "67ede585-d4b3-4979-b111-8c191117a226", "metadata": {}, "outputs": [], "source": [ "# create a row vector \n", - "\n", - "row_vec = create_interval(matrix=np.array([1, 3, 5]))\n", - "print(row_vec.shape)\n", - "row_vec" + "\n" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 32, "id": "f75a5aaf-9013-4951-bb84-88a09d50b270", "metadata": {}, "outputs": [], @@ -737,17 +692,17 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 33, "id": "0631a1bf-dd74-4b0e-88df-a102c073c9eb", "metadata": {}, "outputs": [], "source": [ - "# sigmoid(v1)" + "# sigmoid(mat_i)" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 34, "id": "9e8d317c-7655-40eb-9f38-407d6310b66f", "metadata": {}, "outputs": [], @@ -761,10 +716,21 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 35, "id": "9a58174a-49e1-48f6-af8c-2bc8efb98259", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "' lower dimension failed '" + ] + }, + "execution_count": 35, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "''' lower dimension failed '''\n", "\n", @@ -773,18 +739,34 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 36, "id": "f8f0f97d-86b1-416c-866c-1c5c2cbeb445", "metadata": {}, - "outputs": [], + "outputs": [ + { + "ename": "UnboundLocalError", + "evalue": "cannot access local variable 'l' where it is not associated with a value", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mUnboundLocalError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[36], line 7\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;66;03m# matrix which is mat_i\u001b[39;00m\n\u001b[1;32m 2\u001b[0m \u001b[38;5;124;03m'''\u001b[39;00m\n\u001b[1;32m 3\u001b[0m \u001b[38;5;124;03m(3, ) @ (3,3)\u001b[39;00m\n\u001b[1;32m 4\u001b[0m \n\u001b[1;32m 5\u001b[0m \u001b[38;5;124;03m'''\u001b[39;00m\n\u001b[0;32m----> 7\u001b[0m result \u001b[38;5;241m=\u001b[39m \u001b[43mrowcol2\u001b[49m\u001b[43m(\u001b[49m\u001b[43mx\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrow_vec\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mW\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmat_i\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 8\u001b[0m result\n", + "File \u001b[0;32m~/work_leslie/intervals/intervals/mat_features.py:56\u001b[0m, in \u001b[0;36mrowcol2\u001b[0;34m(x, W)\u001b[0m\n\u001b[1;32m 54\u001b[0m y\u001b[38;5;241m=\u001b[39m[]\n\u001b[1;32m 55\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m i \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mrange\u001b[39m(s[\u001b[38;5;241m0\u001b[39m]): \n\u001b[0;32m---> 56\u001b[0m y\u001b[38;5;241m.\u001b[39mappend(\u001b[43mdot\u001b[49m\u001b[43m(\u001b[49m\u001b[43mx\u001b[49m\u001b[43m[\u001b[49m\u001b[43mi\u001b[49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\u001b[43mW\u001b[49m\u001b[43m)\u001b[49m)\n\u001b[1;32m 58\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m intervalise(y)\n\u001b[1;32m 59\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n", + "File \u001b[0;32m~/work_leslie/intervals/intervals/mat_features.py:32\u001b[0m, in \u001b[0;36mdot\u001b[0;34m(x, y)\u001b[0m\n\u001b[0;32m---> 32\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mdot\u001b[39m(x,y): \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28msum\u001b[39m(\u001b[43mx\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43my\u001b[49m)\n", + "File \u001b[0;32m~/work_leslie/intervals/intervals/number.py:166\u001b[0m, in \u001b[0;36mInterval.__mul__\u001b[0;34m(self, other)\u001b[0m\n\u001b[1;32m 164\u001b[0m hi[other_negative]\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mlo[other_negative] \u001b[38;5;241m*\u001b[39m other[other_negative]\n\u001b[1;32m 165\u001b[0m \u001b[38;5;28;01melif\u001b[39;00m otherType \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mInterval\u001b[39m\u001b[38;5;124m'\u001b[39m:\n\u001b[0;32m--> 166\u001b[0m lo,hi \u001b[38;5;241m=\u001b[39m \u001b[43mmultiply\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43mother\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 167\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m: \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mNotImplemented\u001b[39m\n\u001b[1;32m 168\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m Interval(lo,hi)\n", + "File \u001b[0;32m~/work_leslie/intervals/intervals/arithmetic.py:120\u001b[0m, in \u001b[0;36mmultiply\u001b[0;34m(s, o)\u001b[0m\n\u001b[1;32m 118\u001b[0m l[nn] \u001b[38;5;241m=\u001b[39m s_hi[nn] \u001b[38;5;241m*\u001b[39m o_hi\n\u001b[1;32m 119\u001b[0m h[nn] \u001b[38;5;241m=\u001b[39m s_lo[nn] \u001b[38;5;241m*\u001b[39m o_lo\n\u001b[0;32m--> 120\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43ml\u001b[49m,h\n", + "\u001b[0;31mUnboundLocalError\u001b[0m: cannot access local variable 'l' where it is not associated with a value" + ] + } + ], "source": [ - "# matrix which is v1\n", + "# matrix which is mat_i\n", "'''\n", "(3, ) @ (3,3)\n", "\n", "'''\n", "\n", - "result = rowcol2(x=row_vec, W=v1)\n", + "result = rowcol2(x=row_vec, W=mat_i)\n", "result" ] }, @@ -805,7 +787,7 @@ "metadata": {}, "outputs": [], "source": [ - "result_ = intvl_matmul(x=row_vec, W=v1)\n", + "result_ = intvl_matmul(x=row_vec, W=mat_i)\n", "type(result_)" ] }, @@ -821,7 +803,6 @@ "cell_type": "markdown", "id": "5668b7ad-298b-486a-a034-c98515a5c4b9", "metadata": { - "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ @@ -830,80 +811,99 @@ }, { "cell_type": "code", - "execution_count": null, - "id": "c065ed91-870d-4bce-82fa-781036536cc1", - "metadata": {}, - "outputs": [], - "source": [ - "# scalar\n", - "x = 3\n", - "x_intvl = create_interval(matrix=x)\n", - "x_intvl" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "57d11069-0ecf-4266-8798-6b5e4e71923b", - "metadata": {}, - "outputs": [], - "source": [ - "# a vector\n", - "W1 = np.array([[1, 3, 5]])" - ] - }, - { - "cell_type": "code", - "execution_count": null, + "execution_count": 37, "id": "f3643fdb-387d-40dc-a1c6-6e8ee738a3ac", "metadata": {}, "outputs": [], "source": [ - "W1_intvl = create_interval(matrix=W1)\n", - "W1_intvl" + "W1_intvl = row_vec" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 38, "id": "b8ddeda1-0d4c-4994-aef8-89c677a7f009", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "(1, 3)" + ] + }, + "execution_count": 38, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "W1_intvl.shape" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 39, "id": "ea3b0076-545a-4014-a01c-a7b00bdfad00", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "[2.43 3.63] [ 7.29 10.89] [12.15 18.15]" + ] + }, + "execution_count": 39, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "''' \n", "(3, ) @ (1, 3)\n", "'''\n", "\n", - "h1 = x_intvl * W1_intvl\n", + "h1 = x_si * W1_intvl\n", "h1" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 40, "id": "c5b06fc9-177b-4c6f-a03f-cf78b506e4a7", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "(1, 3)" + ] + }, + "execution_count": 40, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "h1.shape" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 41, "id": "2c8056b0-c95e-4048-b6b9-b1fc54dd7e83", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "'\\na further test where if (I) a scalar * interval vector matches with (II) scalar interval * interval vector\\n'" + ] + }, + "execution_count": 41, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "'''\n", "a further test where if (I) a scalar * interval vector matches with (II) scalar interval * interval vector\n", @@ -912,49 +912,178 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 42, "id": "90868753-32eb-48d9-a2cc-eb5caad50a95", "metadata": {}, "outputs": [], "source": [ - "x = np.array([3.2])" + "x_c = np.array([3.2])" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 43, "id": "c049bfdf-eb62-4d37-958d-34e8642f639a", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "[3.2,3.2]" + ] + }, + "execution_count": 43, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "# scaler * interval vector\n", - "x2 = I(3.2, 3.2)\n", - "x2" + "x_ci = I(3.2, 3.2)\n", + "x_ci" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 44, "id": "90d81cb1-8b19-4ee4-9429-460805f63f1d", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "array([[ True, True, True]])" + ] + }, + "execution_count": 44, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "3.2 * h1 == x2 * h1 " + "3.2 * h1 == x_ci * h1 " ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 45, "id": "9f8f1d70-c66e-4003-b58c-f253f5b24a08", "metadata": {}, - "outputs": [], - "source": [] + "outputs": [ + { + "ename": "ValueError", + "evalue": "not enough values to unpack (expected 2, got 0)", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[45], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mmatmul\u001b[49m\u001b[43m(\u001b[49m\u001b[43mx_ci\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mrow_vec\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/work_leslie/intervals/intervals/methods.py:739\u001b[0m, in \u001b[0;36mmatmul\u001b[0;34m(A, B)\u001b[0m\n\u001b[1;32m 734\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mmatmul\u001b[39m(A,B):\n\u001b[1;32m 735\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m'''\u001b[39;00m\n\u001b[1;32m 736\u001b[0m \u001b[38;5;124;03m (m,n) x (n,p) -> (m,p) \u001b[39;00m\n\u001b[1;32m 737\u001b[0m \u001b[38;5;124;03m (1,n) x (n,1) -> (1,1)\u001b[39;00m\n\u001b[1;32m 738\u001b[0m \u001b[38;5;124;03m '''\u001b[39;00m\n\u001b[0;32m--> 739\u001b[0m m,na \u001b[38;5;241m=\u001b[39m A\u001b[38;5;241m.\u001b[39mshape\n\u001b[1;32m 740\u001b[0m nb,p \u001b[38;5;241m=\u001b[39m B\u001b[38;5;241m.\u001b[39mshape\n\u001b[1;32m 741\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m na\u001b[38;5;241m!=\u001b[39mnb: \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mIncompatible shapes (\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mm\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m,\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mna\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m) x (\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mnb\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m,\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mp\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m) -> (?,?). Inner sizes must be same, \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mna\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m is different from \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mnb\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m.\u001b[39m\u001b[38;5;124m'\u001b[39m)\n", + "\u001b[0;31mValueError\u001b[0m: not enough values to unpack (expected 2, got 0)" + ] + } + ], + "source": [ + "matmul(x_ci, row_vec)" + ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 46, "id": "bb1a50bc-00b0-4a98-bbb9-c5bdb4de1f0a", "metadata": {}, + "outputs": [ + { + "ename": "ValueError", + "evalue": "not enough values to unpack (expected 2, got 0)", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[46], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mmatmul\u001b[49m\u001b[43m(\u001b[49m\u001b[43mx_ci\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcol_vec\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/work_leslie/intervals/intervals/methods.py:739\u001b[0m, in \u001b[0;36mmatmul\u001b[0;34m(A, B)\u001b[0m\n\u001b[1;32m 734\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mmatmul\u001b[39m(A,B):\n\u001b[1;32m 735\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m'''\u001b[39;00m\n\u001b[1;32m 736\u001b[0m \u001b[38;5;124;03m (m,n) x (n,p) -> (m,p) \u001b[39;00m\n\u001b[1;32m 737\u001b[0m \u001b[38;5;124;03m (1,n) x (n,1) -> (1,1)\u001b[39;00m\n\u001b[1;32m 738\u001b[0m \u001b[38;5;124;03m '''\u001b[39;00m\n\u001b[0;32m--> 739\u001b[0m m,na \u001b[38;5;241m=\u001b[39m A\u001b[38;5;241m.\u001b[39mshape\n\u001b[1;32m 740\u001b[0m nb,p \u001b[38;5;241m=\u001b[39m B\u001b[38;5;241m.\u001b[39mshape\n\u001b[1;32m 741\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m na\u001b[38;5;241m!=\u001b[39mnb: \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mIncompatible shapes (\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mm\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m,\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mna\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m) x (\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mnb\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m,\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mp\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m) -> (?,?). Inner sizes must be same, \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mna\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m is different from \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mnb\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m.\u001b[39m\u001b[38;5;124m'\u001b[39m)\n", + "\u001b[0;31mValueError\u001b[0m: not enough values to unpack (expected 2, got 0)" + ] + } + ], + "source": [ + "matmul(x_ci, col_vec)" + ] + }, + { + "cell_type": "code", + "execution_count": 47, + "id": "3f353f36-a4e4-4203-a1d7-637be2c46064", + "metadata": {}, + "outputs": [ + { + "ename": "IndexError", + "evalue": "tuple index out of range", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mIndexError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[47], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mrowcol_xT_WT\u001b[49m\u001b[43m(\u001b[49m\u001b[43mx_ci\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmat_i\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/work_leslie/intervals/intervals/methods.py:717\u001b[0m, in \u001b[0;36mrowcol_xT_WT\u001b[0;34m(x, W)\u001b[0m\n\u001b[1;32m 715\u001b[0m n,m \u001b[38;5;241m=\u001b[39m W\u001b[38;5;241m.\u001b[39mshape\n\u001b[1;32m 716\u001b[0m x_shape \u001b[38;5;241m=\u001b[39m x\u001b[38;5;241m.\u001b[39mshape\n\u001b[0;32m--> 717\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m((n\u001b[38;5;241m==\u001b[39m\u001b[43mx_shape\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m0\u001b[39;49m\u001b[43m]\u001b[49m) \u001b[38;5;241m|\u001b[39m (n\u001b[38;5;241m==\u001b[39mx_shape[\u001b[38;5;241m1\u001b[39m])): \n\u001b[1;32m 718\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mIncompatible shapes (1,\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mx_shape[\u001b[38;5;241m1\u001b[39m]\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m) x (\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mn\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m,\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mm\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m) -> (?,?). Inner sizes must be same, \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mx_shape[\u001b[38;5;241m1\u001b[39m]\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m is different from \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mn\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m.\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m 719\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m x_shape[\u001b[38;5;241m0\u001b[39m]\u001b[38;5;241m==\u001b[39m\u001b[38;5;241m1\u001b[39m: \u001b[38;5;66;03m# this is the correct shape\u001b[39;00m\n", + "\u001b[0;31mIndexError\u001b[0m: tuple index out of range" + ] + } + ], + "source": [ + "rowcol_xT_WT(x_ci, mat_i)" + ] + }, + { + "cell_type": "code", + "execution_count": 48, + "id": "b4f2d2a6-bdba-4871-8a02-5da9ea8200f2", + "metadata": {}, + "outputs": [ + { + "ename": "ValueError", + "evalue": "not enough values to unpack (expected 2, got 0)", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[48], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mrowcol_W_x\u001b[49m\u001b[43m(\u001b[49m\u001b[43mx_ci\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmat_i\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/work_leslie/intervals/intervals/methods.py:687\u001b[0m, in \u001b[0;36mrowcol_W_x\u001b[0;34m(W, x)\u001b[0m\n\u001b[1;32m 676\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mrowcol_W_x\u001b[39m(W,x): \n\u001b[1;32m 677\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m'''\u001b[39;00m\n\u001b[1;32m 678\u001b[0m \u001b[38;5;124;03m Row by column multiplication between a matrix W and a column vector x.\u001b[39;00m\n\u001b[1;32m 679\u001b[0m \n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 685\u001b[0m \u001b[38;5;124;03m (1,n) x (1,n) -> (1,1) \u001b[39;00m\n\u001b[1;32m 686\u001b[0m \u001b[38;5;124;03m '''\u001b[39;00m\n\u001b[0;32m--> 687\u001b[0m m,n \u001b[38;5;241m=\u001b[39m W\u001b[38;5;241m.\u001b[39mshape\n\u001b[1;32m 688\u001b[0m x_shape \u001b[38;5;241m=\u001b[39m x\u001b[38;5;241m.\u001b[39mshape\n\u001b[1;32m 689\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m((n\u001b[38;5;241m==\u001b[39mx_shape[\u001b[38;5;241m0\u001b[39m]) \u001b[38;5;241m|\u001b[39m (n\u001b[38;5;241m==\u001b[39mx_shape[\u001b[38;5;241m1\u001b[39m])): \n", + "\u001b[0;31mValueError\u001b[0m: not enough values to unpack (expected 2, got 0)" + ] + } + ], + "source": [ + "rowcol_W_x(x_ci, mat_i)" + ] + }, + { + "cell_type": "code", + "execution_count": 49, + "id": "a3478b26-17b1-4bc0-959d-15ad49cf16c3", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[0. 0.] [2.88 3.52] [5.76 7.04]\n", + "[ 8.64 10.56] [11.52 14.08] [14.4 17.6]\n", + "[17.28 21.12] [20.16 24.64] [23.04 28.16]" + ] + }, + "execution_count": 49, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "x_ci * mat_i" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b5e47923-1120-40a4-b67b-1c30636fb0a2", + "metadata": {}, "outputs": [], "source": [] }, @@ -983,25 +1112,45 @@ "source": [ "# consider a column vector\n", "\n", - "W2 = np.array([1, 3, 5])[:, np.newaxis]" + "W2_intvl = col_vec" ] }, { "cell_type": "code", "execution_count": null, - "id": "343ea692-fea7-4650-a45c-42b108dd8aed", + "id": "5f9e63cf-80b8-434d-bcb2-f1aac363a127", "metadata": {}, "outputs": [], "source": [ - "W2_intvl = create_interval(matrix=W2)\n", - "print(W2_intvl.shape)\n", "W2_intvl" ] }, { "cell_type": "code", "execution_count": null, - "id": "5f9e63cf-80b8-434d-bcb2-f1aac363a127", + "id": "136c2bd5-81ad-41dc-aa56-aaeef7270828", + "metadata": {}, + "outputs": [], + "source": [ + "y_hat = intvl_matmul(x=x_ci, W=W2_intvl)\n", + "y_hat" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f0ee30f5-1951-4bb1-a1c6-59adcb9b4219", + "metadata": {}, + "outputs": [], + "source": [ + "y_hat2 = intvl_matmul(x=h1, W=mat_i)\n", + "y_hat2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "73da3cd2-4bfb-436b-92e8-7b9ba9daaa83", "metadata": {}, "outputs": [], "source": [] @@ -1009,23 +1158,23 @@ { "cell_type": "code", "execution_count": null, - "id": "136c2bd5-81ad-41dc-aa56-aaeef7270828", + "id": "6a9193cb-dedf-497f-80cb-fef3446b04d1", "metadata": {}, "outputs": [], "source": [ - "y_hat = intvl_matmul(x=h1, W=W2_intvl)\n", - "y_hat" + "# scalar * vector\n", + "\n", + "matmul(x_ci, h1)" ] }, { "cell_type": "code", "execution_count": null, - "id": "f0ee30f5-1951-4bb1-a1c6-59adcb9b4219", + "id": "abaeead0-1f56-4093-b307-ff336272769c", "metadata": {}, "outputs": [], "source": [ - "y_hat2 = intvl_matmul(x=h1, W=v1)\n", - "y_hat2" + "matmaul(5, h1)" ] }, { @@ -1045,6 +1194,42 @@ "source": [ "# sigmoid(x_intvl)" ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "57d9c55c-18a7-4ecb-b517-9c1b14417d53", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6c449f9b-2608-4046-b134-6c023f226ea4", + "metadata": {}, + "outputs": [], + "source": [ + "np.dot(3, [1,2,3])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1ad11d51-9e86-4ca0-a34b-2ceac68e007f", + "metadata": {}, + "outputs": [], + "source": [ + "np.dot([3,2,1], [1,2,3])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e6644df3-75c6-45b7-9ae3-21c29d755b7f", + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { From 8fc6276fbf26ef052bc5c3c0e9c3f7263f10bab8 Mon Sep 17 00:00:00 2001 From: leslieDLcy Date: Sun, 24 Nov 2024 16:11:38 +0000 Subject: [PATCH 11/11] some updates --- pyproject.toml | 20 -------------------- setup.py | 11 +++++++++++ {intervals => src/intervals}/__init__.py | 0 {intervals => src/intervals}/arithmetic.py | 0 {intervals => src/intervals}/complex.py | 0 {intervals => src/intervals}/methods.py | 2 +- {intervals => src/intervals}/number.py | 0 {intervals => src/intervals}/plotting.py | 0 {intervals => src/intervals}/random.py | 0 9 files changed, 12 insertions(+), 21 deletions(-) delete mode 100644 pyproject.toml create mode 100644 setup.py rename {intervals => src/intervals}/__init__.py (100%) rename {intervals => src/intervals}/arithmetic.py (100%) rename {intervals => src/intervals}/complex.py (100%) rename {intervals => src/intervals}/methods.py (99%) rename {intervals => src/intervals}/number.py (100%) rename {intervals => src/intervals}/plotting.py (100%) rename {intervals => src/intervals}/random.py (100%) diff --git a/pyproject.toml b/pyproject.toml deleted file mode 100644 index b580b29..0000000 --- a/pyproject.toml +++ /dev/null @@ -1,20 +0,0 @@ -# file: pyproject.toml - -[build-system] -requires = [ - "setuptools >= 68.0.0", - "wheel >= 0.41.0", -] -build-backend = "setuptools.build_meta" - -[project] -name = "intervals" -version = "0.1.2" -authors = [ - {name = "Marco de Angelis", email = "marco.de-angelis@strath.ac.uk"}, -] -requires-python = ">=3.7" -description = "Emulated interval arithmetic in Python." -dependencies = [ - "numpy", -] diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..6a60ec7 --- /dev/null +++ b/setup.py @@ -0,0 +1,11 @@ +from setuptools import find_packages, setup + +setup( + name='intervals', + packages=find_packages(where="src"), + package_dir={"": "src"}, + version='0.2.0', + description='A modified version of the intervals library by Leslie', + author='Marco, Leslie', + license='MIT', +) \ No newline at end of file diff --git a/intervals/__init__.py b/src/intervals/__init__.py similarity index 100% rename from intervals/__init__.py rename to src/intervals/__init__.py diff --git a/intervals/arithmetic.py b/src/intervals/arithmetic.py similarity index 100% rename from intervals/arithmetic.py rename to src/intervals/arithmetic.py diff --git a/intervals/complex.py b/src/intervals/complex.py similarity index 100% rename from intervals/complex.py rename to src/intervals/complex.py diff --git a/intervals/methods.py b/src/intervals/methods.py similarity index 99% rename from intervals/methods.py rename to src/intervals/methods.py index 7f49a83..be44a9c 100644 --- a/intervals/methods.py +++ b/src/intervals/methods.py @@ -45,7 +45,7 @@ numpy_tan = numpy.tan # numpy_cot = numpy.cotang numpy_pi = numpy.pi -numpy_inf = numpy.Inf +numpy_inf = numpy.inf # Properties or maybe attributes of the interval class. These apply to all interval-like objects. diff --git a/intervals/number.py b/src/intervals/number.py similarity index 100% rename from intervals/number.py rename to src/intervals/number.py diff --git a/intervals/plotting.py b/src/intervals/plotting.py similarity index 100% rename from intervals/plotting.py rename to src/intervals/plotting.py diff --git a/intervals/random.py b/src/intervals/random.py similarity index 100% rename from intervals/random.py rename to src/intervals/random.py