From 1f621041e021c7b8fcaaa8c60cab05b3c93f793f Mon Sep 17 00:00:00 2001 From: Harendra kumar Date: Sun, 29 Mar 2026 22:08:50 +0530 Subject: [PATCH 1/6] your message --- README.md | 188 +- notebooks/tutorial_diversity_measures.ipynb | 518 +-- notebooks/tutorial_image_classification.ipynb | 780 ++-- notebooks/tutorial_partition_based.ipynb | 1100 +++--- notebooks/tutorial_similarity_based.ipynb | 1024 +++--- pyproject.toml | 840 ++--- requirements.txt | 6 +- requirements_dev.txt | 26 +- selector/__init__.py | 54 +- selector/measures/__init__.py | 46 +- selector/measures/converter.py | 832 ++--- selector/measures/diversity.py | 1122 +++--- selector/measures/similarity.py | 652 ++-- selector/measures/tests/__init__.py | 50 +- selector/measures/tests/common.py | 238 +- selector/measures/tests/test_converter.py | 538 +-- selector/measures/tests/test_diversity.py | 726 ++-- selector/methods/__init__.py | 54 +- selector/methods/base.py | 378 +- selector/methods/distance.py | 1402 +++---- selector/methods/partition.py | 1336 +++---- selector/methods/similarity.py | 2096 +++++------ selector/methods/tests/__init__.py | 46 +- selector/methods/tests/common.py | 288 +- .../tests/data/coords_imbalance_case1.txt | 104 +- .../tests/data/coords_imbalance_case2.txt | 108 +- .../tests/data/labels_imbalance_case1.txt | 104 +- .../tests/data/labels_imbalance_case2.txt | 108 +- .../tests/data/ref_esim_selection_data.csv | 1154 +++--- selector/methods/tests/test_distance.py | 1168 +++--- selector/methods/tests/test_partition.py | 370 +- selector/methods/tests/test_similarity.py | 3220 ++++++++--------- selector/methods/utils.py | 236 +- tox.ini | 560 +-- updateheaders.py | 274 +- 35 files changed, 10873 insertions(+), 10873 deletions(-) diff --git a/README.md b/README.md index 7dabf9de..38f898b0 100644 --- a/README.md +++ b/README.md @@ -1,94 +1,94 @@ -
- - Logo -
- -[![This project supports Python 3.9+](https://img.shields.io/badge/Python-3.9+-blue.svg)](https://python.org/downloads) -[![GPLv3 License](https://img.shields.io/badge/License-GPL%20v3-yellow.svg)](https://opensource.org/licenses/) -[![CI Tox](https://github.com/theochem/Selector/actions/workflows/ci_tox.yaml/badge.svg?branch=main)](https://github.com/theochem/Selector/actions/workflows/ci_tox.yaml) -[![codecov](https://codecov.io/gh/theochem/Selector/graph/badge.svg?token=0UJixrJfNJ)](https://codecov.io/gh/theochem/Selector) - -The `Selector` library provides methods for selecting a diverse subset of a (molecular) dataset. - -## Citation - -Please use the following citation in any publication using the `selector` library: - -```md -@article{selector_library, -author = {Meng, Fanwang and Martínez González, Marco and Chuiko, Valerii and Tehrani, Alireza and Al Nabulsi, Abdul Rahman and Broscius, Abigail and Khaleel, Hasan and López-P{\'e}rez, Kenneth and Miranda-Quintana, Ramón Alain and Ayers, Paul W. and Heidar-Zadeh, Farnaz}, -title = {Selector: A General Python Library for Diverse Subset Selection}, -journal = {Journal of Chemical Information and Modeling}, -volume = {0}, -number = {0}, -pages = {null}, -year = {0}, -doi = {10.1021/acs.jcim.5c01499}, -note ={PMID: 41591801}, -URL = {https://doi.org/10.1021/acs.jcim.5c01499} -} -``` - -## Web Server - -We have a web server for the `selector` library at https://huggingface.co/spaces/QCDevs/Selector. -For small and prototype datasets, you can use the web server to select a diverse subset of your -dataset and compute the diversity metrics, where you can download the selected subset and the -computed diversity metrics. - -## Installation - -It is recommended to install `selector` within a virtual environment. To create a virtual -environment, we can use the `venv` module (Python 3.9+, -https://docs.python.org/3/tutorial/venv.html), `miniconda` (https://conda.io/projects/conda/en/latest/user-guide/tasks/manage-environments.html), or -`pipenv` (https://pipenv.pypa.io/en/latest/). - -### Installing from PyPI - -To install `selector` with `pip`, we can install the latest stable release from the Python Package Index (PyPI) as follows: - -```bash -# install the stable release -pip install qc-selector -``` - -### Installing from The Prebuild Wheel Files - -To download the prebuilt wheel files, visit the [PyPI page](https://pypi.org/project/qc-selector/) -and [GitHub releases](https://github.com/theochem/Selector/tags). - -```bash -# download the wheel file first to your local machine -# then install the wheel file -pip install file_path/qc_selector-0.1.0-py3-none-any.whl - -``` - -### Installing from the Source Code - -In addition, we can install the latest development version from the GitHub repository as follows: - -```bash -# install the latest development version -pip install git+https://github.com/theochem/Selector.git -``` - -We can also clone the repository to access the latest development version, test it and install it as follows: - -```bash -# clone the repository -git clone git@github.com:theochem/Selector.git - -# change into the working directory -cd Selector -# run the tests -python -m pytest . - -# install the package -pip install . - -``` - -## More - -See https://selector.qcdevs.org for full details. +
+ + Logo +
+ +[![This project supports Python 3.9+](https://img.shields.io/badge/Python-3.9+-blue.svg)](https://python.org/downloads) +[![GPLv3 License](https://img.shields.io/badge/License-GPL%20v3-yellow.svg)](https://opensource.org/licenses/) +[![CI Tox](https://github.com/theochem/Selector/actions/workflows/ci_tox.yaml/badge.svg?branch=main)](https://github.com/theochem/Selector/actions/workflows/ci_tox.yaml) +[![codecov](https://codecov.io/gh/theochem/Selector/graph/badge.svg?token=0UJixrJfNJ)](https://codecov.io/gh/theochem/Selector) + +The `Selector` library provides methods for selecting a diverse subset of a (molecular) dataset. + +## Citation + +Please use the following citation in any publication using the `selector` library: + +```md +@article{selector_library, +author = {Meng, Fanwang and Martínez González, Marco and Chuiko, Valerii and Tehrani, Alireza and Al Nabulsi, Abdul Rahman and Broscius, Abigail and Khaleel, Hasan and López-P{\'e}rez, Kenneth and Miranda-Quintana, Ramón Alain and Ayers, Paul W. and Heidar-Zadeh, Farnaz}, +title = {Selector: A General Python Library for Diverse Subset Selection}, +journal = {Journal of Chemical Information and Modeling}, +volume = {0}, +number = {0}, +pages = {null}, +year = {0}, +doi = {10.1021/acs.jcim.5c01499}, +note ={PMID: 41591801}, +URL = {https://doi.org/10.1021/acs.jcim.5c01499} +} +``` + +## Web Server + +We have a web server for the `selector` library at https://huggingface.co/spaces/QCDevs/Selector. +For small and prototype datasets, you can use the web server to select a diverse subset of your +dataset and compute the diversity metrics, where you can download the selected subset and the +computed diversity metrics. + +## Installation + +It is recommended to install `selector` within a virtual environment. To create a virtual +environment, we can use the `venv` module (Python 3.9+, +https://docs.python.org/3/tutorial/venv.html), `miniconda` (https://conda.io/projects/conda/en/latest/user-guide/tasks/manage-environments.html), or +`pipenv` (https://pipenv.pypa.io/en/latest/). + +### Installing from PyPI + +To install `selector` with `pip`, we can install the latest stable release from the Python Package Index (PyPI) as follows: + +```bash +# install the stable release +pip install qc-selector +``` + +### Installing from The Prebuild Wheel Files + +To download the prebuilt wheel files, visit the [PyPI page](https://pypi.org/project/qc-selector/) +and [GitHub releases](https://github.com/theochem/Selector/tags). + +```bash +# download the wheel file first to your local machine +# then install the wheel file +pip install file_path/qc_selector-0.1.0-py3-none-any.whl + +``` + +### Installing from the Source Code + +In addition, we can install the latest development version from the GitHub repository as follows: + +```bash +# install the latest development version +pip install git+https://github.com/theochem/Selector.git +``` + +We can also clone the repository to access the latest development version, test it and install it as follows: + +```bash +# clone the repository +git clone git@github.com:theochem/Selector.git + +# change into the working directory +cd Selector +# run the tests +python -m pytest . + +# install the package +pip install . + +``` + +## More + +See https://selector.qcdevs.org for full details. diff --git a/notebooks/tutorial_diversity_measures.ipynb b/notebooks/tutorial_diversity_measures.ipynb index ad4432c1..07352e69 100644 --- a/notebooks/tutorial_diversity_measures.ipynb +++ b/notebooks/tutorial_diversity_measures.ipynb @@ -1,259 +1,259 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Tutorial Diversity Measures\n", - "\n", - "This tutorial demonstrates how to quantify the diversity of selected subset with `diversity` module as implemented in\n", - "`selector` package. The diversity measures are calculated based on the feature matrix of the selected subset." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import sys\n", - "import warnings\n", - "\n", - "warnings.filterwarnings(\"ignore\")\n", - "\n", - "# uncomment the following line to run the code for your own project directory\n", - "# sys.path.append(\"/Users/Someone/Documents/projects/Selector\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import matplotlib.pylab as plt\n", - "import numpy as np\n", - "from sklearn.datasets import make_blobs\n", - "from sklearn.metrics.pairwise import pairwise_distances\n", - "from IPython.display import Markdown\n", - "\n", - "from selector.methods.distance import MaxMin, MaxSum, OptiSim, DISE\n", - "from selector.measures.diversity import compute_diversity, hypersphere_overlap_of_subset" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Utility Function for Showing Diversity Measures as A Table\n" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "# define function to render tables easier\n", - "\n", - "\n", - "def render_table(data, caption=None, decimals=3):\n", - " \"\"\"Renders a list of lists in ta markdown table for easy visualization.\n", - "\n", - " Parameters\n", - " ----------\n", - " data : list of lists\n", - " The data to be rendered in a table, each inner list represents a row with the first row\n", - " being the header.\n", - " caption : str, optional\n", - " The caption of the table.\n", - " decimals : int, optional\n", - " The number of decimal places to round the data to.\n", - " \"\"\"\n", - "\n", - " # check all rows have the same number of columns\n", - " if not all(len(row) == len(data[0]) for row in data):\n", - " raise ValueError(\"Expect all rows to have the same number of columns.\")\n", - "\n", - " if caption is not None:\n", - " # check if caption is a string\n", - " if not isinstance(caption, str):\n", - " raise ValueError(\"Expect caption to be a string.\")\n", - " tmp_output = f\"**{caption}**\\n\\n\"\n", - "\n", - " # get the width of each column (transpose the data list and get the max length of each new row)\n", - " colwidths = [max(len(str(s)) for s in col) + 2 for col in zip(*data)]\n", - "\n", - " # construct the header row\n", - " header = f\"| {' | '.join(f'{str(s):^{w}}' for s, w in zip(data[0], colwidths))} |\"\n", - " tmp_output += header + \"\\n\"\n", - "\n", - " # construct a separator row\n", - " separator = f\"|{'|'.join(['-' * w for w in colwidths])}|\"\n", - " tmp_output += separator + \"\\n\"\n", - "\n", - " # construct the data rows\n", - " for row in data[1:]:\n", - " # round the data to the specified number of decimal places\n", - " row = [round(s, decimals) if isinstance(s, float) else s for s in row]\n", - " row_str = f\"| {' | '.join(f'{str(s):^{w}}' for s, w in zip(row, colwidths))} |\"\n", - " tmp_output += row_str + \"\\n\"\n", - "\n", - " return display(Markdown(tmp_output))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Generating Data\n", - "\n", - "The data should be provided as:\n", - "\n", - "- either an array `X` of shape `(n_samples, n_features)` encoding `n_samples` samples (rows) each in `n_features`-dimensional (columns) feature space,\n", - "- or an array `X_dist` of shape `(n_samples, n_samples)` encoding the distance (i.e., dissimilarity) between each pair of `n_samples` sample points.\n", - "\n", - "This data can be loaded from various file formats (e.g., csv, npz, txt, etc.) or generated using various libraries on the fly. In this tutorial, we use [`sklearn.datasets.make_blobs`](https://scikit-learn.org/stable/modules/generated/sklearn.datasets.make_blobs.html) to generate cluster(s) of `n_samples` points in 2-dimensions (`n-features=2`), so that it can be easily visualized. However, the same functionality can be applied to higher dimensional datasets.\n" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Shape of data = (500, 20)\n", - "Shape of labels = (500,)\n", - "Unique labels = [0 1 2]\n", - "Cluster size = 167\n", - "Shape of the distance array = (500, 500)\n" - ] - } - ], - "source": [ - "# generate n_sample data in 2D feature space forming 1 cluster\n", - "X, labels = make_blobs(\n", - " n_samples=500,\n", - " n_features=20,\n", - " # centers=np.array([[0.0, 0.0]]),\n", - " random_state=42,\n", - ")\n", - "# binarize the fetures\n", - "# Calculate median for each feature\n", - "median_threshold = np.median(X, axis=0)\n", - "X = (X > median_threshold).astype(int)\n", - "\n", - "# compute the (n_sample, n_sample) pairwise distance matrix\n", - "X_dist = pairwise_distances(X, metric=\"euclidean\")\n", - "\n", - "print(\"Shape of data = \", X.shape)\n", - "print(\"Shape of labels = \", labels.shape)\n", - "print(\"Unique labels = \", np.unique(labels))\n", - "print(\"Cluster size = \", np.count_nonzero(labels == 0))\n", - "print(\"Shape of the distance array = \", X_dist.shape)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Perform the Subset Selection" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [], - "source": [ - "from scipy.spatial.distance import pdist, squareform\n", - "\n", - "# select data using distance base methods\n", - "# ---------------------------------------\n", - "size = 50\n", - "\n", - "collector = MaxMin()\n", - "index_maxmin = collector.select(X_dist, size=size)\n", - "\n", - "collector = MaxSum(fun_dist=lambda x: squareform(pdist(x, metric=\"minkowski\", p=0.1)))\n", - "index_maxsum = collector.select(X, size=size)\n", - "\n", - "collector = OptiSim(ref_index=0, tol=0.1)\n", - "index_optisim = collector.select(X_dist, size=size)\n", - "\n", - "collector = DISE(ref_index=0, p=2.0)\n", - "index_dise = collector.select(X, size=size)" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "data": { - "text/markdown": [ - "**Diversity of Selected Sets**\n", - "\n", - "| | logdet | wdud | shannon_entropy | hypersphere_overlap |\n", - "|---------|--------------------|---------------------|--------------------|---------------------|\n", - "| MaxMin | 44.143 | 0.273 | 18.637 | 1299.615 |\n", - "| MaxSum | 33.938 | 0.261 | 19.379 | 4396.672 |\n", - "| OptiSim | 43.734 | 0.254 | 19.758 | 1175.49 |\n", - "| DISE | 45.402 | 0.268 | 18.958 | 1363.434 |\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "div_measure = [\"logdet\", \"wdud\", \"shannon_entropy\", \"hypersphere_overlap\"]\n", - "seleced_sets = zip(\n", - " [\"MaxMin\", \"MaxSum\", \"OptiSim\", \"DISE\"],\n", - " [index_maxmin, index_maxsum, index_optisim, index_dise],\n", - ")\n", - "\n", - "# compute the diversity of the selected sets and render the results in a table\n", - "table_data = [[\"\"] + div_measure]\n", - "for i in seleced_sets:\n", - " div_data = [i[0]]\n", - " for m in div_measure:\n", - " if m != \"hypersphere_overlap\":\n", - " div_data.append(compute_diversity(X[i[1]], div_type=m))\n", - " else:\n", - " div_data.append(hypersphere_overlap_of_subset(x=X, x_subset=X[i[1]]))\n", - " table_data.append(div_data)\n", - "\n", - "render_table(table_data, caption=\"Diversity of Selected Sets\")" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "selector_div", - "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.11.9" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Tutorial Diversity Measures\n", + "\n", + "This tutorial demonstrates how to quantify the diversity of selected subset with `diversity` module as implemented in\n", + "`selector` package. The diversity measures are calculated based on the feature matrix of the selected subset." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import sys\n", + "import warnings\n", + "\n", + "warnings.filterwarnings(\"ignore\")\n", + "\n", + "# uncomment the following line to run the code for your own project directory\n", + "# sys.path.append(\"/Users/Someone/Documents/projects/Selector\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.pylab as plt\n", + "import numpy as np\n", + "from sklearn.datasets import make_blobs\n", + "from sklearn.metrics.pairwise import pairwise_distances\n", + "from IPython.display import Markdown\n", + "\n", + "from selector.methods.distance import MaxMin, MaxSum, OptiSim, DISE\n", + "from selector.measures.diversity import compute_diversity, hypersphere_overlap_of_subset" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Utility Function for Showing Diversity Measures as A Table\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "# define function to render tables easier\n", + "\n", + "\n", + "def render_table(data, caption=None, decimals=3):\n", + " \"\"\"Renders a list of lists in ta markdown table for easy visualization.\n", + "\n", + " Parameters\n", + " ----------\n", + " data : list of lists\n", + " The data to be rendered in a table, each inner list represents a row with the first row\n", + " being the header.\n", + " caption : str, optional\n", + " The caption of the table.\n", + " decimals : int, optional\n", + " The number of decimal places to round the data to.\n", + " \"\"\"\n", + "\n", + " # check all rows have the same number of columns\n", + " if not all(len(row) == len(data[0]) for row in data):\n", + " raise ValueError(\"Expect all rows to have the same number of columns.\")\n", + "\n", + " if caption is not None:\n", + " # check if caption is a string\n", + " if not isinstance(caption, str):\n", + " raise ValueError(\"Expect caption to be a string.\")\n", + " tmp_output = f\"**{caption}**\\n\\n\"\n", + "\n", + " # get the width of each column (transpose the data list and get the max length of each new row)\n", + " colwidths = [max(len(str(s)) for s in col) + 2 for col in zip(*data)]\n", + "\n", + " # construct the header row\n", + " header = f\"| {' | '.join(f'{str(s):^{w}}' for s, w in zip(data[0], colwidths))} |\"\n", + " tmp_output += header + \"\\n\"\n", + "\n", + " # construct a separator row\n", + " separator = f\"|{'|'.join(['-' * w for w in colwidths])}|\"\n", + " tmp_output += separator + \"\\n\"\n", + "\n", + " # construct the data rows\n", + " for row in data[1:]:\n", + " # round the data to the specified number of decimal places\n", + " row = [round(s, decimals) if isinstance(s, float) else s for s in row]\n", + " row_str = f\"| {' | '.join(f'{str(s):^{w}}' for s, w in zip(row, colwidths))} |\"\n", + " tmp_output += row_str + \"\\n\"\n", + "\n", + " return display(Markdown(tmp_output))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Generating Data\n", + "\n", + "The data should be provided as:\n", + "\n", + "- either an array `X` of shape `(n_samples, n_features)` encoding `n_samples` samples (rows) each in `n_features`-dimensional (columns) feature space,\n", + "- or an array `X_dist` of shape `(n_samples, n_samples)` encoding the distance (i.e., dissimilarity) between each pair of `n_samples` sample points.\n", + "\n", + "This data can be loaded from various file formats (e.g., csv, npz, txt, etc.) or generated using various libraries on the fly. In this tutorial, we use [`sklearn.datasets.make_blobs`](https://scikit-learn.org/stable/modules/generated/sklearn.datasets.make_blobs.html) to generate cluster(s) of `n_samples` points in 2-dimensions (`n-features=2`), so that it can be easily visualized. However, the same functionality can be applied to higher dimensional datasets.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Shape of data = (500, 20)\n", + "Shape of labels = (500,)\n", + "Unique labels = [0 1 2]\n", + "Cluster size = 167\n", + "Shape of the distance array = (500, 500)\n" + ] + } + ], + "source": [ + "# generate n_sample data in 2D feature space forming 1 cluster\n", + "X, labels = make_blobs(\n", + " n_samples=500,\n", + " n_features=20,\n", + " # centers=np.array([[0.0, 0.0]]),\n", + " random_state=42,\n", + ")\n", + "# binarize the fetures\n", + "# Calculate median for each feature\n", + "median_threshold = np.median(X, axis=0)\n", + "X = (X > median_threshold).astype(int)\n", + "\n", + "# compute the (n_sample, n_sample) pairwise distance matrix\n", + "X_dist = pairwise_distances(X, metric=\"euclidean\")\n", + "\n", + "print(\"Shape of data = \", X.shape)\n", + "print(\"Shape of labels = \", labels.shape)\n", + "print(\"Unique labels = \", np.unique(labels))\n", + "print(\"Cluster size = \", np.count_nonzero(labels == 0))\n", + "print(\"Shape of the distance array = \", X_dist.shape)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Perform the Subset Selection" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "from scipy.spatial.distance import pdist, squareform\n", + "\n", + "# select data using distance base methods\n", + "# ---------------------------------------\n", + "size = 50\n", + "\n", + "collector = MaxMin()\n", + "index_maxmin = collector.select(X_dist, size=size)\n", + "\n", + "collector = MaxSum(fun_dist=lambda x: squareform(pdist(x, metric=\"minkowski\", p=0.1)))\n", + "index_maxsum = collector.select(X, size=size)\n", + "\n", + "collector = OptiSim(ref_index=0, tol=0.1)\n", + "index_optisim = collector.select(X_dist, size=size)\n", + "\n", + "collector = DISE(ref_index=0, p=2.0)\n", + "index_dise = collector.select(X, size=size)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "**Diversity of Selected Sets**\n", + "\n", + "| | logdet | wdud | shannon_entropy | hypersphere_overlap |\n", + "|---------|--------------------|---------------------|--------------------|---------------------|\n", + "| MaxMin | 44.143 | 0.273 | 18.637 | 1299.615 |\n", + "| MaxSum | 33.938 | 0.261 | 19.379 | 4396.672 |\n", + "| OptiSim | 43.734 | 0.254 | 19.758 | 1175.49 |\n", + "| DISE | 45.402 | 0.268 | 18.958 | 1363.434 |\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "div_measure = [\"logdet\", \"wdud\", \"shannon_entropy\", \"hypersphere_overlap\"]\n", + "seleced_sets = zip(\n", + " [\"MaxMin\", \"MaxSum\", \"OptiSim\", \"DISE\"],\n", + " [index_maxmin, index_maxsum, index_optisim, index_dise],\n", + ")\n", + "\n", + "# compute the diversity of the selected sets and render the results in a table\n", + "table_data = [[\"\"] + div_measure]\n", + "for i in seleced_sets:\n", + " div_data = [i[0]]\n", + " for m in div_measure:\n", + " if m != \"hypersphere_overlap\":\n", + " div_data.append(compute_diversity(X[i[1]], div_type=m))\n", + " else:\n", + " div_data.append(hypersphere_overlap_of_subset(x=X, x_subset=X[i[1]]))\n", + " table_data.append(div_data)\n", + "\n", + "render_table(table_data, caption=\"Diversity of Selected Sets\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "selector_div", + "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.11.9" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/notebooks/tutorial_image_classification.ipynb b/notebooks/tutorial_image_classification.ipynb index b2277deb..49e2a5f0 100644 --- a/notebooks/tutorial_image_classification.ipynb +++ b/notebooks/tutorial_image_classification.ipynb @@ -1,390 +1,390 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "29092fcb", - "metadata": {}, - "source": [ - "# Tutorial Image Classification" - ] - }, - { - "cell_type": "markdown", - "id": "5a3cc2f6", - "metadata": {}, - "source": [ - "In this tutorial, we show how the Selector library can be used for image classification tasks. We\n", - "will select different percentages of the MINST dataset and evaluate the performances of a simple\n", - "support vector machine (SVM) classifier on the selected subsets. We will compare the results of\n", - "different selection methods with the random selection baseline.\n" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "5602017a", - "metadata": {}, - "outputs": [], - "source": [ - "# based on https://scikit-learn.org/stable/auto_examples/classification/plot_digits_classification.html\n", - "import matplotlib.pyplot as plt\n", - "\n", - "import numpy as np\n", - "from sklearn import datasets, metrics, svm\n", - "from sklearn.metrics import pairwise_distances\n", - "from sklearn.model_selection import train_test_split\n", - "from selector.methods import MaxMin, MaxSum, DISE, OptiSim, GridPartition" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "b8ac2044", - "metadata": {}, - "outputs": [], - "source": [ - "# load dataset\n", - "digits = datasets.load_digits()\n", - "data = digits.images.reshape((len(digits.images), -1))" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "c7b7bd1e", - "metadata": {}, - "outputs": [], - "source": [ - "# split into training and test sets\n", - "X_train, X_test, y_train, y_test = train_test_split(\n", - " data, digits.target, test_size=0.4, shuffle=True, random_state=42\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "a41e45fb", - "metadata": {}, - "outputs": [], - "source": [ - "# set up the selection methods\n", - "methods = {\n", - " \"MaxMin\": MaxMin(),\n", - " \"MaxSum\": MaxSum(),\n", - " \"DISE\": DISE(ref_index=0, p=2.0),\n", - " \"OptiSim\": OptiSim(ref_index=0, tol=0.1),\n", - "}" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "6ff6b194", - "metadata": {}, - "outputs": [], - "source": [ - "# define the percentages of data to select\n", - "percentages = np.linspace(0.05, 1.0, 15)\n", - "sizes = [int(p * X_train.shape[0]) for p in percentages]" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "7cb54cde", - "metadata": {}, - "outputs": [], - "source": [ - "# compute the pairwise distance of X_train\n", - "X_train_dist = pairwise_distances(X_train)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8f36b0be", - "metadata": {}, - "outputs": [], - "source": [ - "# perform the subset selection and classification\n", - "results_accuracies = {}\n", - "results_f1_scores = {}\n", - "\n", - "for method_name in methods.keys():\n", - " results_accuracies[method_name] = []\n", - " results_f1_scores[method_name] = []\n", - "\n", - "# Run experiments and store results\n", - "for method_name, method in methods.items():\n", - " print(f\"Method: {method_name}\")\n", - " method_accuracies = []\n", - " method_f1_scores = []\n", - " for p, size in zip(percentages, sizes):\n", - " if p == 1.0:\n", - " # use the whole training set\n", - " X_train_reduced = X_train\n", - " y_train_reduced = y_train\n", - "\n", - " # when p > 0.5, we can select the samples to drop instead of to keep to speed up\n", - " elif p > 0.5 and p < 1.0:\n", - " p_tmp = 1.0 - p\n", - " size_tmp = int(p_tmp * X_train.shape[0])\n", - " # select a subset of the training set to remove\n", - " picker = method\n", - " selected_indices_to_drop = picker.select(X_train_dist, size=size_tmp)\n", - " # get the selected indices to keep\n", - " selected_indices = np.setdiff1d(np.arange(X_train.shape[0]), selected_indices_to_drop)\n", - " X_train_reduced = X_train[selected_indices]\n", - " y_train_reduced = y_train[selected_indices]\n", - "\n", - " else:\n", - " # select a subset of the training set\n", - " picker = method\n", - " selected_indices = picker.select(X_train_dist, size=size)\n", - " X_train_reduced = X_train[selected_indices]\n", - " y_train_reduced = y_train[selected_indices]\n", - "\n", - " actual_percentage = X_train_reduced.shape[0] / X_train.shape[0]\n", - "\n", - " # create a support vector classifier\n", - " clf = svm.SVC(gamma=0.001)\n", - " clf.fit(X_train_reduced, y_train_reduced)\n", - " y_test_pred = clf.predict(X_test)\n", - "\n", - " accuracy = metrics.accuracy_score(y_test, y_test_pred)\n", - " method_accuracies.append((actual_percentage, accuracy))\n", - " print(f\" Percentage: {actual_percentage:.2f}, Accuracy: {accuracy:.4f}\")\n", - "\n", - " f1 = metrics.f1_score(y_test, y_test_pred, average=\"weighted\")\n", - " method_f1_scores.append((actual_percentage, f1))\n", - "\n", - " results_accuracies[method_name] = method_accuracies\n", - " results_f1_scores[method_name] = method_f1_scores" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "89c23ea5", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Method: Random\n", - "Percentage: 0.05, Accuracy: 0.7224\n", - "Percentage: 0.12, Accuracy: 0.9209\n", - "Percentage: 0.19, Accuracy: 0.9480\n", - "Percentage: 0.25, Accuracy: 0.9651\n", - "Percentage: 0.32, Accuracy: 0.9733\n", - "Percentage: 0.39, Accuracy: 0.9803\n", - "Percentage: 0.46, Accuracy: 0.9834\n", - "Percentage: 0.53, Accuracy: 0.9855\n", - "Percentage: 0.59, Accuracy: 0.9857\n", - "Percentage: 0.66, Accuracy: 0.9878\n", - "Percentage: 0.73, Accuracy: 0.9900\n", - "Percentage: 0.80, Accuracy: 0.9907\n", - "Percentage: 0.86, Accuracy: 0.9905\n", - "Percentage: 0.93, Accuracy: 0.9917\n", - "Percentage: 1.00, Accuracy: 0.9930\n" - ] - } - ], - "source": [ - "# add random selection as baseline\n", - "print(\"Method: Random\")\n", - "random_accuracies = []\n", - "random_f1_scores = []\n", - "\n", - "for p, size in zip(percentages, sizes):\n", - " random_accuracies_tmp = []\n", - " random_f1_scores_tmp = []\n", - "\n", - " for i in range(10): # Run 10 trials\n", - " rng = np.random.default_rng(seed=42 + i)\n", - " random_indices = rng.choice(X_train.shape[0], size=size, replace=False)\n", - " X_train_reduced = X_train[random_indices]\n", - " y_train_reduced = y_train[random_indices]\n", - "\n", - " clf = svm.SVC(gamma=0.001)\n", - " clf.fit(X_train_reduced, y_train_reduced)\n", - " y_test_pred = clf.predict(X_test)\n", - "\n", - " accuracy = metrics.accuracy_score(y_test, y_test_pred)\n", - " random_accuracies_tmp.append(accuracy)\n", - " f1 = metrics.f1_score(y_test, y_test_pred, average=\"weighted\")\n", - " random_f1_scores_tmp.append(f1)\n", - "\n", - " accuracy = np.mean(random_accuracies_tmp)\n", - " random_accuracies.append((p, accuracy))\n", - " f1_score = np.mean(random_f1_scores_tmp)\n", - " random_f1_scores.append((p, f1_score))\n", - " print(f\"Percentage: {p:.2f}, Accuracy: {accuracy:.4f}\")\n", - "\n", - "results_accuracies[\"Random\"] = random_accuracies\n", - "results_f1_scores[\"Random\"] = random_f1_scores" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "d2d75dc3", - "metadata": {}, - "outputs": [], - "source": [ - "markers = [\"o\", \"*\", \"^\", \"s\", \"p\", \"x\", \">\", \"<\", \"|\", \"v\", \"_\"]" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "85d7528d", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "# Plot the results for accuracies\n", - "plt.figure(figsize=(6, 4))\n", - "\n", - "for idx, (method_name, accuracies) in enumerate(results_accuracies.items()):\n", - " plt.plot(\n", - " [a[0] for a in accuracies],\n", - " [a[1] for a in accuracies],\n", - " marker=markers[idx],\n", - " label=method_name,\n", - " linewidth=2,\n", - " markersize=7,\n", - " )\n", - "\n", - "plt.xlabel(\"Percentages of Training Data\")\n", - "plt.ylabel(\"Accuracy\")\n", - "plt.legend()\n", - "plt.grid(True, alpha=0.3)\n", - "plt.xlim(0, 1.05)\n", - "# plt.ylim(0.75, 1.00)\n", - "plt.title(\"Accuracy vs Different Subsets\")\n", - "\n", - "# save the figure\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "f5eb9bd5", - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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M0R/j++++060f1++fLloilZUVIT2CguM1iDHUmCwBYNhGMYuxelARnLdsv87efu+b623l9S6nN3M8OHDhcigSV+B1klcDBs2zLxt1apVmDBhgmigSa3bzz//fBw/ftz8+CeffIKgoCAcPXrUvO2OO+5A3759UVFRgf3794v933nnHZxxxhno0qULxo8fj2effVbcJ9avXy+sJpaCIzk5WWw7ceKEuL906VJxDitXrhTHpqZkl19+uXiNZcuWoWvXrqIVPLWNNxqN8DQsMFrbgkExGAzDMEx9vpgNfDC5binPk7fTreX2zy/32CnceOONWLJkifn+4sWLccMNN1jtU15ejvvuuw///vsv1qxZIzrwXnzxxaIrL3Hdddfh3HPPxdVXXy06nP7yyy/46KOP8PnnnyMgIADR0dHiOd98802zJ34SE2+99Ra+/PJLITRImNC5/Prrr2L59NNP8f7774vX8jTcNaY1BYZfKBAU29pnwzAM07K8Pxkoy4EWEgAnQe7VpTYbJJvbWgpPAq+6cLFGGXu3/tWoU73mmmvw0EMP4eTJk+L+pk2bhNuEJm6FSy+91Oo5JEKio6Nx4MABDBw4UGyjSX3w4MHCekBWkCeffBIjRowQjyUkJAhR8MADD+Cpp57CyJEjMXXqVCFIunfv3mh3y7vvviueR2KGzu2zzz5Ddna2sKL0799fHHvdunWYM2cOPAkLjJamqgQoSZfXuQcJwzAdkbIcqJRMOndQUyovHoCEwnnnnSfcD5IkifWoqCirfcj18fjjj2Pbtm3Iy8szWy5OnTplFhjkmvj4448xc+ZMjBs3Dg8++GC9wFGydJBw2bp1K1asWIGFCxfip59+EvEZrkIWkR49eohzJWJjY4VrhMSFAm3LycmBp2GB0dLkHalb5wJbDMN0RIJiam0QsgVD5Upqv768/nZdoGwJbsTrNtVNctddd4n1RYsW1Xv8ggsuEHETH374ocgCIYExcOBA1NTUWO23YcMGaDQaZGZmCrdKcHCw1eN0n45FC8VfkBihWxIY5EIhFOGgWCts0el0VvcpRsPeNkUEeRIWGC0NV/BkGKajQ24KSRImfK1W27Al97cFwLb3a+9YuFWGXwec84LHT/fss88WYoEmZpr0LcnPzxdZHyQuJk6cKLZt3Lix3jE2b96MF198ET///DMWLFggBAsFXjqCXosC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VavEZEuTriXLli0TE8a2bdvw0ksvCdfN6tWrxWP//POPuF2yZImY/JT7NKmce+65WLNmDXbt2iXO9YILLhATvAKdW0ZGhph4vv32WxH7YDup0PukbTSR7dixQ0xuZ555JgoKCsTjV199NRITE8Xr0uM0wZMZ3x5k0SFxQc/966+/xHtISUkRVgmCbhURtH379nrWCFeh93z48GFx/JUrV4ptZBV55plnhCCiyZyECwkEZ9Dn+corr4jJd8OGDWLsSGQ6w9lnRVYtEiQkiOhxGu9HHnkETYW+O0OGDMF3331n3kZxK/Rdo+8fncvatWuF4FHcQCQeSdgp1h7l/TRlfBjGKR7t1cow7QjLNucmk0lavXq1aM393//+Vzp58qSk0Wik9PR0q+eceeaZ0kMPPSTWqfUx/UklJyebHz98+LDYRseyxzPPPCOdddZZVttOnz4tnkPPJajl8oQJE6z2GTVqlLRgwQLzfdr/+++/b/A9DhgwQLTRJg4ePCie988//5gfP3r0qNj2+uuvi/t///23FBISIlVVVVkdh9pqv//++2I9ODhYWrp0qeQKf/zxhxjHU6dOmbft379fvOb27dvF/V27don7qampLh2Txueee+6x+hxjY2Ol6upqp8+j902vU1paatX+WmkRrnyex44dMz9n0aJF4tj2vjOufFa//fabpNVqpczMTPPj9N1o6POzfR1L5syZI/Xr18/hc1esWCFFRkaa79P7Cg0NlRrCdnwYprFoncsPhulY0NUuWRfoao6utslMTCZkusKnq8/evXtb7U/uj8jISPN9MtcPHjzYfD85ORkajQaTJ0+2+3p0tbhu3TqzRcMScnEor2d5TIJiExoyX5MFg879l19+EVeq5KevrKw0WzDoCl+r1QqLhAK5b8LDw63Oj45j+R4JOg6dH3HfffcJFwpd5ZNLiSwePXr0sHtOZMEhi4SlVYLcBOSKoMfIjeMOyEVAn4UlZF2h8aD3VFhYaI6PofGgc7AHWRos34sr4+7ss6Ixp/dOLgiF0aNHozmQvrSMGyEL0PPPPy9cMRQwS597VVWVsMbYxrM0d3wYxhksMBjGAoolePfdd8XkRP57moAJmmRJKNCPMN1aYikOyKVi+WNP951BxyW3BblVbKGJScHW5UCv0VAAKZm+yTRPJn4SDnQul112mctBj8r50XlYxpooKMGNNCmRECMhQ26UJ554QriRKCaktSAXhSXl5eWYOXOmWD7//HMRT0ITJ913Nh72xl02GDmmKZ9VcyBhRvEzBLk1KOiT4ocoBoXiQDZu3IibbrpJvE9HAqOp48MwzmCBwTA2ExNNxrZQjARZMOhKdOLEiY26kqbJheIN6OreFrIeUOwDBVYqYqYp0KRG52fJpk2bhA9dmehJLFgGTFLwI13dUnwGBWYSx44dE1evlueXlZUlzk0JHrUHWVpomT9/Pq688koRD2JPYFCw5OnTp8WiWDEOHDggYlE8eZVMV/P5+fl44YUXzK/rLBDVU9CY03unOBsKviWUmJmmQPEVe/fuFeNOkACm79urr74qYjGIr7/+2uo5JJ5tvyttZXwY74KDPBnGBWjypGBGCoqkgLrU1FQRhEimaLpydwRNynPnzsWNN94oAufoeWQNUH7077zzThHwSJMyTTTkdqCsBYr0t50EnEGvQ4GNJAYUgdCrVy9xruSmIbM3WRksr6T79u0rRA/VmaD3QkKD1i2tMPQ4pYFSYOIff/whBMrmzZtFYCJNQOQqoeBXek8nT54UoobeBwkJe9DxSHTRWO7cuVO8Lo0puZAog8FTdO7cWUysb7/9tggqpUwfCmhsaah2Bblc6DtBgcI0Xo8++qh4rKH0WHLH0edLtUFo7BYuXCgCZsliQWNIkDgm957yPslt9d5779X7rpDYpO8LZSuR66StjA/jXbDAYBgXoaty+iGn+hh0JUqTLk2m9OPsDHK5kGuC0gVpUqeaDWSSJsgNQ5MMiYmzzjpLTL733nuvcD8oV6CuQFes5A6hq0+ytijpihRPQZkD5IYhc7dlvAXxySefiCvpSZMmCYsDnRulKVIKpTLp/frrr+JxEj0ktK644gohJuh55C6iK18aF3qMsl8o5fapp56ye550PEqtpPOiY5LgoHTU5cuXw5OQyZ9SOVesWCEsJXSlTq6jlobGi4QmTfAUb0KxK0oWiTLmjqAMI3JXkUCgjCCK3aFsERpPxW1HGSX0uZPLbeDAgcLdQSLYEvo+3HbbbSJjh8aFMl3ayvgw3oWKIj1b+yQYhmkbpKWlCZFCgYKUisp4HhKYVBeD3FOOgmMZpj3CAoNhOjDkw6erabKcUKYJ1UsgE/yRI0cc1rJgmsf3338vAoPJhUWigqpxkkWHgjEZxpvgIE+G6cCQv54qQpLfnVwjZD4nszqLC89RWloqKrtSlkZUVJRwE5GLi2G8DbZgMAzDMAzjdjjIk2EYhmEYt8MCg2EYhmEYt8MCg2EYhmEYt8MCg2EYhmEYt8MCg2EYhmEYt8MCg2EYhmEYt8MCg2EYhmEYt8MCg2EYhmEYuJv/B3ehSyZgEy66AAAAAElFTkSuQmCC", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "# Plot the results for F1 scores\n", - "plt.figure(figsize=(6, 4))\n", - "for idx, (method_name, f1_scores) in enumerate(results_f1_scores.items()):\n", - " plt.plot(\n", - " [a[0] for a in f1_scores],\n", - " [a[1] for a in f1_scores],\n", - " marker=markers[idx],\n", - " label=method_name,\n", - " linewidth=2,\n", - " markersize=7,\n", - " )\n", - "\n", - "plt.xlabel(\"Percentages of Training Data\")\n", - "plt.ylabel(\"F1 Score\")\n", - "plt.legend()\n", - "plt.grid(True, alpha=0.3)\n", - "plt.xlim(0, 1.05)\n", - "# plt.ylim(0.75, 1.00)\n", - "plt.title(\"F1 Score vs Different Subsets\")\n", - "\n", - "# save the figure\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "id": "f8e12294", - "metadata": {}, - "source": [ - "Based on the results, we can notiece that:\n", - "- Selecting subsets of data can achieve comparable performance to using the full dataset. For\n", - " example, selecting ~20% of data, different selection methods can achieve over 95% accuracy (except\n", - " MaxSum). This holds for F1 scores as well.\n", - "- Random sampling performance is not satisfactory when the subset size is small. For example, when\n", - " selecting only 5% of data, random sampling achieves only around 70% accuracy and F1 score of 0.7, \n", - " while other methods are better. This trends hold until the subset size reaches around 50%. Once we\n", - " have enough data as training subset, we noticed that random sampling can achieve comparable performance\n", - " to other methods. This is because we have enough data to cover the data distribution well with random\n", - " sampling in such cases. Therefore, these subset selection methods are more useful when we have limited\n", - " labeling budget and can only select small subsets of data for training.\n", - "- The MaxSum algorithm consistently underperforms compared to other selection methods across different subset sizes.\n", - " This suggests that MaxSum may not be as effective for selecting representative subsets of data\n", - " for image classification tasks on the MNIST dataset as it tends to select outliers or less\n", - " informative samples. This indicates the potential usage of MaxSum for outlier detection tasks." - ] - }, - { - "cell_type": "markdown", - "id": "8301c517", - "metadata": {}, - "source": [ - "*Limitations*\n", - "\n", - "This tutorial uses a simple SVM classifier for demonstration purposes. In practice, more advanced\n", - "neural network architectures should be used for image classification tasks to achieve better\n", - "performance.\n", - "The dataset used in this tutorial is the MNIST dataset from scikit-learn, which is\n", - "relatively simple and small.\n", - "To better evaluate the effectiveness of different subset selection methods, larger and more\n", - "complex datasets such as CIFAR-10 or ImageNet should be used in practice. Papers such as:\n", - "[Grad-Match: Gradient Matching Based Data Subset Selection for Efficient Deep Model Training,\n", - "International Conference on Machine Learning,\n", - "2021](https://proceedings.mlr.press/v139/killamsetty21a/killamsetty21a.pdf) and [Dataset Efficient\n", - "Training with Model Ensembling, IEEE Computer Society Conference on Computer Vision and Pattern\n", - "Recognition Workshops (CVPRW), 2023](https://openaccess.thecvf.com/content/CVPR2023W/ECV/html/Ro_Dataset_Efficient_Training_With_Model_Ensembling_CVPRW_2023_paper.html)." - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "chem_py312", - "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.12.8" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} +{ + "cells": [ + { + "cell_type": "markdown", + "id": "29092fcb", + "metadata": {}, + "source": [ + "# Tutorial Image Classification" + ] + }, + { + "cell_type": "markdown", + "id": "5a3cc2f6", + "metadata": {}, + "source": [ + "In this tutorial, we show how the Selector library can be used for image classification tasks. We\n", + "will select different percentages of the MINST dataset and evaluate the performances of a simple\n", + "support vector machine (SVM) classifier on the selected subsets. We will compare the results of\n", + "different selection methods with the random selection baseline.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "5602017a", + "metadata": {}, + "outputs": [], + "source": [ + "# based on https://scikit-learn.org/stable/auto_examples/classification/plot_digits_classification.html\n", + "import matplotlib.pyplot as plt\n", + "\n", + "import numpy as np\n", + "from sklearn import datasets, metrics, svm\n", + "from sklearn.metrics import pairwise_distances\n", + "from sklearn.model_selection import train_test_split\n", + "from selector.methods import MaxMin, MaxSum, DISE, OptiSim, GridPartition" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "b8ac2044", + "metadata": {}, + "outputs": [], + "source": [ + "# load dataset\n", + "digits = datasets.load_digits()\n", + "data = digits.images.reshape((len(digits.images), -1))" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "c7b7bd1e", + "metadata": {}, + "outputs": [], + "source": [ + "# split into training and test sets\n", + "X_train, X_test, y_train, y_test = train_test_split(\n", + " data, digits.target, test_size=0.4, shuffle=True, random_state=42\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "a41e45fb", + "metadata": {}, + "outputs": [], + "source": [ + "# set up the selection methods\n", + "methods = {\n", + " \"MaxMin\": MaxMin(),\n", + " \"MaxSum\": MaxSum(),\n", + " \"DISE\": DISE(ref_index=0, p=2.0),\n", + " \"OptiSim\": OptiSim(ref_index=0, tol=0.1),\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "6ff6b194", + "metadata": {}, + "outputs": [], + "source": [ + "# define the percentages of data to select\n", + "percentages = np.linspace(0.05, 1.0, 15)\n", + "sizes = [int(p * X_train.shape[0]) for p in percentages]" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "7cb54cde", + "metadata": {}, + "outputs": [], + "source": [ + "# compute the pairwise distance of X_train\n", + "X_train_dist = pairwise_distances(X_train)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8f36b0be", + "metadata": {}, + "outputs": [], + "source": [ + "# perform the subset selection and classification\n", + "results_accuracies = {}\n", + "results_f1_scores = {}\n", + "\n", + "for method_name in methods.keys():\n", + " results_accuracies[method_name] = []\n", + " results_f1_scores[method_name] = []\n", + "\n", + "# Run experiments and store results\n", + "for method_name, method in methods.items():\n", + " print(f\"Method: {method_name}\")\n", + " method_accuracies = []\n", + " method_f1_scores = []\n", + " for p, size in zip(percentages, sizes):\n", + " if p == 1.0:\n", + " # use the whole training set\n", + " X_train_reduced = X_train\n", + " y_train_reduced = y_train\n", + "\n", + " # when p > 0.5, we can select the samples to drop instead of to keep to speed up\n", + " elif p > 0.5 and p < 1.0:\n", + " p_tmp = 1.0 - p\n", + " size_tmp = int(p_tmp * X_train.shape[0])\n", + " # select a subset of the training set to remove\n", + " picker = method\n", + " selected_indices_to_drop = picker.select(X_train_dist, size=size_tmp)\n", + " # get the selected indices to keep\n", + " selected_indices = np.setdiff1d(np.arange(X_train.shape[0]), selected_indices_to_drop)\n", + " X_train_reduced = X_train[selected_indices]\n", + " y_train_reduced = y_train[selected_indices]\n", + "\n", + " else:\n", + " # select a subset of the training set\n", + " picker = method\n", + " selected_indices = picker.select(X_train_dist, size=size)\n", + " X_train_reduced = X_train[selected_indices]\n", + " y_train_reduced = y_train[selected_indices]\n", + "\n", + " actual_percentage = X_train_reduced.shape[0] / X_train.shape[0]\n", + "\n", + " # create a support vector classifier\n", + " clf = svm.SVC(gamma=0.001)\n", + " clf.fit(X_train_reduced, y_train_reduced)\n", + " y_test_pred = clf.predict(X_test)\n", + "\n", + " accuracy = metrics.accuracy_score(y_test, y_test_pred)\n", + " method_accuracies.append((actual_percentage, accuracy))\n", + " print(f\" Percentage: {actual_percentage:.2f}, Accuracy: {accuracy:.4f}\")\n", + "\n", + " f1 = metrics.f1_score(y_test, y_test_pred, average=\"weighted\")\n", + " method_f1_scores.append((actual_percentage, f1))\n", + "\n", + " results_accuracies[method_name] = method_accuracies\n", + " results_f1_scores[method_name] = method_f1_scores" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "89c23ea5", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Method: Random\n", + "Percentage: 0.05, Accuracy: 0.7224\n", + "Percentage: 0.12, Accuracy: 0.9209\n", + "Percentage: 0.19, Accuracy: 0.9480\n", + "Percentage: 0.25, Accuracy: 0.9651\n", + "Percentage: 0.32, Accuracy: 0.9733\n", + "Percentage: 0.39, Accuracy: 0.9803\n", + "Percentage: 0.46, Accuracy: 0.9834\n", + "Percentage: 0.53, Accuracy: 0.9855\n", + "Percentage: 0.59, Accuracy: 0.9857\n", + "Percentage: 0.66, Accuracy: 0.9878\n", + "Percentage: 0.73, Accuracy: 0.9900\n", + "Percentage: 0.80, Accuracy: 0.9907\n", + "Percentage: 0.86, Accuracy: 0.9905\n", + "Percentage: 0.93, Accuracy: 0.9917\n", + "Percentage: 1.00, Accuracy: 0.9930\n" + ] + } + ], + "source": [ + "# add random selection as baseline\n", + "print(\"Method: Random\")\n", + "random_accuracies = []\n", + "random_f1_scores = []\n", + "\n", + "for p, size in zip(percentages, sizes):\n", + " random_accuracies_tmp = []\n", + " random_f1_scores_tmp = []\n", + "\n", + " for i in range(10): # Run 10 trials\n", + " rng = np.random.default_rng(seed=42 + i)\n", + " random_indices = rng.choice(X_train.shape[0], size=size, replace=False)\n", + " X_train_reduced = X_train[random_indices]\n", + " y_train_reduced = y_train[random_indices]\n", + "\n", + " clf = svm.SVC(gamma=0.001)\n", + " clf.fit(X_train_reduced, y_train_reduced)\n", + " y_test_pred = clf.predict(X_test)\n", + "\n", + " accuracy = metrics.accuracy_score(y_test, y_test_pred)\n", + " random_accuracies_tmp.append(accuracy)\n", + " f1 = metrics.f1_score(y_test, y_test_pred, average=\"weighted\")\n", + " random_f1_scores_tmp.append(f1)\n", + "\n", + " accuracy = np.mean(random_accuracies_tmp)\n", + " random_accuracies.append((p, accuracy))\n", + " f1_score = np.mean(random_f1_scores_tmp)\n", + " random_f1_scores.append((p, f1_score))\n", + " print(f\"Percentage: {p:.2f}, Accuracy: {accuracy:.4f}\")\n", + "\n", + "results_accuracies[\"Random\"] = random_accuracies\n", + "results_f1_scores[\"Random\"] = random_f1_scores" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "d2d75dc3", + "metadata": {}, + "outputs": [], + "source": [ + "markers = [\"o\", \"*\", \"^\", \"s\", \"p\", \"x\", \">\", \"<\", \"|\", \"v\", \"_\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "85d7528d", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Plot the results for accuracies\n", + "plt.figure(figsize=(6, 4))\n", + "\n", + "for idx, (method_name, accuracies) in enumerate(results_accuracies.items()):\n", + " plt.plot(\n", + " [a[0] for a in accuracies],\n", + " [a[1] for a in accuracies],\n", + " marker=markers[idx],\n", + " label=method_name,\n", + " linewidth=2,\n", + " markersize=7,\n", + " )\n", + "\n", + "plt.xlabel(\"Percentages of Training Data\")\n", + "plt.ylabel(\"Accuracy\")\n", + "plt.legend()\n", + "plt.grid(True, alpha=0.3)\n", + "plt.xlim(0, 1.05)\n", + "# plt.ylim(0.75, 1.00)\n", + "plt.title(\"Accuracy vs Different Subsets\")\n", + "\n", + "# save the figure\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "f5eb9bd5", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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M0R/j++++060f1++fLloilZUVIT2CguM1iDHUmCwBYNhGMYuxelARnLdsv87efu+b623l9S6nN3M8OHDhcigSV+B1klcDBs2zLxt1apVmDBhgmigSa3bzz//fBw/ftz8+CeffIKgoCAcPXrUvO2OO+5A3759UVFRgf3794v933nnHZxxxhno0qULxo8fj2effVbcJ9avXy+sJpaCIzk5WWw7ceKEuL906VJxDitXrhTHpqZkl19+uXiNZcuWoWvXrqIVPLWNNxqN8DQsMFrbgkExGAzDMEx9vpgNfDC5binPk7fTreX2zy/32CnceOONWLJkifn+4sWLccMNN1jtU15ejvvuuw///vsv1qxZIzrwXnzxxaIrL3Hdddfh3HPPxdVXXy06nP7yyy/46KOP8PnnnyMgIADR0dHiOd98802zJ34SE2+99Ra+/PJLITRImNC5/Prrr2L59NNP8f7774vX8jTcNaY1BYZfKBAU29pnwzAM07K8Pxkoy4EWEgAnQe7VpTYbJJvbWgpPAq+6cLFGGXu3/tWoU73mmmvw0EMP4eTJk+L+pk2bhNuEJm6FSy+91Oo5JEKio6Nx4MABDBw4UGyjSX3w4MHCekBWkCeffBIjRowQjyUkJAhR8MADD+Cpp57CyJEjMXXqVCFIunfv3mh3y7vvviueR2KGzu2zzz5Ddna2sKL0799fHHvdunWYM2cOPAkLjJamqgQoSZfXuQcJwzAdkbIcqJRMOndQUyovHoCEwnnnnSfcD5IkifWoqCirfcj18fjjj2Pbtm3Iy8szWy5OnTplFhjkmvj4448xc+ZMjBs3Dg8++GC9wFGydJBw2bp1K1asWIGFCxfip59+EvEZrkIWkR49eohzJWJjY4VrhMSFAm3LycmBp2GB0dLkHalb5wJbDMN0RIJiam0QsgVD5Upqv768/nZdoGwJbsTrNtVNctddd4n1RYsW1Xv8ggsuEHETH374ocgCIYExcOBA1NTUWO23YcMGaDQaZGZmCrdKcHCw1eN0n45FC8VfkBihWxIY5EIhFOGgWCts0el0VvcpRsPeNkUEeRIWGC0NV/BkGKajQ24KSRImfK1W27Al97cFwLb3a+9YuFWGXwec84LHT/fss88WYoEmZpr0LcnPzxdZHyQuJk6cKLZt3Lix3jE2b96MF198ET///DMWLFggBAsFXjqCXosC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VavEZEuTriXLli0TE8a2bdvw0ksvCdfN6tWrxWP//POPuF2yZImY/JT7NKmce+65WLNmDXbt2iXO9YILLhATvAKdW0ZGhph4vv32WxH7YDup0PukbTSR7dixQ0xuZ555JgoKCsTjV199NRITE8Xr0uM0wZMZ3x5k0SFxQc/966+/xHtISUkRVgmCbhURtH379nrWCFeh93z48GFx/JUrV4ptZBV55plnhCCiyZyECwkEZ9Dn+corr4jJd8OGDWLsSGQ6w9lnRVYtEiQkiOhxGu9HHnkETYW+O0OGDMF3331n3kZxK/Rdo+8fncvatWuF4FHcQCQeSdgp1h7l/TRlfBjGKR7t1cow7QjLNucmk0lavXq1aM393//+Vzp58qSk0Wik9PR0q+eceeaZ0kMPPSTWqfUx/UklJyebHz98+LDYRseyxzPPPCOdddZZVttOnz4tnkPPJajl8oQJE6z2GTVqlLRgwQLzfdr/+++/b/A9DhgwQLTRJg4ePCie988//5gfP3r0qNj2+uuvi/t///23FBISIlVVVVkdh9pqv//++2I9ODhYWrp0qeQKf/zxhxjHU6dOmbft379fvOb27dvF/V27don7qampLh2Txueee+6x+hxjY2Ol6upqp8+j902vU1paatX+WmkRrnyex44dMz9n0aJF4tj2vjOufFa//fabpNVqpczMTPPj9N1o6POzfR1L5syZI/Xr18/hc1esWCFFRkaa79P7Cg0NlRrCdnwYprFoncsPhulY0NUuWRfoao6utslMTCZkusKnq8/evXtb7U/uj8jISPN9MtcPHjzYfD85ORkajQaTJ0+2+3p0tbhu3TqzRcMScnEor2d5TIJiExoyX5MFg879l19+EVeq5KevrKw0WzDoCl+r1QqLhAK5b8LDw63Oj45j+R4JOg6dH3HfffcJFwpd5ZNLiSwePXr0sHtOZMEhi4SlVYLcBOSKoMfIjeMOyEVAn4UlZF2h8aD3VFhYaI6PofGgc7AHWRos34sr4+7ss6Ixp/dOLgiF0aNHozmQvrSMGyEL0PPPPy9cMRQwS597VVWVsMbYxrM0d3wYxhksMBjGAoolePfdd8XkRP57moAJmmRJKNCPMN1aYikOyKVi+WNP951BxyW3BblVbKGJScHW5UCv0VAAKZm+yTRPJn4SDnQul112mctBj8r50XlYxpooKMGNNCmRECMhQ26UJ554QriRKCaktSAXhSXl5eWYOXOmWD7//HMRT0ITJ913Nh72xl02GDmmKZ9VcyBhRvEzBLk1KOiT4ocoBoXiQDZu3IibbrpJvE9HAqOp48MwzmCBwTA2ExNNxrZQjARZMOhKdOLEiY26kqbJheIN6OreFrIeUOwDBVYqYqYp0KRG52fJpk2bhA9dmehJLFgGTFLwI13dUnwGBWYSx44dE1evlueXlZUlzk0JHrUHWVpomT9/Pq688koRD2JPYFCw5OnTp8WiWDEOHDggYlE8eZVMV/P5+fl44YUXzK/rLBDVU9CY03unOBsKviWUmJmmQPEVe/fuFeNOkACm79urr74qYjGIr7/+2uo5JJ5tvyttZXwY74KDPBnGBWjypGBGCoqkgLrU1FQRhEimaLpydwRNynPnzsWNN94oAufoeWQNUH7077zzThHwSJMyTTTkdqCsBYr0t50EnEGvQ4GNJAYUgdCrVy9xruSmIbM3WRksr6T79u0rRA/VmaD3QkKD1i2tMPQ4pYFSYOIff/whBMrmzZtFYCJNQOQqoeBXek8nT54UoobeBwkJe9DxSHTRWO7cuVO8Lo0puZAog8FTdO7cWUysb7/9tggqpUwfCmhsaah2Bblc6DtBgcI0Xo8++qh4rKH0WHLH0edLtUFo7BYuXCgCZsliQWNIkDgm957yPslt9d5779X7rpDYpO8LZSuR66StjA/jXbDAYBgXoaty+iGn+hh0JUqTLk2m9OPsDHK5kGuC0gVpUqeaDWSSJsgNQ5MMiYmzzjpLTL733nuvcD8oV6CuQFes5A6hq0+ytijpihRPQZkD5IYhc7dlvAXxySefiCvpSZMmCYsDnRulKVIKpTLp/frrr+JxEj0ktK644gohJuh55C6iK18aF3qMsl8o5fapp56ye550PEqtpPOiY5LgoHTU5cuXw5OQyZ9SOVesWCEsJXSlTq6jlobGi4QmTfAUb0KxK0oWiTLmjqAMI3JXkUCgjCCK3aFsERpPxW1HGSX0uZPLbeDAgcLdQSLYEvo+3HbbbSJjh8aFMl3ayvgw3oWKIj1b+yQYhmkbpKWlCZFCgYKUisp4HhKYVBeD3FOOgmMZpj3CAoNhOjDkw6erabKcUKYJ1UsgE/yRI0cc1rJgmsf3338vAoPJhUWigqpxkkWHgjEZxpvgIE+G6cCQv54qQpLfnVwjZD4nszqLC89RWloqKrtSlkZUVJRwE5GLi2G8DbZgMAzDMAzjdjjIk2EYhmEYt8MCg2EYhmEYt8MCg2EYhmEYt8MCg2EYhmEYt8MCg2EYhmEYt8MCg2EYhmEYt8MCg2EYhmEYt8MCg2EYhmEYuJv/B3ehSyZgEy66AAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Plot the results for F1 scores\n", + "plt.figure(figsize=(6, 4))\n", + "for idx, (method_name, f1_scores) in enumerate(results_f1_scores.items()):\n", + " plt.plot(\n", + " [a[0] for a in f1_scores],\n", + " [a[1] for a in f1_scores],\n", + " marker=markers[idx],\n", + " label=method_name,\n", + " linewidth=2,\n", + " markersize=7,\n", + " )\n", + "\n", + "plt.xlabel(\"Percentages of Training Data\")\n", + "plt.ylabel(\"F1 Score\")\n", + "plt.legend()\n", + "plt.grid(True, alpha=0.3)\n", + "plt.xlim(0, 1.05)\n", + "# plt.ylim(0.75, 1.00)\n", + "plt.title(\"F1 Score vs Different Subsets\")\n", + "\n", + "# save the figure\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "id": "f8e12294", + "metadata": {}, + "source": [ + "Based on the results, we can notiece that:\n", + "- Selecting subsets of data can achieve comparable performance to using the full dataset. For\n", + " example, selecting ~20% of data, different selection methods can achieve over 95% accuracy (except\n", + " MaxSum). This holds for F1 scores as well.\n", + "- Random sampling performance is not satisfactory when the subset size is small. For example, when\n", + " selecting only 5% of data, random sampling achieves only around 70% accuracy and F1 score of 0.7, \n", + " while other methods are better. This trends hold until the subset size reaches around 50%. Once we\n", + " have enough data as training subset, we noticed that random sampling can achieve comparable performance\n", + " to other methods. This is because we have enough data to cover the data distribution well with random\n", + " sampling in such cases. Therefore, these subset selection methods are more useful when we have limited\n", + " labeling budget and can only select small subsets of data for training.\n", + "- The MaxSum algorithm consistently underperforms compared to other selection methods across different subset sizes.\n", + " This suggests that MaxSum may not be as effective for selecting representative subsets of data\n", + " for image classification tasks on the MNIST dataset as it tends to select outliers or less\n", + " informative samples. This indicates the potential usage of MaxSum for outlier detection tasks." + ] + }, + { + "cell_type": "markdown", + "id": "8301c517", + "metadata": {}, + "source": [ + "*Limitations*\n", + "\n", + "This tutorial uses a simple SVM classifier for demonstration purposes. In practice, more advanced\n", + "neural network architectures should be used for image classification tasks to achieve better\n", + "performance.\n", + "The dataset used in this tutorial is the MNIST dataset from scikit-learn, which is\n", + "relatively simple and small.\n", + "To better evaluate the effectiveness of different subset selection methods, larger and more\n", + "complex datasets such as CIFAR-10 or ImageNet should be used in practice. Papers such as:\n", + "[Grad-Match: Gradient Matching Based Data Subset Selection for Efficient Deep Model Training,\n", + "International Conference on Machine Learning,\n", + "2021](https://proceedings.mlr.press/v139/killamsetty21a/killamsetty21a.pdf) and [Dataset Efficient\n", + "Training with Model Ensembling, IEEE Computer Society Conference on Computer Vision and Pattern\n", + "Recognition Workshops (CVPRW), 2023](https://openaccess.thecvf.com/content/CVPR2023W/ECV/html/Ro_Dataset_Efficient_Training_With_Model_Ensembling_CVPRW_2023_paper.html)." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "chem_py312", + "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.12.8" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/tutorial_partition_based.ipynb b/notebooks/tutorial_partition_based.ipynb index 45454b40..d0c24e63 100644 --- a/notebooks/tutorial_partition_based.ipynb +++ b/notebooks/tutorial_partition_based.ipynb @@ -1,550 +1,550 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Tutorial Partition-Based Selectors\n", - "\n", - "This tutorial demonstrates using partition-based selectors in `selector` package. To easily visualize the data and sampled points, we will use a 2D dataset in this tutorial. However, the same functionality can be applied to higher dimensional datasets.\n" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import sys\n", - "\n", - "# uncomment the following line to run the code for your own project directory\n", - "# sys.path.append(\"/Users/Someone/Documents/projects/Selector\")" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "import matplotlib.pylab as plt\n", - "import numpy as np\n", - "from sklearn.datasets import make_blobs\n", - "from sklearn.metrics.pairwise import pairwise_distances\n", - "from IPython.display import Markdown\n", - "\n", - "from selector.measures.diversity import compute_diversity\n", - "from selector.methods.partition import Medoid, GridPartition" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Utility Function for Plotting Data\n" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "# define a function to make visualization easier\n", - "\n", - "\n", - "def graph_data(\n", - " data,\n", - " indices=None,\n", - " labels=None,\n", - " reference=False,\n", - " title=\"\",\n", - " xlabel=\"\",\n", - " ylabel=\"\",\n", - " number=False,\n", - " fname=None,\n", - "):\n", - " \"\"\"Graphs the data in a scatter plot.\n", - "\n", - " Parameters\n", - " ----------\n", - " data : numpy.ndarray of shape (n_samples, 2)\n", - " The original data points to be graphed.\n", - " indices : list of numpy.ndarray, optional\n", - " List of indices array of the data points selected.\n", - " labels : list of str, optional\n", - " List of labels denoting method for selected indices.\n", - " reference : bool, optional\n", - " Whether to highlight the first data point.\n", - " title : str, optional\n", - " The title of the plot.\n", - " xlabel : str, optional\n", - " The label of the x-axis.\n", - " ylabel : str, optional\n", - " The label of the y-axis.\n", - " number : bool, optional\n", - " Whether to label the selected data points with numbers representing the order of selection.\n", - " fname : str, optional\n", - " Filename for saving the figure. If None, figure is shown.\n", - " \"\"\"\n", - " if data.ndim != 2 or data.shape[1] != 2:\n", - " raise ValueError(f\"Expect data to be a 2D array with 2 columns, got {data.shape}.\")\n", - "\n", - " if labels is not None and len(indices) != len(labels):\n", - " raise ValueError(\n", - " f\"Expect indices and labels to have the same length, got {len(indices)} and {len(labels)}.\"\n", - " )\n", - "\n", - " # Add a title and axis labels\n", - " plt.figure(dpi=100)\n", - " plt.title(title, fontsize=18)\n", - " plt.xlabel(xlabel, fontsize=14)\n", - " plt.ylabel(ylabel, fontsize=14)\n", - "\n", - " # plot original data\n", - " plt.scatter(data[:, 0], data[:, 1], marker=\"o\", facecolors=\"none\", edgecolors=\"0.75\")\n", - "\n", - " colors = [\"skyblue\", \"r\", \"b\", \"k\", \"g\", \"orange\", \"navy\", \"indigo\", \"pink\", \"purple\", \"yellow\"]\n", - " markers = [\"o\", \"x\", \"*\", \"_\", \"|\", \"s\", \"p\", \">\", \"<\", \"^\", \"v\"]\n", - " text_location = [(0.1, 0.1), (-0.1, 0.1)]\n", - " colors_numbers = [\"black\", \"red\", \"blue\", \"k\", \"k\", \"k\", \"k\", \"k\", \"k\", \"k\", \"k\"]\n", - "\n", - " if indices:\n", - " for index, selected_index in enumerate(indices):\n", - " plt.scatter(\n", - " data[selected_index, 0],\n", - " data[selected_index, 1],\n", - " c=colors[index],\n", - " label=labels[index] if labels is not None else None,\n", - " marker=markers[index],\n", - " )\n", - " if number:\n", - " shift_x, shift_y = text_location[index]\n", - " for i, mol_id in enumerate(selected_index):\n", - " plt.text(\n", - " data[mol_id, 0] + shift_x,\n", - " data[mol_id, 1] + shift_y,\n", - " str(i + 1),\n", - " c=colors_numbers[index],\n", - " )\n", - " if reference:\n", - " plt.scatter(data[0, 0], data[0, 1], c=\"black\")\n", - " if labels is not None:\n", - " # plt.legend(loc=\"upper left\", frameon=False)\n", - " plt.legend(loc=\"best\", frameon=False)\n", - " if fname is not None:\n", - " plt.savefig(fname, dpi=500)\n", - " else:\n", - " plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "# define function to render tables easier\n", - "\n", - "\n", - "def render_table(data, caption=None, decimals=3):\n", - " \"\"\"Renders a list of lists in ta markdown table for easy visualization.\n", - "\n", - " Parameters\n", - " ----------\n", - " data : list of lists\n", - " The data to be rendered in a table, each inner list represents a row with the first row\n", - " being the header.\n", - " caption : str, optional\n", - " The caption of the table.\n", - " decimals : int, optional\n", - " The number of decimal places to round the data to.\n", - " \"\"\"\n", - "\n", - " # check all rows have the same number of columns\n", - " if not all(len(row) == len(data[0]) for row in data):\n", - " raise ValueError(\"Expect all rows to have the same number of columns.\")\n", - "\n", - " if caption is not None:\n", - " # check if caption is a string\n", - " if not isinstance(caption, str):\n", - " raise ValueError(\"Expect caption to be a string.\")\n", - " tmp_output = f\"**{caption}**\\n\\n\"\n", - "\n", - " # get the width of each column (transpose the data list and get the max length of each new row)\n", - " colwidths = [max(len(str(s)) for s in col) + 2 for col in zip(*data)]\n", - "\n", - " # construct the header row\n", - " header = f\"| {' | '.join(f'{str(s):^{w}}' for s, w in zip(data[0], colwidths))} |\"\n", - " tmp_output += header + \"\\n\"\n", - "\n", - " # construct a separator row\n", - " separator = f\"|{'|'.join(['-' * w for w in colwidths])}|\"\n", - " tmp_output += separator + \"\\n\"\n", - "\n", - " # construct the data rows\n", - " for row in data[1:]:\n", - " # round the data to the specified number of decimal places\n", - " row = [round(s, decimals) if isinstance(s, float) else s for s in row]\n", - " row_str = f\"| {' | '.join(f'{str(s):^{w}}' for s, w in zip(row, colwidths))} |\"\n", - " tmp_output += row_str + \"\\n\"\n", - "\n", - " return display(Markdown(tmp_output))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Generating Data\n", - "\n", - "The data should be provided as:\n", - "\n", - "- either an array `X` of shape `(n_samples, n_features)` encoding `n_samples` samples (rows) each in `n_features`-dimensional (columns) feature space,\n", - "- or an array `X_dist` of shape `(n_samples, n_samples)` encoding the distance (i.e., dissimilarity) between each pair of `n_samples` sample points.\n", - "\n", - "This data can be loaded from various file formats (e.g., csv, npz, txt, etc.) or generated using various libraries on the fly. In this tutorial, we use [`sklearn.datasets.make_blobs`](https://scikit-learn.org/stable/modules/generated/sklearn.datasets.make_blobs.html) to generate cluster(s) of `n_samples` points in 2-dimensions (`n-features=2`), so that it can be easily visualized. However, the same functionality can be applied to higher dimensional datasets.\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Selecting from One Cluster\n" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Shape of data = (500, 2)\n", - "Shape of labels = (500,)\n", - "Unique labels = [0]\n", - "Cluster size = 500\n", - "Shape of the distance array = (500, 500)\n" - ] - } - ], - "source": [ - "# generate n_sample data in 2D feature space forming 1 cluster\n", - "X, labels = make_blobs(\n", - " n_samples=500,\n", - " n_features=2,\n", - " centers=np.array([[0.0, 0.0]]),\n", - " random_state=42,\n", - ")\n", - "\n", - "# compute the (n_sample, n_sample) pairwise distance matrix\n", - "X_dist = pairwise_distances(X, metric=\"euclidean\")\n", - "\n", - "print(\"Shape of data = \", X.shape)\n", - "print(\"Shape of labels = \", labels.shape)\n", - "print(\"Unique labels = \", np.unique(labels))\n", - "print(\"Cluster size = \", np.count_nonzero(labels == 0))\n", - "print(\"Shape of the distance array = \", X_dist.shape)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Selecting from One Cluster\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Check Documentation: **[Medoid](https://selector.qcdevs.org/api_methods_partition.html#selector.methods.partition.Medoid) | [GridParition](https://selector.qcdevs.org/api_methods_partition.html#selector.methods.partition.GridPartition)**\n" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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WCxYu3Yt4uLioFKpml3XaWlpeOihhxAWFgaJRAKRSISAgABcc801+L//+7/es8r28tTZgKS0tJT1v1m0aNEV9bV//36iUqlc5qKlUqmL78bff//drF1T/4cff/yR7UOhUBAul8uWTZo0iZjNZvLLL78QiURCABClUkkYhmHrzJ49u0XZnPPDK1asIJMmTSIACI/Hc5EXbcwfL1iwgK3D4/GIu7s74fF47DahUEi2bt3aZtv58+eTO+64gwAgHA6HuLm5EQ6Hw879t+UH0tQH5q+//iIymYwAIHK53EUOjUbTqn/Ptm3bCJ/PZ+vKZDIiEokIAOLr60s2b9582f4CTeXbt29fi3VSUlLYOm+88Uazds5zLpfLXbbdddddxGaztbnPrVu3ssemUCiISCQikydPJu+88w7x8fFhf+MKhcLF/8THx8elz5aO4fbbbyeenp5smaenp0v722+/vUWZWqIrrpFffvmFeHt7EwBEIpEQoVDoMn6JiYntna4WcV4jkydPbrXO//73P3ZfSUlJzcpfeeUVtpzL5RI3NzcX+RiGIRs2bGix74SEBJdrWSgUNvNlaclPJi8vj0RFRbnsQ6lUurR75JFHWtxnVVUVGTFihMu17Tw/DMOQjz/++LJ9dG666SYCgPj7+xO73d6ptk3lu/baa12O5dJju/XWW1v0l2zPJ+att95y8b2USCREIBCw3319fcmZM2dabHv69GkSEBDA1uVwOMTd3d3lXK9bt44QQsi3335LfHx82OtTKpU2uwYLCgrYvmtra0l8fLzL70ilUrn8NpYtW9aiXM5jXr58ORk/fjx7Tt3c3AjDMOx1/dtvv7nIyufzO/ws6G6ootMNfPPNNy430MuloKCA/aFERkaSQ4cOsWUHDx4kQ4cOJQCIu7t7swdx05u4SqUiU6dOJSkpKYQQQhobG8n777/PKjwvvvgiUSqVZPbs2SQvL48QQkh9fT154YUX2D5+//33ZvI5LwClUkmEQiHZuHEjMRgMrOx33nkn2/6nn35q1n7VqlXknXfeIefPnycWi4UQQojNZiPJycnk3nvvZS/goqKiZm2dio5MJiM8Ho+8++67RKfTsbIXFxc3G4e2FB03Nzdy6623kgsXLhBCCDGZTOS7775jFYR58+Y1kyE7O5tVDkeOHElOnTpFCCHEbreT33//nQQFBRE3N7duVXR27drF1vnkk08IIQ7n3Ycffpj8/vvv7JgQ4rjBb9iwgX3QtfRwbLpPmUxGbrrpJnZMCCEkIyOD/b+jD6vWjqGjzshtKTpddY24ubmRCRMmkJMnTxJCCLFYLOT3338nvr6+BHC8EFwObSk6RqOR/PDDD8TLy4sAINOmTWuxj08//ZS88sor5NSpU+zD1263k5ycHLJkyRLCMAzhcrnNHqANDQ3s73fu3LkkKyuLLdPr9eTUqVPk2WefJbt27XJpp9frSXh4OAFA4uPjyf79+4nRaCSEOB6Y7733HvtSsH79+mby3n777axS1fSekJeXR26//XbC5/PZ66azis7KlSvZc/b0008TvV7fqfZWq5U9J8OHDyc///wzaWhoYI/7iy++YBXep556qln7thSdTZs2sdfNG2+8QUpKSth9njp1ilx33XWsklZfX+/StqCggFX8AwICyLfffsvKZbfbSUpKClm5ciX53//+12F5muJ8GRQIBOT9999n+y4pKSH3339/s3tIS/uQyWREJpORzZs3k8bGRkIIIZWVlaSqqooQQsigQYPY3/H58+fZ9gaDgSQnJ5NXX331spzPuwKq6HQDL774IvvDaekh3VEeeeQR9ibsvGiaotVq2YfW448/7lLW9CYeFRXF3qiaMm/ePLbODTfc0OIbktNS05JlynkBACD//e9/m5XbbDb2zSkqKqozh04IIeRf//oXAUBWrVrVrKypNej9999vtY+OKjpTpkxp0cLx/vvvE8CxKsapjDlZtGgRAUC8vb3Zi70paWlpLm84naUjio5zjACQs2fPdqjfH374gQCO1Vpt7XPMmDHEarW22k9fUHS66hoJDw9nb95N2blzJ1tHq9W2eZwt0ZFVVwEBAeS5555rcf8d4fHHH2/xGj1+/Dj7snDpb7ctXnvtNVY5M5vNLdbZtm0bARyWuKZ9O/fZ2j3BarWSiRMnsnU6++CrqKggGo2GbS+VSsmMGTPISy+9RHbs2EHKysrabP/ll1+y57u2trbFOqdOnSIMwxCBQNCsv9YUi7q6Olbh3rt3b4v9WiwWMmrUKAL8Y5lxMnfuXAKAeHh4uFhi2qMjis6xY8fY8fr0009brONUhDw9PVnF9NJ9ACA7d+5ssX1ZWRlbx/mS2Zegik438Oijj7In/dIfTUex2+3szXDFihWt1nvuuefYC6QpTW/imzZtarFtU5P5n3/+2WKd119/nQAgo0ePblbmvAACAgJaNSP/9ttv7D7OnTvX6nG0xMcff0wAkOnTpzcrcyo6bm5ubS7J76ii05LFihBC8vPz2Tqpqansdrvdzt7Y2rrJNFUmO0trio7BYCCJiYlkzpw5LopaR2lsbGTbXaocNN3nDz/80GY/va3odOU18p///KfFthaLhZ16uJzl300fEq19FAoFeeCBB1pU1DrC7t27CYBmy+/T09NZJau0tLTD/TnPa0tWWCd2u51VII8dO8ZuX7p0abv3hF9//fWyFR1CCMnJySE33HBDq+M5atQosnnz5hZfXJzno7WpPifDhg0jAMi3337bYvtLr3nnFPWIESPa7Pfdd98lAMiMGTPYbXq9np2Ceuedd9o5+paPp617kPOc+Pv7tzgmhBCSmpraqjLj3EdbL6uNjY3slN3p06c7dQw9AXVG7qPk5uaiuroaAHD99de3Wu+GG24AAFRVVSE3N7fFOq0t6/Xx8WH/Hz16dJt1ampqWpXB6azWEpMmTQKPxwMAnDp1qll5UlISHnvsMcTExEChUIDD4bDOdI899hgAtOos6ZRbIBC0Wt5Rxo4d2+J2jUbD/u88HwCQk5PDBrmbPHlyq/02daq9EqZMmcKOi1gsxvDhw/HNN98AAEaMGMH+76S+vh7vvPMOJk+eDG9vbwgEAra9RCJh67U1thMmTOgS2buLrrxGWjv/zuCMgOv57yyTJ08GcbxYsh+dToc//vgDMTEx2LRpE8aMGYPMzMwW2+fk5GDZsmUYNWoUVCoVuFwuez5vuukmAM3P5aBBgxAeHg6LxYKxY8firbfeQmJiImw2W6tyFhUVsU7mixYtglqtbvHj6+vLOk43DXbovMbbuidce+217D3hcggJCcFvv/2G1NRUvPnmm5g5c6aLY/Lp06dx33334cYbb4TRaGS322w21nF75cqVrR6bWq1Genp6s2Nri8OHDwMALly40Ga/r732WrN+T506xS74uOWWWy57XFrDeU6mTJkCDqflR35ERAQbfqOl+zTQ9v1ALBZj6tSpAIAZM2bg5ZdfxvHjx2E2m69E9C7j8n9tlFbx8PBg/6+urnZ5WHaU8vJy9v+24r80Xc1VXl7uspLFiVwub7Ft05tNe3VaW3nVnnwikQgeHh4oKytzOSYA+PDDD7FkyRLY7XYAjtU5SqUSQqEQgGPlRl1dXZuxRby9vVst6wwdGaOmY1BRUcH+39b57arYPW5ubqxCx+PxoFQqERkZiZkzZ2L27Nng8/ls3YyMDEydOtXlwSeRSKBSqdgbnXP1Rk+MbXfRE9cI0PI1cOTIEcyaNavF+hs2bMDs2bNbF/wiCoUCU6dOxZgxYxAdHY38/Hw8/PDD+Ouvv1zqbd++HXPmzIHJZHJpKxKJwDAMzGYzampqmp1LLpeLb7/9Frfffjtyc3Px/PPP4/nnn4dEIsH48eMxa9YsLFiwwEXxLS4uZv9vb4WQk6axv5znpKP3hCshIiICERER7PfS0lL89NNPWLNmDfLz8/Hbb7/hxRdfxLvvvgvAcS92jmFbL25N6WhcM+e4GY1GF+WqI/2Wlpay/wcFBXVof52hI+cEcFwnRUVFze7TTtq7H2zatAm33norkpKSsGrVKqxatQoCgQCjR4/GzJkzsWjRIri7u1/eQVwh1KLTDURFRbH/nz17thcl6btcuHABTz31FOx2O+666y6cOHECRqMRNTU1bFC19957DwDaXOrJ5XJ7SuRW6YkcTE0DBhYWFiIlJQU//PAD5s6d66LkAI7l3oWFhQgODsYPP/yAqqoqNDQ0oLy8HKWlpS7L5fv62PZVzGYzysrKWvwYDIZO9SWXy1nFaN++fSgpKWHLqqqqsHDhQphMJlx33XXYv38/GhsbodPpUFZWhtLSUvzwww+t9h0bG4u0tDT8+OOPeOihhzBs2DAYDAb88ccfeOyxxxAeHo7z58+z9Ztaey5cuNDMCtXSZ+HChZ063u5CrVbj4YcfxvHjx9mH8ueff86+SDU9tj179nTo2Dqa08rZ9+zZszvUb9Ol3/0lh1t794PAwECcOXMGe/fuxZNPPolRo0bBbrfj8OHDeO655zB48OBmSnxPQRWdbqCpiXD79u2X1UdT7bmt6YWmZb31Bt5WnBmTyYSqqioArvJt3boVNpsNERER+Pbbb1ucgmr6ptPXcE5nAK5vwZfS00HLtFotm+Pnm2++wZ133tnsLaovj2tn6M1rJD4+vksf/E3f5Js+BHfv3o26ujq4ubnh559/xuTJk5vFh2nvfAoEAsyaNQuffvopzp8/j4qKCmzcuBHu7u7QarVYsGABW1etVrP/X07+Lef4dvSe0B34+PiwwVdrampY66uHhwdrnevq3GLOcbucfq90zNvDeU7aukaall/JNcLhcDB9+nRs2LABp06dQnV1Nb766isEBgaipqYG99xzT69MZ1FFpxvw8fHBHXfcAQD4+uuvkZGR0eG2zjfskJAQ9gHVVpCtP/74A4DjIm7JJN8THDhwoFXLwN9//w2r1QoAiIuLY7drtVoAjjfO1uaNncfWFwkNDWUjsrYVbKunk+05xxVw+O60RFeNq/O8tWUV6kj7y+2jP10j7dH0ISSVStn/nedz6NChLlNMTens+fTw8MDDDz+Mt956C4DD6uxUPIKDg9kpjp9//rlT/QL/XONt3RMOHjzI3hO6C5lMxv7vnArn8/msv+LlHFtbOP1XTp8+7WKR6whxcXHsS15n5erINeg8J/v27WOtW5eSlpbGKqet+WteDnK5HPfccw/++9//AnBMmTe1IPYUVNHpJl5//XXIZDIYDAbMmjWr3Tf7mpoa3HHHHdDpdAAc5kynOfvTTz9t8a2tuLgYn376KQBgzpw5XXwEHaegoABffPFFs+12ux2rV68GAERGRiI6Opotc0aAPn/+fIsX6Z49e/p0Rl6GYVgfjY0bN7Y455+ZmYnvv/++R+VqGlk7KSmpWXl9fT1ef/31LtmXQqEAgMvOPO5sf7l99KdrpC2MRiO2bdsGwPGAHjp0KFvmPJ8ZGRkt+n4kJibi66+/brHfpj49LdHUMtRU6XzwwQcBAP/973/bnXq/1EHbeT7auidcye/v77//btdvRq/Xs+MZEhLikiLioYceAuCwlO3evbvNfjrjfH7XXXdBpVLBYrHg6aefblPxsNvtLr93iUSCf//73wCAN9980+VlpT06cg06+y4qKsKmTZtarPPyyy8DADw9Pdt07G+N9qw0rf3WeoxuWMlFucj27dvZpamenp7kzTffJJmZmWy51WolZ86cIS+99BK7VLmmpoYt12q17PaoqChy+PBhtuzQoUMkIiKCAO0HQ2tt6W57EWcJ+WfZZFBQULOypgEDRSIR+eyzz1wCBt59991s/9u2bXNp+8cff7Bljz76KBuHRq/Xk40bNxKJREI8PDxa3bdzefmCBQtalb29cejI8RPS+vLozMxMIhaLCQASFxfHBmyz2+3kzz//JCEhId0eMPBSbDYbCQwMZH8zziCGhBBy5MgRMnLkSHZcW+q3o2NCCGGDOo4fP55UV1e3Wq+tY/Dz8yMAyBNPPNFqrJe2ZOrua4SQK8u03V5k5JSUFDJz5kxWjuXLl7uUZ2RksMt2Z82axR6DM6Cll5eXy/lsSkJCAhk/fjzZuHEjyc7OZrdbrVayd+9e4u/vTwCQcePGubSrr68n0dHR7LX9wQcfkMrKSra8pqaG7N69m8ybN49ERkY2O6Zbb72VAGDvCc4YXvn5+eTOO++8ooCBd9xxB/Hw8CCLFy9uFhBTp9OR7777jpUdAPnwww9d2lutVnL99dcTwBE8b9WqVS6xzvR6Pfnrr7/IY489RpRKZbP9t7WcOyEhgd3vjTfeSI4dO8Yu57bZbCQ1NZW8++67JDw8nGzZssWlrVardQkY+N1337Fxlex2Ozl//jxZtmwZ+fLLL13aOYO6Dh48uNXo7c5xcx7zBx984BIw8IEHHmDlbitgYFtL2Pft20eio6PJe++9R1JTU9njttvt5PDhw+w58ff3bzM2V3dBFZ1u5tChQ2Tw4MEucR4EAgFxd3d3CRXOMAyZM2dOswBd+/fvdwlPfml4e5VKRQ4ePNhsvz2p6KxYsYINAsbn810e7oAj8nJL/Pvf/3app1Kp2GjNo0aNIh988EGfVnQIcQTfa5ouQi6XszdxPz8/dvyEQmGb+2iJy1F0CCHk559/dpFJIpGwMkmlUhcl80oUnQMHDrAh5LlcLvH19SVBQUHNzldbx7Bq1Sq2XCgUkoCAABIUFOSSdqQjKSC66xohpGsUnUsDBvr4+LDnxPmZPXt2iwH6li9f7lJPqVSycVdCQkLIV1991eL4NE0/4hxfDw8Pl/uORqNxiXztpKioiFxzzTUu9yeVStUsfcTgwYObta2srCSxsbFsnaapABiGIR999NFlj+ml9wznNeeM1Oz8cDicZkqjE51OR26++WaX+gqFollKBB6P16xtew/9Tz75xCXlg3PMm6aJAdAswjEhjhQQTsXfeU15eHiwKWWA5oEGMzIy2HIOh0N8fHzYa7BpgMva2lqXmE5NUzg4t7WXAqI9Rafp8fH5fOLh4eFyH1IoFC1ehz0BVXR6AKvVSr755hty7733ksGDBxOFQkH4fD7x9PQkEydOJC+88AJJS0trtX1xcTF55plnSEREBBGLxUQikZCIiAiybNmyVoOM9aSi88orrxCTyURWr15Nhg0bRiQSCVEqlWTq1KnNwss3xWazkfXr15OYmBgiFAqJXC4nw4cPJ2vWrCFGo7HNffcVRYcQQhITE8ldd91FvLy8iEAgICEhIWTJkiWkvLycjSB7af6njnC5ig4hDuvNv/71L6JSqYhAICCBgYHkvvvuY39nXaHoEOIIVnf99dc3e4A2pa1jsNlsZMOGDSQuLo7IZDL2xtvUAtIRmbrrGiGkaxSdlj4ikYiEhISQf//732TPnj1t9vPll1+SMWPGuBzb//3f/5Ha2tpWx6eqqop8+eWX5L777iOxsbHE29ub8Hg8olQqyZgxY8iqVatcLMiX4rxv3XrrrUSj0RCBQEBEIhEJDg4mt9xyC1m/fn2rUXAbGhrIq6++SsLDw4lQKCSenp5kxowZ5I8//iCEXP6YWiwW8tdff5EVK1aQqVOnEn9/fyIUCtkH9+jRo8nSpUtbzBl2Kbt37yazZ88mgYGBRCgUEoFAQPz9/cm0adPImjVrXKxgTjry0M/NzSXLli0jsbGxbG5BNzc3EhcXR5544gny+++/txq4r66ujrz55pvkmmuuYa/dgIAAEh8fT957770WIz8fPXqU3HrrrcTHx8dFsbj0N221Wsl///tfEh8fT9zc3Aifzye+vr7kjjvuaPP+0pFj1uv15PvvvyePPvooGTVqFPH19SV8Pp/IZDIyfPhw8txzz11RloArhSHkMj0JKVc98fHxOHDgAF555ZUOL8O82njhhRewevVqXHfddVecuZlCoVAonYc6I1Mo3URFRQXr/DdjxoxeloZCoVCuTqiiQ6FcAe+//z7efPNNZGVlsUtmTSYTdu/ejWuvvRbl5eXw8vLC/fff38uSUigUytUJTQFBoVwBOTk52LBhA1asWAEulwulUom6ujpW6VEqlfj+++9d0oJQKBQKpeegig6FcgUsWLAAXC4XBw8eRFFREaqqqiAWixESEoLp06djyZIlXZbvikKhUCidhzojUygUCoVCGbBQHx0KhUKhUCgDlqt+6sput6O4uBhyubzfZJGlUCgUCuVqhxCC+vp6aDSaNlNLXPWKTnFxMQICAnpbDAqFQqFQKJeBVquFv79/q+VXvaIjl8sBOAaqaZJBCoVCoVAofZe6ujoEBASwz/HWuOoVHed0lUKhoIoOhUKhUCj9jPbcTqgzMoVCoVAolAELVXQoFAqFQqEMWAaUovPmm2+CYRg89dRTvS0KhUKhUCiUPsCAUXROnjyJTz/9FDExMb0tCoVCoVAolD7CgFB09Ho97r33XvznP/+Bm5tbb4tDoVAoFAqljzAgFJ3HH38c//rXv3D99de3W9dkMqGurs7lQ6FQKBQKZWDS75eXf/vttzhz5gxOnjzZofpr1qzBq6++2s1SUSgUCoVC6Qv0a4uOVqvFkiVL8NVXX0EkEnWozYoVK6DT6diPVqvtZikpFAqFQqH0Fv06e/mOHTtw++23g8vlsttsNhsYhgGHw4HJZHIpa4m6ujoolUrodDoaMJBCoVAolH5CR5/f/XrqaurUqTh//rzLtvvuuw/h4eFYvnx5u0oOhUKh9Bo6HYwVFSgEg8wqPYx2QC7kIULtDl+rBRylElAqe1tKCqXf06+nruRyOYYNG+bykUql8PDwwLBhw3pbPAqFQmkZnQ62G26AbfIU/JVegySBH9JFfjjF+GDX2UIYJ0wEmTED0Ol6W9IBw8KFC3Hbbbf1mX4YhsGOHTuuuJ+eYOXKlRg+fHhvi3HZ9GtFh0KhUPojpK4OxuISSIsLcdcjd0FeWgQAkJcW4a5H7oakUAtjUTFQX9/Lkg4cNmzYgISEhD7Tz9VOQkICVCpVj+xrwCk6+/fvx/r163tbDAqFQmmVCpEYX326DTX+wXArzMM9D90Gv6QTuOeh2+BWmIca/yD875MfYfX17XHZ7IQgv96M1GoT8uvNsPdfN04XlEpllzxYu6ofSs8x4BQdCoVC6evk1DSgWhOCrz/bwSo78+7710UlJxhff/YTqjTByKlp7FG50mtN+CSlBt9k1WFnfj2+yarDJyk1SK81det+7XY71qxZg5CQEIjFYsTGxmLr1q1s+e7duxEWFgaxWIwpU6YgISEBDMOgtrYWQMtTK+vXr0dwcDD7/dIpp61btyI6OhpisRgeHh64/vrr0dDQ0K6sl/YTHx+PJ598Es899xzc3d2hVquxcuVKlzaZmZm49tprIRKJEBkZid9//71Zv1qtFnfffTdUKhXc3d0xc+ZM5OXlNdvvq6++Ci8vLygUCjzyyCMwm80dHsf9+/eDYRj8+eefiIuLg0Qiwfjx45Genu4iy5tvvgkfHx/I5XIsWrQIRqOxmbybNm1CREQERCIRwsPD8fHHH7NleXl5YBgG27Ztw5QpUyCRSBAbG4ujR4+yctx3333Q6XRgGAYMwzQbs66EKjoUCoXSwxiJ49Zbr/bDL6s+cin7ZdVHqFf7AQAabT0nU3qtCdtz61Fvsbtsr7fYsT23vluVnTVr1uDLL7/Exo0bkZKSgqVLl2Lu3Lk4cOAAtFotZs2ahVtuuQWJiYl44IEH8Pzzz1/R/kpKSjBnzhzcf//9uHDhAvbv349Zs2bhchchf/HFF5BKpTh+/DjefvttvPbaa6wyY7fbMWvWLAgEAhw/fhwbN27E8uXLXdpbLBZMnz4dcrkcf//9Nw4fPgyZTIYZM2a4KDJ//vknK+8333yDbdu2ucSFa2scm/LCCy9g7dq1OHXqFHg8Hu6//3627Pvvv8fKlSuxevVqnDp1Cr6+vi5KDAB89dVXePnll/HGG2/gwoULWL16NV566SV88cUXzfazbNkyJCYmIiwsDHPmzIHVasX48eOxfv16KBQKlJSUoKSkBMuWLbusse8Q5CpHp9MRAESn0/W2KBQK5SohubiKrDlTQT7cnUiq/YMJAdhPtX8w+XB3IllzpoLk6Uw9Io/NbicfnnfI1Nrnw/NVxGa3d/m+jUYjkUgk5MiRIy7bFy1aRObMmUNWrFhBIiMjXcqWL19OAJCamhpCCCGvvPIKiY2Ndamzbt06EhQUxH5fsGABmTlzJiGEkNOnTxMAJC8vr9PyNu2HEEImT55MJk6c6FJn9OjRZPny5YQQQn799VfC4/FIUVERW75nzx4CgGzfvp0QQsiWLVvI0KFDib3J+JpMJiIWi8mvv/7K7tfd3Z00NDSwdT755BMik8mIzWZrdxwJIWTfvn0EAPnjjz/Y8l27dhEAxGAwEEIIGTduHHnsscdc+hg7dqzL+A4aNIh8/fXXLnVWrVpFxo0bRwghJDc3lwAgmzZtYstTUlIIAHLhwgVCCCGbN28mSqWSXAkdfX5Tiw6FQqH0MOE+KniU5OOeB2ey01VbNu/6x2fnwZnwLi9EgJzfI/Jo9ZZmlpxLqbfYodVbunzfWVlZaGxsxA033ACZTMZ+vvzyS2RnZ+PChQsYO3asS5tx48Zd0T5jY2MxdepUREdH46677sJ//vMf1NTUXHZ/lyaT9vX1RXl5OQDgwoULCAgIgEajYcsvlT8pKQlZWVmQy+Xs8bu7u8NoNCI7O9tFbolE4tKPXq+HVqttdxxbk9f3oh9YU3nbGu+GhgZkZ2dj0aJFLvt5/fXXO7WfnqRfx9GhUCiU/gi3uBgLHrsLgqJ81PgF4evPdqBe7YevP9vhUH6K8jH3kVng/H0Q8PfvdnkaLB2bsulovc6g1+sBALt27YKfn59LmVAoxJNPPtluHxwOp9m0k8XSulLG5XLx+++/48iRI/jtt9/wwQcf4IUXXsDx48cREhLS6WPg810VUoZhYLe3rTg2Ra/XY9SoUfjqq6+alXl5eXW4D6D1cWxNXoZhAKDD8jr385///KeZQnRp7Lor2U9XQhUdCoVC6Wnkcgh8fWBmgO0bt6He2/Fgqlf74afPf8I9D98OgdoHkMt7RBwpn+nSep0hMjISQqEQBQUFmDx5crPyiIgI7Ny502XbsWPHXL57eXmhtLQUhBD2gZqYmNjmfhmGwYQJEzBhwgS8/PLLCAoKwvbt2/H0009f2QG1IL9Wq0VJSQlr1bhU/pEjR+K7776Dt7d3mxF+k5KSYDAYIBaL2X5kMhkCAgLg7u7e5jh2Rt7jx49j/vz57Lam8vr4+ECj0SAnJwf33nvvZe9HIBDAZusZJzSq6FAoFEpPo1QCe/dCUF+PhX5+0OotaLAQSPkMAoZ7OCw5cnmPRUYOkPEh53PanL6S8zkIkHX9VJpcLseyZcuwdOlS2O12TJw4ETqdDocPH2ZXFq1duxbPPvssHnjgAZw+fbpZHJv4+HhUVFTg7bffxp133om9e/diz549rSoNx48fx59//olp06bB29sbx48fR0VFBSIiIrr8+K6//nqEhYVhwYIFeOedd1BXV4cXXnjBpc69996Ld955BzNnzsRrr70Gf39/5OfnY9u2bXjuuefgf9GqZzabsWjRIrz44ovIy8vDK6+8gsWLF4PD4bQ7jgsWLOiQvEuWLMHChQsRFxeHCRMm4KuvvkJKSgpCQ0PZOq+++iqefPJJKJVKzJgxAyaTCadOnUJNTU2HFcXg4GDo9Xr8+eef7JRc02m5roT66FAoFEpvoFQC/v7gMAyC5AJEugsRJBeAwzCO6aoeTP/AYRhc7y9ts871/lKHbN3AqlWr8NJLL2HNmjWIiIjAjBkzsGvXLoSEhCAwMBA//vgjduzYgdjYWGzcuBGrV692aR8REYGPP/4YH330EWJjY3HixIk2V/EoFAocPHgQN910E8LCwvDiiy9i7dq1uPHGG7v82DgcDrZv3w6DwYAxY8bggQcewBtvvOFSRyKR4ODBgwgMDMSsWbMQERHBLutuqqxNnToVQ4YMwbXXXovZs2fj1ltvdVmW3dY4dpTZs2fjpZdewnPPPYdRo0YhPz8fjz76qEudBx54AJs2bcLmzZsRHR2NyZMnIyEhoVP7GT9+PB555BHMnj0bXl5eePvttzvctrP066SeXQFN6kmhUCgO0mtN+KOwwcWyI+dzcL2/FENVwjZa9iz79+/HlClTUFNTc9UE71u4cCFqa2v7TdqInuCqSOpJoVAolK5jqEqIIUqB61SajN9tlhwKpSegig6FQqFQWJxTaVcrMpms1bI9e/Zg0qRJPSgNpSugU1d06opCoVAoF8nKymq1zM/Pj13xROl96NQVhUKhUCidZPDgwb0tAqWLoauuKBQKhUKhDFiookOhUCgUCmXAQhUdCoVCoVAoAxaq6FAoFAqFQhmwUEWHQqFQKBTKgIUqOhQKhUIZ8CxcuBC33XZbv+u7q8nLywPDMO0mPR1I0OXlFAqFQhnwbNiwAVd52LhuhWEYbN++vU8qfNSiQ6FQKBRApwMKC1suKyx0lPdjlErlVZMXi+IKVXQoFArlakenA2bMACZPBrRa1zKt1rF9xoxuU3bsdjvWrFmDkJAQiMVixMbGYuvWrWz57t27ERYWBrFYjClTpiAhIQEMw6C2thYAsHLlSgwfPtylz/Xr1yM4OJj9fun00tatWxEdHQ2xWAwPDw9cf/31aGhoaFdWm82Gp59+GiqVCh4eHnjuueeaWYraO579+/eDYRjs2rULMTExEIlEuOaaa5CcnOzSz6FDhzBp0iSIxWIEBATgySefdJExODgYq1evxv333w+5XI7AwEB89tlnLn2cOHECI0aMgEgkQlxcHM6ePdvsmJKTk3HjjTdCJpPBx8cH8+bNQ2VlJVseHx+PJ598Es899xzc3d2hVqtdsqY7x/n2228HwzAu494XoIoOhUKhXO3U1wPl5UBODhAf/4+yo9U6vufkOMrr67tl92vWrMGXX36JjRs3IiUlBUuXLsXcuXNx4MABaLVazJo1C7fccgsSExPxwAMP4Pnnn7+i/ZWUlGDOnDm4//77ceHCBezfvx+zZs3q0NTW2rVrkZCQgM8//xyHDh1CdXU1tm/f3uHjacqzzz6LtWvX4uTJk/Dy8sItt9wCi8UCAMjOzsaMGTNwxx134Ny5c/juu+9w6NAhLF68uJk8TgXmsccew6OPPor09HQAgF6vx80334zIyEicPn0aK1euxLJly1za19bW4rrrrsOIESNw6tQp7N27F2VlZbj77rtd6n3xxReQSqU4fvw43n77bbz22mv4/fffAQAnT54EAGzevBklJSXs9z4DucrR6XQEANHpdL0tCoVCofQeBQWEhIYSAjj+Hj7s+r2goFt2azQaiUQiIUeOHHHZvmjRIjJnzhyyYsUKEhkZ6VK2fPlyAoDU1NQQQgh55ZVXSGxsrEuddevWkaCgIPb7ggULyMyZMwkhhJw+fZoAIHl5eZ2W19fXl7z99tvsd4vFQvz9/dm+2zseQgjZt28fAUC+/fZbtryqqoqIxWLy3XffsfUfeughlz7+/vtvwuFwiMFgIIQQEhQURObOncuW2+124u3tTT755BNCCCGffvop8fDwYOsTQsgnn3xCAJCzZ88SQghZtWoVmTZtmst+tFotAUDS09MJIYRMnjyZTJw40aXO6NGjyfLly9nvAMj27dvbGLmup6PPb+qMTKFQKBQgIADYv/8fC86ECY7toaGO7QEB3bLbrKwsNDY24oYbbnDZbjabMWLECBgMBowdO9albNy4cVe0z9jYWEydOhXR0dGYPn06pk2bhjvvvBNubm5tttPpdCgpKXGRh8fjIS4ujrUGtXc8rR2Hu7s7hg4digsXLgAAkpKScO7cOXz11VdsHUII7HY7cnNzERERAQCIiYlhyxmGgVqtRnl5OQDgwoUL7NRYS/t07mffvn0tZm3Pzs5GWFhYs/0AgK+vL7ufvg5VdCgUCoXiICAA2LLlHyUHcHzvJiUHcEyvAMCuXbvg5+fnUiYUCvHkk0+22weHw2k27eScAmoJLpeL33//HUeOHMFvv/2GDz74AC+88AKOHz+OkJCQyziKf2jveDrTz8MPP9zi8QcGBrL/8/l8lzKGYWC32zu1n1tuuQVvvfVWszJfX98u209vQhUdCoVCoTjQaoF581y3zZvXrRadyMhICIVCFBQUYPLkyc3KIyIisHPnTpdtx44dc/nu5eWF0tJSEELAMAwAtBsnhmEYTJgwARMmTMDLL7+MoKAgbN++HU8//XSrbZRKJXx9fXH8+HFce+21AACr1YrTp09j5MiRHTqeS4/DqbTU1NQgIyODtdSMHDkSqampV5RNPSIiAlu2bIHRaGStOpeO3ciRI/Hjjz8iODgYPN7lqwR8Ph82m+2y23cn1BmZQqFQKK6Ox6GhwOHDjr+XOih3MXK5HMuWLcPSpUvxxRdfIDs7G2fOnMEHH3yAL774Ao888ggyMzPx7LPPIj09HV9//TUSEhJc+oiPj0dFRQXefvttZGdn46OPPsKePXta3efx48exevVqnDp1CgUFBdi2bRsqKipYJaMtlixZgjfffBM7duxAWloaHnvsMXb1V0eOpymvvfYa/vzzTyQnJ2PhwoXw9PRkV4YtX74cR44cweLFi5GYmIjMzEz89NNPzZyR2+Kee+4BwzB48MEHkZqait27d+Pdd991qfP444+juroac+bMwcmTJ5GdnY1ff/0V9913X6cUl+DgYPz5558oLS1FTU1Nh9v1CD3gL9Snoc7IFArlqkerbdnx+FIHZa22W3Zvt9vJ+vXrydChQwmfzydeXl5k+vTp5MCBA4QQQn7++WcyePBgIhQKyaRJk8jnn3/u4oxMiMPJNiAggEilUjJ//nzyxhtvtOqMnJqaSqZPn068vLyIUCgkYWFh5IMPPuiQrBaLhSxZsoQoFAqiUqnI008/TebPn8/23ZHjcToj//zzzyQqKooIBAIyZswYkpSU5LKvEydOkBtuuIHIZDIilUpJTEwMeeONN9jyoKAgsm7dOpc2sbGx5JVXXmG/Hz16lMTGxhKBQECGDx9OfvzxRxdnZEIIycjIILfffjtRqVRELBaT8PBw8tRTTxG73U4IcTgjL1myxGU/M2fOJAsWLGC/79y5kwwePJjweDyXce9OOvr8Zgi5ukNF1tXVQalUQqfTQaFQ9LY4FAqF0vM44+iUlzefpnJaery9gb17AaWyt6Rk2b9/P6ZMmYKampp+GQSwv8vfV+jo85v66FAoFMrVjlLpUGLq6wF/f9eygADgwAFALu8TSg6F0lmookOhUCgUhxLTmiJzqfIzgGlpmbWTPXv2YNKkST0oDaUroFNXdOqKQqFQKBfJyspqtczPzw9isbgHpaG0BZ26olAoFAqlk1zJcm5K34QuL6dQKBQKhTJgoYoOhUKhUCiUAQtVdCgUCoVCoQxYqKJDoVAoFAplwEIVHQqFQqFQKAMWquhQKBQKZcCzcOFCNo8UABBC8NBDD8Hd3R0Mw7SbBDQ+Ph5PPfXUFcmQl5fXoX31FS4ds/4KXV5OoVAolAHPhg0b0DRs3N69e5GQkID9+/cjNDQUnp6ebbbftm0b+Hx+d4s54Fm5ciV27NjRo8oeVXQoFAqF4gIhjqwPkycDDNPb0nQNykuiPmdnZ8PX1xfjx4/vUHt3d/fuEIvSA/TrqatPPvkEMTExUCgUUCgUGDduHPbs2dPbYlEoFEq/Zu9eYMoU4Ndfe2Z/drsda9asQUhICMRiMWJjY7F161a2fPfu3QgLC4NYLMaUKVOQkJAAhmFQW1sLwGElGD58uEuf69evR3BwMPu96TTMwoUL8cQTT6CgoAAMw7jUa41Lp66Cg4OxevVq3H///ZDL5QgMDMRnn33m0ubEiRMYMWIERCIR4uLicPbs2Wb9Jicn48Ybb4RMJoOPjw/mzZuHyspKl/0uXrwYixcvhlKphKenJ1566SUX65TJZMKyZcvg5+cHqVSKsWPHYv/+/Wx5QkICVCoVfv31V0REREAmk2HGjBkoKSlh69hsNjz99NNQqVTw8PDAc889h0sTJ7R3nvbv3w+GYfDnn38iLi4OEokE48ePR3p6OivHq6++iqSkJDAMA4ZhkJCQ0O7YXyn9WtHx9/fHm2++idOnT+PUqVO47rrrMHPmTKSkpPS2aBQKhdJvcT67mjzDupU1a9bgyy+/xMaNG5GSkoKlS5di7ty5OHDgALRaLWbNmoVbbrkFiYmJeOCBB/D8889f0f42bNiA1157Df7+/igpKcHJkycvq5+1a9eyCsxjjz2GRx99lH2o6/V63HzzzYiMjMTp06excuVKLFu2zKV9bW0trrvuOowYMQKnTp3C3r17UVZWhrvvvtul3hdffAEej4cTJ05gw4YNeO+997Bp0ya2fPHixTh69Ci+/fZbnDt3DnfddRdmzJiBzMxMtk5jYyPeffddbNmyBQcPHkRBQYGLPGvXrkVCQgI+//xzHDp0CNXV1di+fbuLHG2dp6a88MILWLt2LU6dOgUej4f7778fADB79mw888wziIqKQklJCUpKSjB79uzLGvtOQQYYbm5uZNOmTR2ur9PpCACi0+m6USoKhULpu9hshHz4ISGvv+74KBSEAIQolf9s+/BDR72uxmg0EolEQo4cOeKyfdGiRWTOnDlkxYoVJDIy0qVs+fLlBACpqakhhBDyyiuvkNjYWJc669atI0FBQez3BQsWkJkzZ7Za3h6TJ08mS5YsYb8HBQWRuXPnst/tdjvx9vYmn3zyCSGEkE8//ZR4eHgQg8HA1vnkk08IAHL27FlCCCGrVq0i06ZNc9mPVqslAEh6ejq734iICGK3212OPyIighBCSH5+PuFyuaSoqMiln6lTp5IVK1YQQgjZvHkzAUCysrLY8o8++oj4+Piw3319fcnbb7/NfrdYLMTf358ds/bOEyGE7Nu3jwAgf/zxB1u+a9cuAoAdh5bO1eXS0ef3gPHRsdls+OGHH9DQ0IBx48b1tjgUCoXSb2hoAF5+GaiudvjkcC7a+vV64KWXHD477u7A/PmAXN61+87KykJjYyNuuOEGl+1msxkjRoyAwWDA2LFjXcr6yj0+JiaG/Z9hGKjVapSXlwMALly4gJiYGIhEIrbOpXInJSVh3759LWZMz87ORlhYGADgmmuuAdPEWWrcuHFYu3YtbDYbzp8/D5vNxtZ1YjKZ4OHhwX6XSCQYNGgQ+93X15eVVafToaSkxGWceTwe4uLi2Omr9s5Ta+Pi6+sLACgvL0dgYGCz4+wJ+r2ic/78eYwbNw5GoxEymQzbt29HZGRkq/VNJhNMJhP7va6urifEpFAolD6LXA6cPQvMmQMcPQrYbI7tNptD8Rk/Hvj2265XcgDHFA8A7Nq1C35+fi5lQqEQTz75ZLt9cDicZv4kFoul64RshUtXYTEMA7vd3uH2er0et9xyC956661mZU4FoSN9cLlcnD59Glwu16WsqQLVkqyXjll7+wFaP09Nabovp4LWmXHpavq9ojN06FAkJiZCp9Nh69atWLBgAQ4cONCqsrNmzRq8+uqrPSwlhUKh9G0CA4F9+xyWm4aGf7ZLJMD+/UB3rayOjIyEUChEQUEBJk+e3Kw8IiICO3fudNl27Ngxl+9eXl4oLS0FIYR9sPZ2rJqIiAhs2bIFRqORtepcKvfIkSPx448/Ijg4GDxe64/j48ePu3w/duwYhgwZAi6XixEjRsBms6G8vByTJk26LFmVSiV8fX1x/PhxXHvttQAAq9WK06dPY+TIkQDaP08dRSAQwObUpHuIfu2MDDgGbfDgwRg1ahTWrFmD2NhYbNiwodX6K1asgE6nYz9arbYHpaVQKJS+y4kTrkoO4Ph+4kT37VMul2PZsmVYunQpvvjiC2RnZ+PMmTP44IMP8MUXX+CRRx5BZmYmnn32WaSnp+Prr79utlInPj4eFRUVePvtt5GdnY2PPvqo11fg3nPPPWAYBg8++CBSU1Oxe/duvPvuuy51Hn/8cVRXV2POnDk4efIksrOz8euvv+K+++5zUQYKCgrw9NNPIz09Hd988w0++OADLFmyBAAQFhaGe++9F/Pnz8e2bduQm5uLEydOYM2aNdi1a1eH5V2yZAnefPNN7NixA2lpaXjsscfYVW1A++epowQHByM3NxeJiYmorKx0mWHpLvq9onMpdru9zYETCoXscnTnh0KhUCjAzz87/t52G5CVBcyc6fh+iUGly1m1ahVeeuklrFmzBhEREZgxYwZ27dqFkJAQBAYG4scff8SOHTsQGxuLjRs3YvXq1S7tIyIi8PHHH+Ojjz5CbGwsTpw40WyFU08jk8nw888/4/z58xgxYgReeOGFZlNUGo0Ghw8fhs1mw7Rp0xAdHY2nnnoKKpUKHM4/j+f58+fDYDBgzJgxePzxx7FkyRI89NBDbPnmzZsxf/58PPPMMxg6dChuu+02nDx5slM+Mc888wzmzZuHBQsWYNy4cZDL5bj99ttd6rR1njrKHXfcgRkzZmDKlCnw8vLCN9980+G2lwtDOjNJ18dYsWIFbrzxRgQGBqK+vh5ff/013nrrLfz666/NHKZao66uDkqlEjqdjio9FArlqubwYSA/3+GrwzAOJ+RvvgGCgoAJE3pbun/Yv38/pkyZgpqaGqhUqt4Wp1uJj4/H8OHDsX79+t4Wpc/R0ed3v/bRKS8vx/z581FSUgKlUomYmJhOKTkUCoVC+YcJE1wVGoYB7rmn9+ShULqCfq3o/Pe//+1tESgUCoXSzykoKGhztW5qamqvLY2mXDn9euqqK6BTVxQKhXJ1Y7VakZeX12p5e6uiKL3DVTF1RaFQKBTKlcLj8TB48ODeFoPSTQy4VVcUCoVCoVAoTqhFh0Kh9HkaGxvR2NgIHo8HhULhsvSWQqFQ2oIqOhQKpc/SUFyM3HPnUNkkX5BAIEBwcDA0drsjJ4FS2YsSUiiUvg5VdCgUSp+ksaQEtmnTMLi2Fuqff4Y8MhImkwlFRUXIP3QIXs8+C75GA+zdS5UdCoXSKtT+S6FQ+iTa1FQIamshKiqC5513QlheDoVCgQiZDHHLloFfUABSVgbU1/e2qBQKpQ9DFR0KhdLnsFgsKOFyUbNtGxAaCuTkAPHxwJEjQHw8+FotDBoNSr/9FvD3721xKf2AhQsX4rbbbmO/E0Lw0EMPwd3dHQzDXFYS0Pj4eDz11FNdJmN3sn//fjAM45K/6mqBTl1RKAMVnQ7WmhqUCwTQ6/VgGAYeHh5wc3MDU1TUp/1bzGYzAEAcFuZInR0f71B2nGF7Q0Nx4b33oPTw6DUZKf2LDRs2oGnYuL179yIhIQH79+9HaGgoPD09e1G6/kleXh5CQkJw9uxZDB8+vLfFaRWq6FAoAxGdDpbrr4e1uBj569aBFxICm82GoqIiuOn1iHnySTA+Pn3Wv4XP5wNwrLZSBQQAW7a45Cawbt4MPQAvgaCXJKT0N5SX/M6zs7Ph6+uL8ePH95JElJ6CTl1RKAMQfUkJrMXFEBcXY+zzz2O0Wo2xY8diuIcHhj78MJjcXJDy8j7r3yIQCODu7o6ioiLY8vKAefNcysm8eeCXlsLb27t3BKR0KXa7HWvWrEFISAjEYjFiY2OxdetWtnz37t0ICwuDWCzGlClTkJCQ4DINs3LlymYWhfXr1yM4OJj93nTqauHChXjiiSdQUFAAhmFc6rVGQ0MD5s+fD5lMBl9fX6xdu7ZZHZPJhGXLlsHPzw9SqRRjx47F/v372fKEhASoVCrs2LEDQ4YMgUgkwvTp06HVal36+emnnzBy5EiIRCKEhobi1VdfhdVqZcsZhsGmTZtw++23QyKRYMiQIdh5SYr5S8espcjPhw4dwqRJkyAWixEQEIAnn3wSDQ0NbHlwcDBWr16N+++/H3K5HIGBgfjss8/YcmfW8hEjRoBhGMTHx7c7jr0CucrR6XQEANHpdL0tCoXSZaSkpJDTO3YQe2goIQAhoaGEHD7s+AuQRo2GVJ4929titkldXR059sMPxOjvTwhA7KGhxPjXX8QcEEAI4PhbUNDbYlK6gNdff52Eh4eTvXv3kuzsbLJ582YiFArJ/v37SUFBAREKheTpp58maWlp5H//+x/x8fEhAEhNTQ0hhJBXXnmFxMbGuvS5bt06EhQUxH5fsGABmTlzJiGEkNraWvLaa68Rf39/UlJSQsrLy9uV8dFHHyWBgYHkjz/+IOfOnSM333wzkcvlZMmSJWydBx54gIwfP54cPHiQZGVlkXfeeYcIhUKSkZFBCCFk8+bNhM/nk7i4OHLkyBFy6tQpMmbMGDJ+/Hi2j4MHDxKFQkESEhJIdnY2+e2330hwcDBZuXIlWwcA8ff3J19//TXJzMwkTz75JJHJZKSqqooQQjo0ZllZWUQqlZJ169aRjIwMcvjwYTJixAiycOFCdj9BQUHE3d2dfPTRRyQzM5OsWbOGcDgckpaWRggh5MSJEwQA+eOPP0hJSQm7/56io89vquhQRYcywLDb7eTAgQMkLy/PoQg4lR3nJzSUJP78M0lNTe1tUdtGqyXW4GBWMTvy3Xdk37595NgPPxBzYOA/CpxW29uSDgj0en2bn+7CaDQSiURCjhw54rJ90aJFZM6cOWTFihUkMjLSpWz58uVXpOi0VN4W9fX1RCAQkO+//57dVlVVRcRiMavo5OfnEy6XS4qKilzaTp06laxYsYIQ4lB0AJBjx46x5RcuXCAAyPHjx9n6q1evduljy5YtxNfXl/0OgLz44ovsd71eTwCQPXv2EEJIh8Zs0aJF5KGHHnKp8/fffxMOh0MMBgMhxKHozJ07ly232+3E29ubfPLJJ4QQQnJzcwkAcraXXpo6+vymPjoUygDEbrdDIBAAvr7N/FuwZQsglcJms/WegB1BLgdXrQbhcGD+6ScEubuDx+PB3d0dvLFjHQ7K3t4Op2rKFSOTydosJ92U/zkrKwuNjY244YYbXLabzWaMGDECBoMBY8eOdSkbN25ct8jSGtnZ2TCbzS5yuLu7Y+jQoez38+fPw2azISwszKWtyWSCRxOneR6Ph9GjR7Pfw8PDoVKpcOHCBYwZMwZJSUk4fPgw3njjDbaOzWaD0WhEY2MjJBIJACAmJoYtl0qlUCgUKC8vBwBcuHCh3TFLSkrCuXPn8NVXX7HbCCGw2+3Izc1FREREs/0wDAO1Ws3up79AFR0KZYDBMAzEYjFqamrga7W26N9ifOsteI0c2UsSdhClEti7F0x9PZT+/nBxJQ0IAA4c6NMrxygdQ6/XAwB27doFPz8/lzKhUIgnn3yy3T44HE4zRcxisXSdkB1Ar9eDy+Xi9OnT4HK5LmXtKZGX9vPqq69i1qxZzcpETSKEOx32nTAMA7vd3qn9PPzwwy2Ob2BgYJftpy9AFR0KZQCi0WhQdOwYbM89B25eniMWzZYtIPPmgcnJQcySJWCaOEn2WZTK1hUZGj+nS3EqHD1NZGQkhEIhCgoKMHny5GblERERzRxtjx075vLdy8sLpaWlIISAYRgAuKy4OK0xaNAg8Pl8HD9+nFUCampqkJGRwco8YsQI2Gw2lJeXY9KkSa32ZbVacerUKYwZMwYAkJ6ejtraWtaCMnLkSKSnp19RNvWOjNnIkSORmpp6RfsRXFz12Netw1TRoVAGIH6EwPvpp8EtLIQ5IAD6bdtg9vFB5YcfYtADD0BcXAzMmOGwilCFgQLH9EdvIJfLsWzZMixduhR2ux0TJ06ETqfD4cOHoVAo8Mgjj2Dt2rV49tln8cADD+D06dNISEhw6SM+Ph4VFRV4++23ceedd2Lv3r3Ys2cPFApFl8gok8mwaNEiPPvss/Dw8IC3tzdeeOEFl+SyYWFhuPfeezF//nysXbsWI0aMQEVFBf7880/ExMTgX//6FwCHheSJJ57A+++/Dx6Ph8WLF+Oaa65hFZ+XX34ZN998MwIDA3HnnXeCw+EgKSkJycnJeP311zskb0fGbPny5bjmmmuwePFiPPDAA5BKpUhNTcXvv/+ODz/8sEP78fb2hlgsxt69e+Hv7w+RSNRsGX9fgC4vp1AGIBylEgJ/f1gCA3Fuwwacq6lBWloazD4+MOze7bDwUP8W2O12lJeXIzs7G7m5udDpdJfli2I2m2E0GvudSb+vsGrVKrz00ktYs2YNIiIiMGPGDOzatQshISEIDAzEjz/+iB07diA2NhYbN27E6tWrXdpHRETg448/xkcffYTY2FicOHECy5Yt61IZ33nnHUyaNAm33HILrr/+ekycOBGjRo1yqbN582bMnz8fzzzzDIYOHYrbbrsNJ0+edJkKkkgkWL58Oe655x5MmDABMpkM3333HVs+ffp0/PLLL/jtt98wevRoXHPNNVi3bh2CgoI6LGtHxiwmJgYHDhxARkYGJk2ahBEjRuDll1+GRqPp8H54PB7ef/99fPrpp9BoNJg5c2aH2/YkDOkuD7N+Ql1dHZRKJXQ6XZdp/xRKn0CnA+rrQfz8YLFYwDDMP/PthYVXvX+LTqdDSkoKzGYzRCIRbDYbLBYLFAoFhg0bxprl2+gA1fn5yLNaUVdXB8Dxtu7r64sgLhdcleqqHt/uZP/+/ZgyZQpqamqgUql6W5wOk5CQgKeeeuqqTMPQHXT0+U2nriiUgcpF/xYGaP7QvsqnqxobG3Hu3DnIZDLExMRAJpOBEILq6mqkp6fj3LlzGDlypMvUhAs6HczXXQdxaSkEmzYhfMQI8Pl8VFdXo+LMGfg99RQ4/v5gfv2VKjsUSi9Dp64oFMpVh1arBZfLRXR0NLsixpkLbNiwYdDr9aiqqmq1vamyErbSUoiLixG1eDHUFgs8PDwwRCTC6GefhbCoCNaSkj4beZriSkFBAWQyWaufgoKC3haRcgXQqSs6dUWhXHUcOnQIGo0GoaGhLZafPn0aIpEIUVFRLZbn5eWh7NQpjFm+HExODruqDfPmATk5MAcE4Pz772PkzJnsKiBK38VqtbaYIsFJcHAweDw6AdLXoFNXFAqF0go2mw1CobDVcqFQ2OaS2cbGRggGDXIs0W8hs7ruhx9QX1cHu93eLKYKpe/B4/GuaJk1pW9Dp64oFMpVh1gsbtUh1G63Q6fTQSwWt9qey+XCbDaD+Ps7LDlN2bIFRi8vMAxDrTkUSh+AKjoUCuWqQ6PRoLKyskVlR6vVwmKxtLnM1svLCwaDAbrk5BYjT1clJsLT07N1Z2YKhdJj0KuQQqFcdWg0GiiVSpw7dw6ZmZmoqalBZWUlkpOTkZubi6CgoDYD6Lm5ucGjsRHCGTOAnByQ0FDg8GHYQ0LA5ORg6COPIJBacyiUPgF1RqbOyBTKVYnNZkN+fj5KSkrYvEgSiQQBAQFQq9VtTzsVFoJcey2Y3FwYNBqkfPgh7H5+sOXlYfjSpY7I06GhNPI0hdKNUGdkCoVCaQMul4vQ0FAEBwfDaDSCw+FAKBR2zK9GLgfj4wPCMLDs3Ak3kQh2ux1Sf38IDh8Gpk7t0sjTJpMJRqMRXC4XUqmU+v5QKJ2AKjoUCuWqhsPhQCKRdK5Rk8zqCn9/NHuX7KLM6kajEVlZWaisrGS3icViBAUFQa1WX1HfFMrVAlV0KBQK5XLo5szqRqMRZ86cAcMwGDJkCFQqFcxmM4qKipCWlgar1Qp/Oi1GobQLVXQoFAqlD+IMYDdy5Eg25o9UKoVKpUJ2djays7Ph7e3dfk4uCuUqh666olAolD6GzWZDeXk5/Pz8mgU2ZBiGzYZdXl7eG+JRKP0KatGhUCiUPoTZbEZ+fj7sdjvy8/NRVlYGX19f+Pr6smkIBAIBxGIxDAZDL0tLofR9qKJDoVAofQSDwYDExER2ubu7uzs4HA6ys7OhLSwEx0MDK1cAH6UcJrMZfD6/lyWmUPo+VNGhUCiUPkJaWhoYhsGYMWOQkZEBg8EAf39/ZNSakSPwhrnhoj9OnRECcSgUIlnvCkyh9AOojw6FQqH0AfR6PUpLS6FWq2Gz2eDl5YXKykrsS87BOaigN5ld6psZPvaUmJBea+oliSmU/gG16FAoFEofoK6uDjfddFObddacqfjnC8MAhOAPrR5DlAJwaBBBCqVFqKJDoVzl2O12VFRUoKqqCjabDTKZDL6+vhCJRL0t2lXFZUU7ZhjUWwm0eguC5HSZOYXSElTRoVCuYgwGA86dOweDwQC5XA4+n4/CwkIUFBRgyJAhbWbwvurR6WCtqUEZn4+KigrY7XZIJBJoNBoo6uo6HRnZzc0Nu3fvxpAhQ+Dr6wudToe/UvOQI/Frt22D5apOWUihtAlVdCiUqxS73Y5z584BAOLi4iCTORxbrVYrsrOzkZGRAbFYDDc3t94Us2+i08E2bRqshYUoWLcO0vBwiEQi1NTUoObcOcQ9+yx4Gg2YvXs7rOyIRCIEBgaipKQEHh4e8PDwgFxYBIG49SzqTqR8Om1FobQGVXQolKuUqqoqGAwGjBo1ilVyAIDH4yEsLAz19fXQarVU0WkBu04HS1ERRMXFGPv88+AcOAAEBIAUFMD673+DX1AAK8OAV1/fKavO0KFDcf78eSQlJUEul8OTa4HAboGZ4Tl8ci6FEMgFHATI6DJzCqU16KorCuUqpaqqClKpFPIWMmwzDAO1Wo3q6mrY7fZekK5vUyUW4+x778EeHAxObi4QHw8cOQJmyhTwCwpg8vdHyocfdjrnFY/HQ2xsLIYNGwaRSAShQIBgY8nF0kumpwgBGOB6fxl1RKZQ2oBadCiUqxS73c5G2m0JZxkh1P/jUmpqasANDgbn4EGHkpOTA0yY4CgMDUXdDz+gpq4OFoul00H9OBwOPD094enpCQCIbGyEOC0fF+xKmDn/OBwLYcVEDz6GqoStdUWhUNDPLTpr1qzB6NGjIZfL4e3tjdtuuw3p6em9LRaF0i+QyWSoq6uD2WxusbyqqgoSiQRcLreHJesfMAwDBAQAW7a4FmzZAnLRktMVSqLZbIakvhyTSDGuV5gw1YuDW3w4uI5bgYacZJrvikJph36t6Bw4cACPP/44jh07ht9//x0WiwXTpk1DQ0NDb4tGofR51Go1GIZBZmZms+mpyspKVFRU0FVXraBQKNDQ0ABDRgYwb55r4bx5qD1/HmKx+IpTNBBCkJWVBblcjlEjRyJukB9G+7sjSuOOmJhoeHp6Iisri04vUiht0K8Vnb1792LhwoWIiopCbGwsEhISUFBQgNOnT/e2aBRKn0cgECA8PByVlZU4efIk8vPzUVxcjPPnzyM5ORmenp5U0WkFLy8vSKurwZk61TFtFRoKHD7s+JuTg4D58xHIMJcXG6cJDQ0N0Ov1CAoKAofjertmGAZBQUEwm82oqam5ov1QKAOZAeWjo9PpADgS4bWGyWSCyfRPyPS6urpul4tC6at4e3tDJBJBq9WyGbOlUinCwsKgVqubPVwpDrglJRj5zDPgFhbCoNGgdPNmMBoN9B9+iEEPPABxcTFEc+YABw502iG5Kc57VdNVcU1xbm96T6NQKK4MGEXHbrfjqaeewoQJEzBs2LBW661ZswavvvpqD0pGofRtFAoFoqKiWH+SK7VCXBXI5eCq1bAzDMq++AJlfD5sRUWQ+vqi4ZdfILrzTjDe3o6ggVeAc+qrsbERQmFzp2ODweBSrymEEDQ0NMBut7tMo9ntdpSXl6OkpAQGgwE8Hg/e3t7QaDQQCGh0ZcrAgyEDZEnFo48+ij179uDQoUPwb+MNqiWLTkBAAHQ6HRQKRU+ISqEMaBobG1lLqUqlGripJHQ6oL6+mcWGEAJzTg4gl0Pg5QWGYUAIgdFoBAAIhcIOW8oIIThx4gTEYjGio6ObKaFpaWmorKzEuHHjWKdxQghKS0uRn5/P7pNhGHh7eyMkJATp6emoqamBm5sbFAoFTCYTysvLwePxMHz4cEgkkisdGQqlR6irq4NSqWz3+T0gFJ3Fixfjp59+wsGDBxESEtKpth0dKAqF0jZmsxlpaWmorq522e7l5YWwsLArdszt6xBCUFhYiKKiIlbBEIvFkMvlqKuvR5mZAwuHBwkXCPdxQ3BQYIcUnsrKStZnKjg4GFKpFAaDAVqtFiUlJRgyZAj8/P5JE5GXl4e8vDx4eXlBo9GAz+ejuroaWq0WhBBYrVbExsa6BII0mUxISkoCwzCIi4ujVj1Kv+CqUHQIIXjiiSewfft27N+/H0OGDOl0H1TRoVAuH0IIqqqqUFRUjPx6EywMD15KGUYPDgCfx0NZWRlyc3MhkUgwfPjwAevzQwjBhQsXUF5eDh8fH3h5eYEQguzsbBRbBciXaGBi/vEUENgtGMbT4/roQR0ak/LycmRlZbmEAuBwOKwS6bTmGI1GHDt2DEFBQc1e+vR6PU6dOgWZTIa4uLhm+6ipqUFSUlIzJYhC6at09Pndr310Hn/8cXz99df46aefIJfLUVpaCgBQKpUQi8W9LB2F0gI6HUhdHSpEYqSV1aDBSiAXcDHMzxOq+vpOJ4LsTex2O1JTU5FRa0aexBdmqcNik2kBTqfW4AZ/OYb5+UEmk+Hs2bOoqKiAj49PL0vdPVRUVKC8vByRkZHw9vYG4FgcUWwVIEMa0CyosZnDxxmbCsr8CowNaX9MvL29oVKpcO7cOej1enA4HPD5fJSVlaG6uhrh4eHw8PBAaWkpuFwuAgICWu3LYDCAENLMaqNSqcDj8VBXV0cVHcqAol8rOp988gkAID4+3mX75s2bsXDhwp4XiEJpC50O9unTYSwsxo5Pf0S15uIbtwlIPZSBeY/eCZFf5xJB9gY2mw02mw15eXlIrzUjU9L8oWoCD78UGsDj8xDupoRSqURpaemAVXRKSkqgVCpZJQeAw8ol0QBggJZmghjgaC3BaELaTeFACEFqaiqMRiMiIyPh6ekJDoeDxsZGZGVlITk5GSNGjIDBYIBUKm0z4rXNZoPVam3VgZlCGWj0a0WHXpSUfkV9PYxFxZAUaXHXI3fj6892oF7tB3lpEe565C6ICwtgAANxJxNB9hQ6nQ4FBQWoqqoCAFTxFA4lp6WHNMMAhOAPrR5hKiGkUmnvhHLQ6WCtqUG5QIDKykp2+bxGo4G0pqbLLGgNDQ3w9fV12VZstLtMVzWHgRE8aPUWBMnbXu2k0+lQW1uLYcOGsakhAEAikWDYsGE4deoUCgoKIBKJUFtb26LFxhnl2maztRjtuqqqCjabre9Zc3Q6GMrLoSVAXp0JZoYLd6kYsYHekFZX9ysrKKV3GJgT5hRKH6RepcL/Nv6IGv8guBXm4Z6HboNf0gnc89BtcCvMR41/EP73yVZYL3lg9gUqKyuRmJgIo9EIPz8/VLel5DhhGOhtgFZvgV6vb3F5dLei08E2bRqsEyYg/9AhGAwGWCwWlJWV4dyuXbBMmADMmOFYPXWFcLncZqk0LJyOOV83WNp/YauoqIBIJIKHh0ezMg6HA19fX1RWVsLT0xMmkwkVFRXN6jVVfioqKlxeFBsaGpCZmQmFQtFiktdeQ6eDeepU2OKnYH+mDme4aiRzvHDQIMNX+1JhnDCxy84hZeBCFR0KpYdIL9OhWhOCrz/7CTX+wXArzMO8+/4Ft8I81PgH4+vPfkKVJhjpZW3ftE0mEwoLC5GXl4eysjLYbLZuldtmsyEtLQ3u7u4YNWoUDAbjxSmZjlFWW4+6ujqo1epulLI5dp0OlsJCiIqLMXzpUkCrhdFoBPfid35BAWylpY4l4leIl5cXysvLYbFY2G0+qo4pDFJ++yucrFYrBAJBq6uhnEqkRCKBh4cH0tLSUFxczP426urqcO7cOdjtdri7u+PChQs4deoU0tPTkZSUhJMnT4LL5SIqKqpPrbhqKC2FuaQUsmKH1VNeWgQAF62gd0JUkA9TSdecw06h08GQmYms7BwcTM7EX6l5SC2tgc1uBwoLqeLVx6CKDoXSQzReTEdUr/bDL6s+cin7ZdVHqFc7lgin5eajrKysWXu73Y7MzEwcPXoU2dnZKCoqwoULF3Ds2LEW3+C7ioqKClitVgwaNAgMwyCvzuiYkungA7GsIBdubm4tWiO6k3KBAGfXrYNBo4G4uBhjli/HRA4HY5Yvh7i4GAaNBqkffXRFkYud+Pn5gWEY1lkYAIb5eUJALEBrU+yEQMZjECBr3/IjkUig1+thtVpbLNfpdODz+eDz+awPT0ZGBg4dOoRDhw7hzJkzMBqNiImJQXR0NGJiYiCRSFBfXw9CCMLCwjBq1Kiet7q1g5YAX3+2g30xaGYF9QvC/zZug73J8vruhtTWwhgfD1v8FPyVVo0jFjecMMmws8SGzb8mwjzpWmpl6mP0ax8dCqU/4SEVA3o75KVFuPmlx13Kbn7pcdZnx1MhxYULFyAUCqFSqdg6WVlZKCkpQWhoKDQaDXg8HhobG5GTk4OUlBTExMS0mf7kcmloaIBIJIJEInEEw2vT76QJhEBArAjzVGDw4I4to+5KSkpKUCuXo27nTtjvvNORk2riRIdoQUE4uWoVGImkVZ+VziAUChEbG4vk5GScOnUKYrEYhBAEWwXIkAQ4lJ2miuHF7zcEyNp1RAYcCVjz8vKQm5uLwYMHu1hd9Ho9SkpK4O/vD4ZhwOVyERkZiZCQENbvRiqVwsPDg23n7u7eLb+VriavzohqTTC+/mzHReXGYQUFcNEKugP1Pn4d8nPqKkozMyEvr2CtTE197e54cBYERfkwAxD0UV+7qxFq0aH0WQgh0Ol0yM/PR35+Putk2V8JV6vgUZKPex6cyU5Xbdm865+31QdnwqusABOjBkMmk6GgoIBtazQaUVxcjNDQUAQGBrKraiQSCaKioqBQKJCXl9ctcnO5XFitVtjtdjAMA4Wwg4H/GGBGkBJDh4ZdsSJxORgMBtx0001Qx8VBlpcHGcB+5Pn5uG7+/C7dn1wux9ixYxEZGQl3d3d4enri2vBA3BYsh5TnqszIBRzcHiLHUFXHLChCoRCDBg1CUVERzp07h4qKCtTW1iInJwdnz56FWCxGYGCgSxuxWAx/f38EBQXB09OzT01JdRSnUt2eFbQjfk5dgd1uR47Fgm837WzZylTksDJ9/dmOHrUyUdqGWnQofRKj0YjU1FTU1dWxD/Xc3FxIpVJERUX1yzD13OJizH/sTgib3Azr1X6Ot9UHZ8KtKB/zHr0T3L8PwtfXF5mZmay1oaKignU6vRSGYeDv788uP+7qlAuenp7Iy8tj4+BEaTyQXGKGmcNHy+umHVtnBssR7tZ5WQghrOPslTycO2pBMplMXfZ74nA48Pb2dllm7gkgzE0Ird6CBguBlO+YruqIJacp/v7+EAqFyM/PR0pKCgCHEqpWqxEcHNzmkvL+iptEBJjRrhW0I35OXYFer0eljY9KdWDbViZPTY9amShtQy06lD6HzWZDUlISTCYToqOjMWHCBEyYMAGxsbGw2+1ISkpycfrsN8jlEPqqYQ4KwdbPfmTfRuvVftj+3+0wB4dAoPYB5HI2xonTguWMe9Law8yp3LTmw3ElyGQyeHh4ICMjAxUVFfBV+yBGYHAEwbvUwkYIAIKZwbJOKzkWiwW5ubk4evQoDh48iL///hvp6elobGy8bLn//OILVGk00APQBwej8pdfUOXrCz2ACrUawvJynDhxAikpKd0ydk44DIMguQCR7kIEyQWdVnKceHl5YdSoUbjmmmswZswYjB8/HkOGDBmw6TViArzgXpyLex5q3QqqrizqkJ9TV2Cz2WDh9C0rE6V9qKJD6XOUlpbCYDAgNjaW9StgGAZubm6IjY2FxWJBcXFxb4vZeZRKYO9eCA4dxA1RXohsyMVN/mLMGazAwmnDIfj7IHAxWGB1dTWEQiE75SMSiWAymdgcSpei0+nAMEy3OZNGRERAqVQiJSUFx44dg5u5FmEGrcPZtgkyHoPbQxSdVnLMZjPOnj2LwsJCeHp6Ijw8HAEBAaiqqsLp06dRfxmravwBjFuxAu7FxeBqNChLSECqQoHM998HR6OBZ2kpRj/7LMJlMlRXVyM5OblfTI0yDMP6TPXGlGBPoqyrw/xH72Idj7/+bAeKYsc4HJT9guBWlI97HrodnKKiHpFHKpVCQBwKcWtWJufKsJ6yMlHahyo6lD5HRUUF3N3dW5xOEIlE7FLefolSCfj7Q+OrhtLWCEGVFoHOaQx/f+Bi3paysjJoNBp26sbLywtcLhe5ubnNHsZms5lVELrrzZ7H4yE6OhojR46Et7e3I19SgCceG+aBOYMUuDVIjjmDFXgs2qPDfidNyc7OhsViwahRoxAWFga1Wo2QkBCMGTMGEokEqampnVZClP7+IF5eMGg0SNu4EYUM44jqrNEgaf16mPz8wNVooB4yBMOGDUNtbW2zhKSUXkYuh8jPF6agYPz4n20uVtCfNv/kYgXtCQQCAUJVErgX57HTVi1ZmXyrSnrMykRpn4E3qUvp91gsFijbWK0gFApRW1vbcwJ1AwKBAEOHDkVaWhobVZfH46GmpgalpaVQKBTwb7LsmcfjYciQIUhLS4PZbIafnx+EQiHq6uqg1Wpht9sRGhrarTIzDAOFQtEseV7QFRqRLBYLysvLERIS0ky55fF4GDRoEBITE1FTU9OplUKMSgXx/v0oSktDg80G+8XpTpvNBu8RI8A7fBiMSgUolVARAplMhrKysh5fBk9pg4tWUGF9Pe7383P1cxruAc7fB3s8MvIQsQghD8+AtKgQNf4t+9rNeXCmQ7YuCF1AuXKookPpc4jFYuh0uhbD2AOO4GcDIWmrWq2GUChEQUEBMjIyADgUoKCgIAQEBDSbllCr1eDxeMjLy0NycjK73dPTE4MGDeq3Y9LY2AhCSKtKjFKpBJfLhV6v7/SSaEalgv8110Bjt+Pvv/+Gn58fQkJCmo0twzAQi8Wd8v2yWCxsIL+BPoXUqyiVgFIJDtDcubcXFAmhpyf4/n4wcDj44ZOtl1iZduKeh27rUSsTpX2ookPpc/j6+uL8+fMoLy9vlgSyuroatbW1iIiI6CXpuhY3Nze4ubnBZrPBbreDx+O1udLI09MTHh4eMBgMsFqtEIlEEAj698oO5+qo1pyB7XY77Hb7FcXhaWxsBI/Hg06ng8FggEwmcyknhKC+vt4lblFrOEMeOKe5OBwOfHx8EBwc3OcC7lG6AaUSnF9/hbi+Hos0GuTXmWCwM5DxOb1mZaK0DVV0KH0Od3d3eHt748KFC9DpdPD29gbDMKioqEBRURHc3d3h5eXV22J2KVwut8NWAYZhOr0c2mq1ory8HLqL0VpVKhW8vb37hCVCKpVCKBSitLS0RUWjrKwMhJDLmlIymUy4cOECO9VpsVhw6tQpqFQqREREsIpJWVkZjEZji8v3m1JVVYXk5GRIJBKEhYVBJBKhrq4ORUVFqK6uxsiRI9k+ncvkezpQIqUHuGhl4gIIVV1iSaXTVX0OquhQ+hwMwyAiIgJSqRRFRUXsCisej4eAgAAEBwd3y8PDZrOhoqICer0eHA4HHh4eUCgU/TLQWlNqa2uRnJwMq9UKhUIBQgjKysqQm5uLYcOGNfO56Wk4HA4CAgKQlZUFiUQCf39/cDgcEEJQVVWF7OxseHt7d3pqzhmmwGq1IjIyEiqVik1MqtfrcfbsWURERKCiogKFhYXw8fFpcyzsdjvS09Ph5uaGYcOGsb9Bd3d3qNVqnDlzBtnZ2QgODoZWq0V5eTlsNhuEQiF8fX3h7+/fYniAuro6FBeXoNhoh5UjgNpNgUiNO3iXKKEWiwUGgwFcLhcSiaTf/y4plJ6CIf1hPWU3UldXB+XFlS69fcOnNMdut7NxVMRicbdZIKqrq5Gamgqr1QqxWAybzQaz2QylUomoqKh+Oz1kNBpx8uRJyOVyhIeHs/F2DAYDUlNTYTAYMGbMmF4/PkIIcnJyoNVqwefzIZPJYDAYYDQa4ebmhqioKFitVlgsFgiFwg7JW1xcjIyMDIwePRpSqRSAQ1nIyspyySXG4/Hg5+eHoKCgNhXoiooKpKSkIC4urtnUFwBotVrk5OSAYRjweDz4+vpCJBJBp9OhvLwcEokEsbGxLjGSMjIykFLRgDyJL8zMP6t0hMSK6YEKRHpKYDabkZ2djfLycnblmTMScnsWKAplINPR5ze16FD6NBwOp8WHyuVCCEFdXR1KSkpYvw1n+gR3d3cMHjyYzelUXV2NtLQ0nD9/HiNHjuyXb9BOa9iwYcNcrAlisRjR0dE4duwYSkpKEBQU1FsiAnBY8QYNGgS1Wo3S0lJWwfHx8YHdbse5c+eg09UhKUmF2NhaeHl5IjQ0tM0pvLKyMri7u7NKDgDw+XxERERg0KBBSElJYZe0d0SBbmxsZJWwllAqlSCEQCKRYMSIEex4O605iYmJyM3NRVhYGACHYpRS0YAMaQAujTBtAhc7tQ0AgPrs87BarQgJCYGbmxssFgtKSkqQnp4Os9nc6+eOQunr0MljylUDIQSZmZk4e/YsdDodxGIx7HY78vLywDAMhgwZwj44GYaBh4cHoqKiUF9f32/jq1RWVsLb27vFKROBQABPT09UVlb2gmQtI5VKMWjQIERFRWHo0KGwWCw4d+4cAKC0dDiWLh2OoqJh7NRTW1GTLRaLy3RXXV0dUlNTcfToUZw+fRoWi6VTCT2dOb9acpo2mUzIzs4GANbpuamxXCaTwc/PD6WlpWzeMG1hIQpkfmgxjQbDAAT4XVsPk9mMESNGIDAwEHK5HO7u7oiKikJgYCByc3NbDSJJoVAcUEWHctXg9PcJCwvDmDFjEBERgdjYWAAOy9GFCxeaBaVTKpWQSCSoqKjoDZGvGOdKrtbg8Xiw2+09Kk95RSVOZGnxd1YxMirrYW9l9txutyMjIwOenp4YMWIE/vhDBQDYv9+TtcI4lYuWEIlEbETloqIinDlzBvX19fD09IREIoHBYIDJZHJJntoWnp6eIISgtLTUZXtRURGOHj3KOnqbzWacP38ep0+fhslkYut5eHjAbrfDYDCgoaEBlTY+jKQNJYthYAAXPK+AFi1XgYGB4HK5zeShUCiuXNbUVXV1NWvyb42CggLk5eXh2muvvWzhKJSughACrVYLHx8faDQal+2AY3qhsLCQnfN14kyrYLPZulW+xsZGaLWFyKrWw0g4kAt4iFC7wU/je0WO17KL6Q1CQ0ObTb05p+faCs7YldTW1uJgegGyeJ4wcy5aWupNEGkbMT1IgQh3V2fj8vJKfP+9F1SqYPz0E4OtWx3bt24FQkL4qKuLhNFYijffNEEsvrisW6eDpboapTwejEYjGhsbWQteEJcLrkSCvJISF+UuJycHJpMJgwcPbnN6UiQSQa1WIzs7GxwOB2q1GjU1NcjMzIREIkFjYyMYhkFcXBzq6+uRmpqK5ORkdtrTaQnicDguOZPagxG1PD3H4/EglUphMBg61A+FcrXSqTvooUOHEB0dDS8vL7i5uWHcuHH4+++/W6y7efNmTJkypUuEpFCulMbGRphMpmZxeTgcDkQiESwWCxuZuCk2mw11dXXdmi29trYWvyVmYJdejvOiQGSK/XGGq8YPZQx+P5d5RRYXjUaDhoaGFnODabVaGI1GF8Wvq7HZbDAYDKitrcW+1FykCnxh5rg6EhsJBz/l65FW4zoFU1VlREJCCF57TYCXXgIaHC4r0OuBl14C3n5bgc2bQ1BVdbGdTgfbDTfAOnEiio4dY2MM6XQ6CMvLobnnHij//W/ILy75VqlUGDNmDLhcrsvqvrYICwuDt7c3MjIycOTIETaLuMFgQGBgIAghqKysZJev19fXs0vbS0tL2RxVEokEQnRMeebZzC1uJ4TAZDIN2ISeFEpX0WFFJz09HdOnT0dKSgqGDBmCyMhIHD9+HNdddx3eeuut7pSRQukyWrKOaDQadhVO06krQgjy8vJgs9m6bXWL3W7HgbR8pIn9YOa4PrDMHAHO2t1xOOvyExa6ubnBz88PmZmZSEpKQklJCYqLi5GYmIicnBwEBQV1i0XHbDYjIyMDhw8fxvHjx3E2MRG5QjXa8kf5Q6t3mcZSqbj4z39OY9w4h6LnNKo5/44ZY8GmTafg5uawjNhqa2EpKoK4uBhjly9HjJsbxo4dC0lVFYYvXQphYSEEtbUwV1bC19cX0dHRkEgkUKvV4HK5yMvLa1ep5HA4iIiIwOjRo+Hr6wu73Q5vb2+MHz8eoaGh8PDwQGZmJmspE4lEqKioQH5+PsrLyxEYGMiuygrzVEBgNzfPAO+EEAiJBbbKohYtihUVFTCZTPD29m77ZFAoVzkdVnRWr14Ng8GAb7/9ll2JcuzYMQwePBj/93//h5deeqk75aRQrgixWAwej9ei462fnx8kEgmsViv0ej2qq6tRXl6Oc+fOQavVYtCgQeyy7K6mrLwCqVYpzIZGmA0NzT/GBpyq58F6mVNnDMNg8ODBCA8Ph9VqRXp6OjIyMmC32xEZGYmQkJAuPiKHY+6ZM2dQUVGBgIAADBs2DHVcaTNF7hJBobcBWv0/KRi8vLzg42PCF19ocalBTSIh+OijVISE8FhrW7lAgLPr1sEeEgImNxeIjwf3+HHELFkCcXExDBoN0jduxKiZMzFkyBDWCdlut0MgEMBisXQ4h5pUKkVAQAAAwNvbm7WqOOM/nTt3DqdOnYLFYkFpaSlyc3ObLQf39vZCsMHpX3OJskMIwAAhxjKYTSacP3+e9Tey2WwoLi5GWloaPDw8IKepBiiUNumwj86+fftw00034e6772a3jRkzBsePH8dtt92G1atXw2azYfXq1d0iKIVyJXA4HGg0GhQWFsLDwwNubm5smd1uB8Mw4HK5qK2tRVVVFQCHf0tkZGSrb8w2mw1lZWUoKyuD2WyGUCiEWq2Gt7d3h/1qcmsN+L9JQ9qss+ZMBXJrDRjicXnL7BmGgVqthlqtZi0W3RmtNzc3FzabDSNHjmTzR3XUH6XB8s8DXyAQwM/PD3v2VKOhwXUJdUMDg6NHbfj3v4NZv5rq6moIBw8G58ABID4eyMkBJkyACIBBo0HiunUwyeUuq6xsNhsqKyvh5eUFg8HQqVxXfD4fAoEAVVVV8PT0BODwmxk+fDhqamrYEAZubm4uK/qc1NfXw9Ouh4/CjBN1XJiYf8ZIxudgggcXuoxahA4ejNzcXJw+fdqlvYeHByIjI1v0KyKEoKGhASaTCQKBADKZDEajEUajEXw+H1KptF+GS6BQLocOKzplZWWIjo5utl2hUGD37t249dZb8dZbb8Fut+PNN9/sUiEplK4gKCgI9fX1SEpKgru7O5RKJSyVlajMzYXJy8tl2srT0xNDxOJWcxdZLBYkJSWxiSY9PT2h1+uRlpaG4uJixMTEtLnayYmpg0bVxi7yhe7udATOVBNBQUHs0m4ejwcR07G4pFK+68N30KBBOH++FgAwcWIFnniiAO+/H4jDh72Qnh4GLy9X5Y/D4QABAcCWLcCECez2tP/7P5guUVhtNhvS0tJgtVpZq0hnoi8zDAONRoOCggL4+Piw6SsYhoFKpUJxcTG4XC6ioqJa/S0wDIPxgzQYB7hm5pbxoa+vxxkAJRedpxUKBXg8HqxWKxoaGlBfXw+j0egSJwhw+HxlZWVBr9cDALh6PfhGI4wXlTEAkEgkCA0NhafRSPMy6XQwVlSg5GLiWGdoCW9vb3BLSuj4DAA6rOh4enqirq6uxTKRSISff/4Zt9xyC9555x3Y7fZmFx+F0ttwuVxER0ejrKwMxcXFKL5wAVHLlsGvpgYZn34Kn7g4NpJtxZkzIIsXw+7vD85vvzW70aWnp8NkMmHUqFEuUwc6nQ7nzp1DVlYWwsPD25XJWyHDq4fz2q2nEvWPyMxGoxF2u90lZxXDMAj3ViJDZ2l9+ooQR1JEmWs5wzBYsMANEyZYcN11Jlit7vj+eyv++suOkBBXJUehUCAnJwfm7GwI5s1zKYt55x2cePttmLy9kZqaCoZhUFVVBbvdjvDwcBQVFUEqlXZ6GiggIAA1NTVISkqCt7c33NzcYDabUVpaCoPB0KaSo1KpkJOTg+rqanh4eDTLzF1eXg6GYWA0GhEQEIDaWh0OH+Zj/HiHAlhYWIjU1FTExcWx1pmamhqcO3cOcrnckaaivh68m28Gv7YWievWIWD8eEgkEmi1WmT+9RdUzz0Hnq8vsHfv1fkw1+lgnjoVpKQE5Rs2QBwWxk7xFh8/jhFPPw2Oj8/VOz4DhA4rOoMHD8ahQ4daLRcKhdi5cyduvfVWrF27Fmq1uksEpFC6Eg6HA19fX/j6+sKWnw9zTQ3ExcWIWbIEzP79gFoNVX09Ap95BkxxMcxcLgT19S43OYPBgMrKSoSFhTV7MCqVSgQFBSE3NxehoaHtpioIV6sgLzXDBK7DKfdSCIGUQxAg7x8ra5zTQmaz60qhoKBAhJ1NRzJzcdVb02O96I9yQ4AMnBbGYMIEYMIEPoB/kiXOndt832q1GsXHj4PMnQsUFgKhoQ7Lzrx54ObkYPjSpUhctw5VHA6EQiG8vLwglUpRUFAAg8GA2NjYdqdznEqMMx+ap6cnoqOjHYpzcTHKysrAMAw8PT0RHh7eZggOuVwOhUKBzMxMiMVil6mtyspKFBYWgmEYcDgcFBQUIDU1CI8/HoIPPsjCsGEZkMlk0Ov10Ol0UKlUIIQgKysLCoUCsbGx4HA4SD1zBqE6HUTFxRj5zDNI/uADjJw5E256PSzLloGn1YJwuWAu+Y1fLegKCyEoKYG4uBhjli933AMCAmDIyAAzdy44RUUgDHPVjs9AocN27OnTpyM5ORlJSUmt1hGJRNi5cyemTp2KkpKSLhGQQukuKkUiJDqdV3NyHH4dR44A8fFgcnNhDQzEmbVrYblkSbozMJy3tzebf6nptJe3tzebaqI9uBwObgi4aJm4dPXNRQVgWpCiRQWgLyISiSCTyVBcXOwyJnw+H9OGhyEWlRAQVz8YCRe4PUSBoaqWpwk7Cr+sDHHPPgthYSGMGg3yEhKQp9Hg3Pvvw6DRsA8zT6MRBoMBpaWlyM7OBp/Px/Dhw9tdfVZaWoqjR48iLy8PJpMJ9fX1SE5OxtmzZ+Ht7Y1rrrkGkyZNwrXXXouoqKh2c+cxDMP62Jw8eRLJycnIysrCmTNnkJyczCZgJYQgLi4Op087HMcTEwcjJiYGDQ0NYBiGdVLW6/VoaGhAYGAgOBwOjEYjygUC1P30ExAaCmFhISIffxz1v/4KZsoUCLRaGDQaVG3detVm3NYSgvSNG0FCQ13uAeIbb4SoqAgGjQYV339/1Y7PQKHDFp27774b58+fR1JSEhtNtiWc01gPP/ww8vPzu0RICqU7aGxsBPH3b+a8CgAIDYXh559hLC9nHTgvpWn+pbFjjfD394Ofn1+n5RjmJQOPy8Nv2no0NlndLOMzuCFAfsUKQE/CMAyCgoKQkpKCjIwMhISEQCAQwG63o6qqClJ9BW5ws4Hn7Q+jnYG7VIwAOb9rFDm5HFy1GnaGQfHmzSjj8WAvKoLM3x+G3bshmjULXG9vDBo+HKisREVFBQghqK2tRX5+PoKCglpVTmpra5GWlga1Wo1Bgwaxv4e6ujqkpKTg/PnziIuL63TSWZFIhFGjRqG0tBTl5eVoaGiAWCy+mMTUji++kIHP98KBA7JLAia6o7o6GlZrJZ56yvGjcUZhdloZnakhpOHhwP79IPHxEOfkQHzjjQAAa1AQEt9+B2ePCnGdOB0aje9VldiYEIKqqiqExMY6LDkt3AOyPvgAHJEIdAF//6ZTU1fffPNNh+oKhUIkJCRcrkwUSo/gdOy0aTTgXuK8ii1bYPTyAsrLm/lYOPMrWSwWFBfHYOlSd2zcmA+TKRs6nQ5yuRwMw3TqoRHuLkKYm7CZQ2p/seQ0xcvLC2FhYcjKykJpaSnEYjHMZjOsViu8vLwQHh7ePVnolUpg715w6usR6u+P0EvLDxyAkc/H2exs2O12VrExGAwoLi7G2bNnER0dDXd392ZdFxQUQCaTYejQoS7TWwqFAlFRUThz5ozL6qvOwOPx4O/vD/9LrAbp6cXYvDkE9fV8MAzg9CN3BkwkxB1yuRyLFztWCTqVr8bGRggEAva7wWCANCAAxs8+g/j669n+zy1bhoO5Q/H885F4770LGDHiDPz8/NqNED2QIIQ4fot+fs0c2LFlC+xSKZjW4hxR+g001xXlqsXLy8uRe+n0aeAS51Uybx4qzpyBTCZziaHT2NiIgoIC9uH966+OaaeTJ4MwbNgwVFZWIi8vDz4+Pu3651wKh2EQJBcg0l2IILmgXyo5TjQaDcaNG4dBgwaxQQtHjx6NqKio7lFy4LBo5FRV4VhhIf7++2+cPHkShYWF/wTb8/dH9sU4SnFxcQgODoa7uzv8/PwwatQoqFQqpKenNwsaaLfbUV1dDbVa3aICoFAoIJFI2LAEXYVMRvCf/5xCVJQjQahrwESCYcN02LTpFDw9hawcIpEIWq2WzaIuk8lQWFgIUlAA7n33ufQ/7O23cfhXh/UnOTkcgwcP7nCE6IEAwzCQyWSO86bVtngPMGZmtpqtntJ/uKxcVxTKQEAkEiEAgOr224HiYsc8/ZYtIHPngsnJQcj998Owe7fLw62wsBg7dwZAqQxCWVkZfvzR8a7w3Xc2iEQWGI2BkMvteOut4N45qD4En89vZqXoLhobG5GYmAibzQYfHx+IxWLU1dUhOzsbZWVliI2Nhd1uR2VlJQYNGtQsbACHw0FoaChOnz6N6upqF8uMU/FpK9UCn8/v8uSoKpUKPj6Z+PzzXEyeHA2j8R8FUSi046OPUkGImZ2qYhgGoaGhSE1NRWpqKoKCghASEoKMP/+EaelSiIqLYfIPxIrRn0LyxylwtTrs04oBNMDhpuOGioogSCRmvPUWAZfbfxXtjuLn54e8v/+G7bnnwM3PZx3Yybx5YHJyELNkiWNqm9KvoYoO5eqlsBChixaBuRg199xbb4FwOCBvvonhS5dCXFwM8axZwIEDrDNiZaUBn38eAZ2OB4bRsNMJBgMHH3+sBiEM5HILXnuNh04adPodFosFOp3D2iCXy7stenR7EEKQmpoKHo+HUaNGuSgx9fX1SExMRHZ2Nnx8fFgHab1e3+xNXS6Xg8fjsVOTTrhcLkQiEaqrq5vlSgMcK7Hq6urg4eHRpccllUrh5uaGw4cZFyUHAIxGLs6dE2HaNA+XqVWnI3xWVhYqKiogrKjA8ItKjkGjwZE31mPdghub9PQuAKCuDnjtNccWudyMZ581wMen+/K79RXUVis8li0DV6uFyd8fNd9+C5O3N6rXrUP4o49CXFwMTJ/ucg+g9D+ookO5epHLwTiDyO3ZA7VQCKvVCnFgIPiHDgHXXw94ezsChl1EoWDw9ddpeOONYTh6lGkyncCAYYCRI434v/87B7l8TC8cUM9gs9mQnZ2N0tJSFyuGp6cnwsLCOj1ld6XU1dVBr9cjJiammaVGLpcjICAA+fn57NRSVlYWWzZkyBDWl8pqtcJmszWbWmMYBn5+fsjJyYFarXaJqk0IQXZ2Nht9uqsJDw/H2rUOua+7TocXXqjFqlVK7N+vwunTGjz6aHOfIB8fH3h5eaG6uhrmigrwfH1BRCI0/vgjPDswHbpp0ynIZDHsd4PBAIPBAB6Px/qfDRQYhQJ8Pz9YORykf/QRqhsawMnPh8egQbD+/jtwyy3N7gGU/gdVdChXLxedV1FfD7G/P4IuLT9woFlUVE9PT1RWpuGXXxoQECBlM2oDjvxL69cnwtvb7dKeBgxO60lNTQ2CgoLg4+MDDofD+iYlJiZi5MiRHYoK3ZTGxkYUFxez8Wk8PDzg4+PToX7q6urA4XBcFJCW5HZGPZbJZPD19UVBQQESExMxfPhwKBQKlJSUgBDSomXGz88P1dXVOHfuHLy8vODu7s7msWpoaEBERES3KHhCoRCLFnlj9OgqjBuXB6vVgvfeq8HRo8GIjvYCl9uym6Uzxg88PYE//wTq6+Hh7w9SWYndu3cjMnI4IiMVaGq8kkiAgwezYTTWQywWo6GhAZmZmS75v0QiEYKDgwdOnDSlEszeveDV1yPG3x+EEFdFroV7AKX/QRUdytWNUtn6TawFU7WXlxfy8/Px/fd5aGiIcilraGCQmCjAiBEVsFgs8PPza/Ph2x+pqalBVVUVhg0b5uLHotFooFKpcPLkSRQXFyMwMLDDfRYWFiIrKws8Hg9ubm6wWq3IzMxEQUEBYmJi2o2yzjAMG2/mUmuDzWaDVqsFAISEhMBoNCItLQ0SiQRRUVFITk5mp7VycnLg6+vb4hQch8NBdHQ066xbXl4OwJFvasiQIS6RoK8Uk8mEyspK2Gw2iMViTJrkgcmTPQD8o4CNGNGJDpv8xp153v74Q4fGRl+Xao2NwLFjdtx4oy+MRiPOnj0LgUCAiIgIKJVKGI1GFBUVsWkzesr/qttpMj7NrFUD5RivcqiiQ6F0Ai6Xi5iYGHz0UQ0AYPLkaixenI/16/1x+LAXEhMDcfPN9aisrERSUhKCg4MRHBzcu0J3IaWlpZBKpS1aPSQSCby9vVFSUtJhRae6uhpZWVnw9/dHSEgIO21kMBiQnJyMc+fOYezYsW3m6HJ3d0dWVhbKy8sdlgadDnadDpUiESoqKtjpKIVCAZVeD6uXF7IvKix8Pp+NLuzj44MhQ1pPsMrhcBAQEICAgADYbDY2anFXYbfbkZWVheLiYjbJrNVqBZ/PR3h4eJf4ADEMg6ioKHzwgSPo5fXX6/Hyy3V45RUp9u1T4tQpXzzyiCcuXLgAHo+HESNGsE7YIpEISqUSmZmZyMnJgY+PT5sO2n0ds9mMwsJClJaWuiTl9fPz6/Hp1wGHTgdSV4dqqRTpZTo02ghUYiGiA7wgLC/vcSvZFSk6paWl2LZtG9LS0tDY2IhNmzYBACoqKpCbm4vo6OhOJcmj9DxWq5W9mXbXst+BhlgsxkMPiTBhQj0mTixFRYUO69fbkZrqhkGDPBES4ong4GDk5+cjLy8PSqVywFh2TCZTm5mvpVIpKi8u4e4IWq0WcrkcgwYNculTLBYjMjISJ0+eREVFBesE7Iw4XVtbC0IIlEolVCoVPDw8kJWVBbHZDMkdd8BaXIzsdetgvtjOZrPh9I6fUPPw17g2IAfuu35BldWK+vp6lJeXIyAgoNXl4y3RHddKZmYmSktLERISArvdjtLSUjby9vnz5zF06FD4+vq231E7yOVyLFokwKhRpbjmmlzYbFa89ZYYJ04MQkyMF2w2KyorKzFkyJBmiowzIGRJSQkqKiqg0WiuWJ7ewGAwIDExEVarFWq1GhKJBA0NDSgsLERZWRlGjBjRakJfSjvodLBPnw5jYTF+/PRHVGscEb1hAc78fg7zH7sTIk3P5le7bEXn448/xjPPPMNG42QYhlV0ysvLMW7cOGzcuBEPPvhg10hK6Tp0OjSUliLXYkV2TSMsHB6EsGGwuwwhfB5EXl50TrodJk5kMHGiHDk5InC5XIwYMRxxcf88/JwPhIqKChQWFg4YRUcgEDgiSrcwTQT8E6yuKYQQxzgUFaGo0QYLhw93qRgxAV6oqalpNUCdM8mmc7WT0WhEamoq6urqWN+dvLw8SKVSDB06FFlZWUg9fhzDi4shLi7GiKVLcXbdOpi8vSEsL0fRoztxe/UP2GG/F5pjx+B/zTVs+gStVgutVguZTIbQ0NAWgwZ2JwaDASUlJQgKCkJxcTFMJhPrSG21WpGfn4/09HQIhcIuke2664S47jo1gH98bUaPdvzV6x15ylqLHyMUCiEQCNjIy/2R9PR0MAyD0aNHu0xVBgQEIDExEenp6YiJiWmjB0prkLo6GAuLISnS4q5H7sbXn+1AvdoP8tIi3PXInRAV5sMEBsIezB92WXbXn3/+GYsXL0Z0dDR27tyJRx991KU8KioKMTEx2LFjR1fISOlKdDpYb7gB5LrrcbTAiAuyEGRJApAiCcbfOXrY4qfANm0acDGfE6VtdDod3N3dW3zDZxgGXl5eHcp5dbnY7XZYrVaXvFJOCCGwWCywWCwttLw81Go19Ho9qqurm5UZDIZ/po+ayJCVlYVDGYU4AF+kSIKRIfLDMZs7EnIMqOYp2rSOcDici8HybEhKSoLJZEJ0dDQmTJiACRMmIDY2FoQQJCcnOzKFBwfj/Pvvw+TnB1FxMYYvXQplSgpGLVuGn6unAAB+jP8AxM+PzUAvFAoxdOhQKBRKHD0qRFLSORQUFLQ4pt2FMxlofn4+K1NDQwOys7NBCMHgwYMBAKmpqf8EQOwmmkZUdkIIgdlsZn9PFoul305bNTQ0oLa2FiEhIc38scRiMYKDg1FdXe1y/JSOUy2V4n+f/oga/2C4Febhnodug1/SCdzz0G1wK8xHjV8QtmzcCvtlpMu5XC7LovPOO+8gMDAQ+/btg1QqxenTp5vViY6Oxt9//33FAlK6FlJXB1NxCWTFhbjz4Tsv0bbvgrSoEI0MAwnN1tshnI6wrdHVQeScOCM0l5eXw263g8vlQq1WIzAwEAKBAMXFxSgqKmJjwshkMgQEBMDb2/uKlge7u7vDzc0NKSkp7Oob56qr3NxcCIVCaDQaWCwWlJSUOLJ6WwXIkAQABADjyFWae5qPkJEEGZIASEqrWpySccanCQ0NRVlZGQwGA0aPHu3inOzm5obY2FgcP34cRUVFaGhowNDx4yE8ehTGcRPwedEtqF1cjN2Yhx+YuwEC7PhdBYmXGlarFVKpFffeW4f09HQkJvpi6dKhePvt82CYHEdfQ4d2qR9Oa9TU1IAQAg6HA7VajbCwMFgsFhQWFiI/P58dH6vVioqKim5d9SQUCqFSqVBYWAhPT08UFRWhqLgYFVYeLBwepDwGIrsd3t79MwOUXq8HgFZ9npzb9Xo9db24DNLLdKjWhODrz3ZcVG7yMO++fwEAavyD2WdOfp0JIcqeib11WYpOYmIi5s2b1+ZqCD8/P5SVlV22YJTuoUYmw9ZPt+GuR+5mte1fVn2Em196HG6FeajxD8IPG3/Ave7uaHutCwVwPGjz8/NbfMMlhKC8vLzLp630ej0SExPB4XAQGBgIiUQCvV6P4uJiVFRUQKFQoLKyEl5eXggODgYhBGVlZbhw4QIaGhoQGtosC1SHYRgGw4YNQ2ZmJnJzc5GTk8OWubu7Y+jQoTCbzUhKSnJYkhgGedJAZ2MAQMYRPhKeUGLhBzoMHW9Gql2B2NIy+Kr/CcZnt9uRkZHBxqdJSUmBu7t7i/ccoVAILy8vVFRUAHA4zcLNDWeeeRkvP307quEBBnZwGAAEaGgAPv00AAADhcKCG288gdGjo/Hll44pofPnh2L06CMoKyuDSCRCSEjIZY9XR7DZbOwUmt1uZ1ez8fl8hISEwGq1oqSkBAzDQCQSsQ/q7iQkJARnz57FsWPHUM5IUCAJhRH/WN4EPG8IC6swflD/89FxKvo2m63F8AVOi1mnXgh0OtQUFEBLgAK9BRaGC7eL07PuDQ1X1RL1Rpvjxa9e7YdfVn3EKjkA8Muqj1Cvdlhy6s3da5lsymUpOna7vV2zZXl5OXXm6oPk1ho6pG3n1DQiWjLwI6NeKc54LKmpqYiMjGSvC5vNhqysLBiNRkRGRnbZ/gghSEtLg0gkQmxsLLs/b29v+Pn54eTJk6isrERERIRLFF8fHx8UFBQgJycHnp6eV5SlmsvlIjw8HKGhoaxTsFwuh0QiASEEiYmJ4PP5CA4OxsnsIpg5rj47yX847gvJfwoxdIIFZkaAE5m5CCotgbu7O6xWK8rKymA2mxEVFQU+nw+r1dqmzCKRCDU1NeBwOKirq4ObXo8R776Cs3gNc/ANjmIcbHaHZcZu5wAgiInRIzY2D3v3huDoURG2bnVYv376iYBhPCESiSGV2vHWWzbw+d3nqF9bWwu73c5aBy+davTy8kJRURGUSiUaGxt7xMKkVCqh0WiQXK5Hhvgfa5wTM4ePgzpAXl6PaO/eD6ZnNBpZR2Kr1QqRSMSuoLpUmVGpVGAYBqWlpQgKahY9C6WlpeBwOB0PGaDTwTRlCvhl5Tj+n59Q5XuxTxuQcSQL8x+9CyK/nnW+7U1UYiFgAeSlRbj5pcddym5+6XH2GaMU9tzU52VdMUOHDm1zWspqteLgwYOIjo6+bME6ysGDB3HLLbdAo9GAYRjqF9QOpotvZU5tuylNtW0jofleO4JAIMCwYcNQV1eHo0ePIiUlBRcuXMDRo0dRUlJy0ffj8pWKS3FGAQ4NDW32suF0EgUcD6pLCQgIgEgk6rKkjQKBAN7e3vDx8YHkolJcVVUFg8GA/2fvveMbuev8/+eod1mW5SLJ3d61vWuvt2aTQEjocPyoB3eUwMEXODg4joTQrsBRQ7gjIcnR+4V2QCCBSwgHIQWSzWaL7bW97rZsq1m2LNvqdX5/yDNrre3NxtlNIX49HvtYW5Kl0Wg0n/e836+yY8cOfD4fWYWKQgH+dFue33+twO+/VuDU77NAnFO/z8q3/eGeRvJ5kenpaQKBADabjf3798vdDb1eL8dNbITl5WVZ3h46cYLsc56D3u/H4cxz40196IVSvoVOV+Czn+3jtts6uflmF5/+tIlo1ASYWFkx89//3ck3v9nCt79dRyCwMccqnU6zuLhIJBJ5QrwZ6W+lztH4+DjhcJhYLIbX62VoaAgoyvez2ewFj5rYDJGlJWaMrmInbl13o/j7H/1JCk9xuncsFuPEiRMEg0GqqqpoaWnBYrHIBpZnF44ajYaamho8Hg+hUEg+pqTO58zMDE6n87xNL1d8PrJzIUx+H3/993+NOegDkOkAutlp0oEgrHbt/tLRWeug3O/hTe9+1eqUoIHbvnfXGc7Ou15F5dwsteYnr9DZUkfnzW9+M9dddx2f+tSn+OQnP1lyXz6f57rrrmNycpKPfvSjF2Qjz4V4PM6ePXt4xzvewWtf+9qL/nrPdFSXWWAp/pjVtsOyPbg6X9hsNg4dOkQgEJC5FtXV1TidTrkAuFCIr1oxbzYOk07q8Xh8HdFSEARsNttFHX0sLS2h0+lQq9XE43Gs5gqySYG7b1rPKcnE4Y/fKv583Jrj8x+r2NRp3263Mz8/z4kTJzAYDNjtdhwOBwqFgsXFRZaWlmhvb6csFqPwj/+I2u8n5XLRe+ONTOUOkxBLj+dUSonH89j8i29/+zhG446S29LpNGNjYyUyepVKJXfQwuEwhUIBo9GIy+XCbrefcwwi8UAMBgNutxuv10t/f798v3QMBYNB1Go1yWQSs9l8UTs7oigSTAukztXJEgSSosBsLEu9+cL5zki8tvN5f6IoMjQ0hEajobu7Wy7+XS6XrKCamJigra2t5O9aWlrIZDKcPn0avV4vy8tTqRQOh+NxjXdnRXj4W3fy13//1xvQAYrk219+/Xbe7nJtrbPwDIM2FCpKyFffu7Sm/Pibd/Cmd70Km2+at7z3dSj+9OCTZsi4pULnH//xH/nNb37Dpz/9aX70ox/JJ9Q3vOENHD9+HI/Hw4tf/GL+3//7fxd0YzfCy172Ml72spc99gO3AUBDmQ7H3DCvfddrsPmmibgbSjg6b3rXq/jVd+6grnvPU72pzyhotdonxRxQOvlL3keb3b+ZkimTyTwpfklSl6Ktykb/XPoxH3/33QHM5o1PeoFAQJYDx2Ix0uk0oVCIiYkJysvLmZubo7y8HIfDgahWE7fZEASB3ptuIuVw8ItvFvfTcy6Z4+tTr+Gjyc9wV/QFPPxwBXfffTe1tc0cPFhDKnVmGVKp8vzylw9jNqdLZNbZbFZOSW9tbcVut5PL5fB4PPh8PhQKBTU1NahUKiKRCAMDA9TU1LBjx45Nix2z2YzZbMbj8dDd3Y1Go2FychJBEFCr1TKhXKlUotfrGR4eZnZ2dsNsrwuJnPL8rrjj2QvQ0VnluMwUCkQiRTNOk8mEy+WiOpdDsFg2HPssLy/LF7tnfx8kAv709DTNzc0l9ysUCnbt2sXy8rJsGGiz2aiursZisTwufs5MLEu4pv7cdIAq1wUvCJ+2MJvROWtII3D7139xhpNT7eJX3/4Vb3nv69BUVz2p+WFbKnTUajW/+93v+NSnPsXXv/51+cD8xS9+gcVi4aMf/Sif+tSn/qLC3/5SoPD5uPq9r0PjO0e1/Z7XPqnV9jbOH+Xl5QiCgN/v35BfoFKpSKfTG3aSUqkUi4uLNDc3X7Tts1qteL1ecrlckXNSyNMmxvjUn6fIZeH6l1WQS505L6h1It/+ZR/79m48jolEIoyMjFBTU0NTU5OsJoNi0RYMBqmtraWxsRGFQkEol2PkC19gp9NJICUwpa2m8kV6/mZ3lD0vVfJQ8BbeJcR5+dQSbrcRvV7PfffFSaVKT7q5HMzMVLNr15JsKAhFv51MJsOBAwfkTkwul2NpaQmDwUAikaC6uhqz2UxjYyPBYJDh4WEsFss5zf527NhBb28vJ06cwO1209HRgcfjkYuc5uZm3G43giAQjUYZGBhgcHCQvXv3XvDzrGTKaFKfX//BqH6Cr7+8TPr5z0cXDCJ885u0dnefyU/705+wX3cdapcLYQOOSzQaPSefxm63MzU1RTweX/cYQRAoKyt7wvEdWUVxGX0s8u0FKQifCVjNENRGo7zDVVRXRTN5rFo1td3dxbXlmeKMrNFo+NznPsdnP/tZRkZGWFxcxGKx0N7e/rR22E2n07LJIXBRPU6eljCb0VRXkQHu/OYdRCuKqolotYs7v/dr3vTuVz/p1fazHaIoEg6HCQQCpFIp1Gq1zH05+7u0ll+g0WjkUM18Po/f7ycejyMIAoODg+zcuVMueGKxGENDQ6jV6osqTbbb7eh0OsbHx6moqGB2dpZDO3eSGpnhjxN15FKlJnTZFKiXajeV8UomflJHpL6+ntraWhKJBPF4nKGhISwWi9zJymaz5E0mHk4pGNG7AIGG7hx05wBYrKlnUYTntsS5vNVFJLKX666TODJJ5ua0JBLF5/r2t5u44ooUSmVUJiRLPJC12xsKhcjlcuzfv5+enh6CwSDm1e9PdXU18/Pz+Hy+cxY6ZrOZvXv34vF4GBsbk2/XaDR0dXWVdJXMZjM7duygv7+flZWVDflYW0Umk2FwcLDIeVKp0CgqyAjqDTg6gChi1iioNT0xrkUyFIJgEL3fT+cHPoBw//3gclGTy5H7yEdQzc6SUyhQbWB5IRG4JYuFsyF1Fi/mmK/CZIDUY5Nvn3BB+EzCan6YAtZLyJ+CC+gtffpNTU28733FD1QQBNra2rjsssvYvXv307rIAbj++uuxWq3yP+lK7VmD1Wpb86cHeesLO3lji4VX1pt5Y4uFt76wE82fHnzWqAOeDigUCgwODjIwMEAmk8FqtaJQKBgdHeXEiRMlRbmElpYWHA4HIyMjPPLII/T09HDkyBEmJiZwu93s2bOHRCLBo48+yrFjx3j00Uc5fvw4+XyePXv2PO5k8ccDhULB7t27yWQycjDl6dOncRTihP9Q7E4cumKJr/3kFJc/p8hx6enZ+DtYKBRYXFxcF82gUCgwmUxUVVVhNBoJh8PyfVqtFhEYKpjJJBNkkvGz/hVvOxZTUhBFlpdzDA0VyeJTUzoks1+FQqS318wtt1Ty7W/X4fMtyaZ55jUXAbFYjLm5OQwGAzqdDpPJtO4zczgcxGKxxyQsm0wmdu/ezeWXXy4LOXbu3LmhQ3F5eTlqtXpD48atolAocOrUKZLJJJ2dnTzn8su5onJ11HI24VgUQRB4oduE4gl2lHyCwMCttyI2NSFMTsKVV8LDD8OVV6KanibtdjP8ta9tuECWl5fLNg4bIRgMotFoNnV5vhDoqqt8TPJt9YL/CReE29g6tnTGW1hYuKBKkicTH//4x7n22mvl31dWVp6dxc5qtb1uZrw9rnpS4fF4CIfDuN1ujEajHHuQSCTo6+tjaGiI7u7ukr9RKBR0dHRQW1vL3Nwc2WwWq9UqZ/YAHD58mPn5eZaXlxEEgcbGRux2+5MiTTaZTBw8eJBAIMDc3BzpdJp8Ps9lly3Q3Bzj//v/YjgcFbzjtVZ+8Quor994oZTUMOcqzFQqVYkpY3l5OVGVkX9+bss5t/H6k/PMxrLo9Tm++91j3HzzYR55RKBQKG5LoSAgCHD4sMgHP3gcg6GYxaVSqUgkEqysrDA2Nib73wAcOXIEURRLUt2Lz1Xcvs1GTGuT1yVejtQx2uzzkgJFL6R788LCArFYjH379snn9wO1FRgMCf7gjZNY431p1ih5odvIzrInzhGKxWIYdu4sdnKuvBImJ+HyywHI1tXxyFe+w4LFTmF2ng5nOao1F9MGg4GKigomJibQ6XQoFAr8fr8s2c9ms7jd7ot63JsiEd76D68/J/n2Te9+9TYd4CnElgqdrq4uRkdHL/S2PCnQarXb/j7beFogm80yOzuLKIp4vV75dpPJRFtbG62trQwODhKNRku6CBIkEutGkJySL8aYqlAosLKyQjabRa/Xy1fL2WyWTCaDWq1Go9FQX18v84jy+TyHD2cRBIFIJEIikSAQ8PPqVzs2VaYplUoMBgPhcHjD9yE5J6819FMoFAi681MMxrMiNr2eqqo0t9++SGurnVVRGwAGA9x+e5iRkbRceFRVVREIBPB6vXIHJpVKMT4+LivNzu5qh0KhkvGaBOnzl8iwSqWSyspK6urqZOXawsLChgq7aDQq52FdKMzPz2M2m9ddxHbYDbSV6zk6Ok0wssK+XW3UmtRPuJMjQaFQkMvloLYWbrtNLnIAfvHJW5l2dQMwtgD3zs/zIreJ3ZVnOjRtbW309/fT19cnP58gCOTzeRQKBV6vF4vFcvGcnM1mdM5qMoLAL79+O9GqM+TbX3/v17xxmw7wlGNLhc5HP/pRXve613Hfffdx1VVXXehtelyIxWKMj4/Lv09NTdHb20t5eTl1dXVP4ZZtYxvnxtDQEKIoUlNTQ0NDA2q1mkgkwuTkJL29vXSvkjKXlpYu6IL2RBAIBJiamiKTyci3GQwG1Go1y2vy0ex2Ow0NDfJ2K5VKFhcXGRkZkQ3dstksU1NTVFZWsnPnzg3H3k6nk/HxcRYWFko6JYVCgfHxcQRBWMd9qbSY+NRDnsd8L0a1gNlkxmQycffd88TjpYToeBzuvnuBPXtM8vuora2VfYjq6uqw2+3y+4jH43L8RmNjI4IgMDMzw9LSErt27Sp57kwmQ09PD5lMhqqqKiwWixzsOT8/z549e6ipqZFjGNYWO7lcjrGxMbRa7QX11MnlcpteBCoEgVqjikwwcsGVQ3a7nbGxMVJjY+iuvrrkvpd+8p/kDgkUfcD+15tEpVLRVl7kfqhUKhobG+nt7cVgMKDVatHr9dTU1GA0GhkeHmZoaAiz2XxxIh0kOkA0yttdRXVVPCtiVAvUdtufEvLtNkqxpUInEonw4he/mBe/+MW8+tWv5uDBg1RVVW3Ymn3rW9/6hDfyXDh+/HhJsSWNpd72trfx/e9//6K+9l8ElpdJhkL4FQqSyeIJpLKyEpvNhuDzbX9BLxLWBmM6nU55gbHb7VgsFo4fP87s7OxTuYnr4PV6GR8fp7KyErfbjU6nY25ujomJCeDMwh+Px/F6vfT09LBnzx6sViuRSITBwUEqKipobm5Gr9eTz+cJhUKMjY0hiuK6YgCK+2ZpaYmBgQHsdrtcWASDQVKpFO3t7etkxV11lTwUjZBRqCix85UgihiVUGtSIwgCO3bs4MYbi0XaS1+a5POfz/Lxj6v53e/03Huvkde/3nnWn4vodDoGBwfXPbVUAJ46dYpUKkU6naahoQGHw1HyuPHxcZnAvLajJXm/DA0NsW/fPlZWVujr68Nut1NWVkY6nWZubg5RFOnq6nrMkUwikSCbzaLRaB5zkTcYDMzPz1MoFDZ8XsmU8UKjqqqK4LFj8Ja3gM9H2u3mV5/+Ki/5xAdkXxq52BGKYWm/90bZYdPKXSWfz4der+fgwYPr1qGdO3eyuLiI3++/eIrDbTrA0xqCuIUhr9QaPPtP1x5g0sz5YiftPlFIqoXl5eVnLO9oqxCXlkg///mIc3P033IL2pYW0uk0iUSCimSSXe9/P0Jl5TY5+SJgYmKCQCCAKIq4XK51BmXT09N4PB5EUSzhTDxVyOVyPPzww3LgpISTJ0+Sz+cpFApyLAUgp43n83kOHDgg/7x37951i6jkk3N2YKeEQqFAMBiUQzsVCgV2u53a2tpN98uxmXnulfz81i58oggCvKbRUsIv+f3vE5w4scAll0xKaylHjzaxf38FL3rRmcV9eXmZnp4e2tra5PF9WVkZZrOZWCwmE6PVajUVFRU4nc513bhMJsORI0doamrakB8YiUTo6+uTi8RgMIjf7yeZTMrjLZfLdc7CJRKJMDU1VaIqLSsro6mpadN9FovFOH78OE1NTeu64cvLy/T29soydwmFQkFWPG1Z5u71UrjiChRTUySdTh68+Rv0NB/GHPTJvjQRdwM//tadRKvOFJ1vbLHIRYV0bG5m9Hf69GlSqRT79u3b2jZu42mJ812/t9TR+d73vrflDdvG0wehiQksc3Po/X4OfuQjCPffj+h2szwwgPalL0WQogK2k8wvOLLZLAaDAYvFgtfrxWazlYwnVCoVoihiMpm2NLZKJpP4/X7Z48pqteJyubZ8RS5d6a/17onFYqysrLBr1y5yuRwjIyOk02m0Wi1KpZKGhgZOnTolOxdvlgReVVXFxMQEoVBowwBNhUKB0+nE6XTKF1ePtagerHOg0axwfzBJUjwzEjOqBF5cZ15Hon3Riwy86EV1ZLM1ZDIZNBoNV121XiUjRWyMj4+j0+lk12OTyUR9fT3hcJjBwUHMZjM7d+7ccNukKIvN/FvKyspQKBTEYjFsNpv83s8Xi4uL9Pf3Yzab2bVrlxz6Ojs7K49EN1oUTCYTdXV1TE5OEo1GZXuDcDiM3+8/4wW0vMzS7Cwzq6o4KGaNOZ1O3IBitbtx3jCbUVRVIQoC0Z/9jOiqcaNM6H33q0nYKsgYSpVTzxpfmm08YWyp0Hnb2952obdjG08yRFHEk8tR9oMfsPPv/16WdQq33UbZ1VeD30/S6aRw110Yt1uvQHGfRSIR0uk0arUam822ZTsFjUbDwsICu3fvJh6P09fXh81mw2w2k0qlZLlsR0fH475Snp+f5/Tp0yiVSpnXEgqF8Pl8tLW1bYmgnE6n0Wg0JRyOZLKYH1VWVkZqVZedSCQQRRG1Wi0v5FJsxdmRFBIUCgUajaak+5vL5eSCwGw2y6/7ePbFnmoLnVXmUs7EY5Bo1Wr1OQOLFQoFSqWSbDbH8eMm9uyZRa1WyfwWydMmGo2uGwEtLCwwPT0tK7V6enpK+FkS8vk8oijKqqpEIiE//2b7UIIoioyOjlJWVkZnZ6f8+kajkYqKCnp7exkbG2P//v0b/n1jYyN6vZ6ZmRk5DV6lUuF2u6mvr0cZi5F5wQvQBgKI3/gGrXv3olKpiqOho0epuvZaNG73huZ+m2KV4yJEo1S63ZiPnZLvila7+PG37iRjMJE2nynORBF+e3sA5RUZnM4abDabXCiffYzkcjlZ2biNZycunqHGNp7WSCaTJJNJWvbuhQ1knWJTE6duuIFqvZ7t1KviIjU2NlbikSIldLtcrsd+glUu1KwI09E0aZTkRS0+f4BOm415vR5/PM7c3BwqlQqFQkFlZeXj7sAkk0lOnz5NRUUFbW1tciFWKBQYHR1leHgYk8n0uH1FNBqNrKqSuhrSc6fTaXlks1b5Ul5eDhSVjhKpeiMFUTqdJplMotfrKRQK8lhvrSzb4XDQ2tp6ziJkIygE4bzIs4VCgVAoRCAQkLlqDocDl8slv994PE5PTw/5fJ5HHy3nYx/r4tZbx+nsLPJDcrkcoVCIiooKFhYWSKVS8ufn8/kYGxujrKyM9vZ2mUwcDAZZWlpi72rBAMgcHIVCwYkTJ0qyycrLy2lubt5wxAfFrLFIJEJdXZ1ciK5FRUUFU1NTxGKxDY8BidxdXV1NKpWS+UhSwZQJh8kHAuj9fnb8/d/Tf8st6FpbqQV2fOQjKL1esgoF6sfbBV7TBeqosTM4l5FT79eOqwAQRTwPK/nmPzYgfOk0+/adoKamhlQqxdjYGC0tLfL25vP5EtL/Np6d2FKhMzMzc96P3VY+PT0hLSIqlWpDWadw223k1zzu2YxwOCyTYXft2iX73MzOzsoutucqdsSlJVJXXUU+NM/93/wVi87V8YzJwdzgFG95z+uoqKnGdtddLObzeDweVCrVlnKz/H4/SqWypMiBYuGxY8cOFhcX8fl8m45VNoPD4WBsbIzZ2VmZ0FlWVoZarWZycpLFxUUUCgVNTU0YDAai0SjT09NAsZtQXV2N3++nurq6hFsiiiJTU1MIgkBlZSWDg4MsLi5SX18vCxwWFhbweDz09PSwd+/ex13sPBYKhQL9/f1EIhEsFgtGo5FMJsPMzAx+v5/u7m4MBoPcJcvlcjz4YFGq/NvfGtm9W5SLirXeNlJnIZPJMD4+jtPppLW1FUEQyGQyTExMUFtbi8/nY2ZmhsbGRhYWFpiYmMBqtTIyMkJZWRm7d+9Gr9ezsrLC7OwsJ0+eZN++fRsWO6lUipe//OXnfL/33XcfqVTqnMWuIAgbcoDGkklWbrqJvddcg97vZ++11zLxyU+i+7d/Q+n3k6mtZeCWW9jrcm1EAz8vuJw17A5PcDKvXuWSr+dYhY8Wi6LBwXZe+1oDHo+Hmpoa/H4/8/PzVFRUUCgUWFhYkInuj9UN28ZfLrZU6DQ0NJxXC1kQhKI/wjaedtDr9fL83bqyAmfJOgtvfjPCDTdgam19irbw6QFRFJmYmMBms7F79275uDcajbS1tSEIAlNTU1RXV286xvKPjGANzWPy+3j9e17Pj795J9FqF+agj9f//esx+GaJFQqcvvtu8gYDiro6NBoNfX196HQ6ampqcKTTmwYbSshkMoRCIdRqNVNTUzgcjpKAQqlLtDZ1O5VKkc/n0Wq15zTmU6vV1NfX4/F4KBQKuN1utFotDodDllu3t7fjcDjIZrOsrKxQKBRQqVRMTU3JypeTJ0/idrtlBZFk7rZz505WVlYIh8Ps3r1bHrmtrKywtLQkj4oSiYfRaNTyeKyyshKn0yl3XbYCj8dDJBLBbrcTDodRKpVyMZXNZunr66OhoYkf/tBKMqkFRO6/v7h9f/5zFbt3G1eJwiu85z0wNxdAr9fLC2swGJRNG6XPwu12k06nmZ2dRaFQMDs7SygUIpVKUV5ezsrKCg6Ho2R0aTQacTgcnDx5kvHxcZn4vRbn63q9FXfsVCrF/Pw8apcLzcMPw/Ofj3pykrbV8Oak08ncj37Eyio5fatjXYVCwQs7mzFNBTm6rCAtqCgU4OjPdeRjAq1lWn7/6+Jz3367QFNTA4GAFqMxy7/+60GCQb9sdeByuXA6ndtFzrMcWyp03vrWt25Y6CwvL9PX18fU1BTPe97zLnqS8za2DslQbv7kSRo+/GEUHg80NcFttyFefTWKyUn2XnNN8YT2LEYsFiORSNDS0rLhMV9bW0sgEGBxcXGdhBiKrfPJbJahb/6K17/n9di8RZdUOTF+NVz1zpu+zxu/8CHEYJDeL38ZXXs7Op2OaDTKxP33Y/3Qh87JfQgEAoyOjiKKIiqVilAoJJvaVVZWcfy4kVe84gypeXFxEY/HI6typI5KY2PjhouCKIo4nU4EQWB2dlYO1lyL06dPo9VqyWQyiKJIXV0dWq2WsbExCoUCe/fuZWpqiunpaaampoCi6aFU2AwODqJUKtHpdMTjcRYXFxkcHESv1zM2Vs8111Ryww0THDq0KG/z9PQ0gUCAPXv2nHPMl8/nSaVSKJVKtFqt/FlKGWFGo5HFxUVaWlqoqalBqVSSTqflHL/e3jG+973DRKNqQEShKHZt4nGB//gPC6JowWwu53WvO02hUKC2tlZ+jUQigdFoLOlECYIgv9bk5GTxgsNqpa2tjXQ6zeLi4oZ8E5VKRW1tLSMjI6RSqXWfVXl5Of/3f/8nj/rO/gyHhobI5XJbysfy+/2yc7Oivn5dF3j6M59hWaOBZPIJB40qFAoua3ZySaHATDRD/0iQL3ytjOiKCkEAifoUi8G//RuIYg1mc5aPfUxY9763sY0tFTrn8qcRRZEvfelLfPGLX+Q73/nOVrdrG08CGtVqaj/4QRQ+H5naWiL/8z8k7HYWv/QlOt73PvR+Pzz/+fDAA89aLwjJF2WzRdRgMMijiI2wsrLCoqhl0dnIj795pyyXlRKOI+4GfvSNOxgbMPH6YAij38+hj34UxQMPFEeKs7PkX/vac3IfwuGwnPANRT5Re3s7Q0NDxGIx7r1Xw8c+VssXv9jP4cNLGI1GTp06hdVqpaOjA61Wy/LyMl6vV+aLSAtoOp1mZmaGYDAoO81WVlZiNptlZZDP5+PSSy9lfn5eJi1XVlai1WrlkU4ikaC8vJy2tjZaVm0MpKJGQjqd5oorrjjn5/HAA35e8xq9LM0XRVHO09q/f/+6BTYajTI8MoI/KZJVqFAXclRrRZoaG3E4HCSTSXK5HLlcjqamJtxuN/l8XubplJWVsbi4iNFY4FvfOs4NN+yhp0dPoSBxQARAZM+eOP/8z/3kckWi+lo+iEqlkou/s7fPaDRis9kIh8Ps2LEDpVLJzMyM7Aq9ESTF1EaFjjS2lHhOtbW18ucwPT1NPB6XO5GPF9FoFJPJRDQaZWVwEMtZXeDmT32K4//xH9jb2y9Y5IJSoaDRqiNjTfPjH53m+uu7OHIEJN56Pl90Dzh4MMN1153AZDpwQV53G39ZuOBkZEEQuO6667jrrrv48Ic/zO23336hX2IbFwgqmw2l201WqWTglltYicVQJBJUtrUh/vGP8PKXQ2Xls9q6XFL7xGKxDTsd8XgcURQ3dZQtFApkFcWvWbTaxf9+5itykQPwv5/5CicmG/j+R62YP/IjPvSjN6GZmkK84goi//mfGD/wAbR+P/EaJ303fYXnOhycvRXT09NYrVZ27Nghu+ueOnUKs9lMTU0NX/xi8S8eeqiGgwfDRKNRKisraW9vlxc8q9VKVVUVJ06cYGpqivb2dpLJJD09PbLXj8lkIpFI4Pf7WVhYKMngUigUG6papAJw7RhDpVJtODo5n/HTAw84+NnPalhaqiCXW+ADH9AwPV0k1y4vL5dItufm5nhozIdH7yRjOvPcE4UMvpFZLslk5McLgkBFRQWjo6PMzc3JCjBp/4iiSFVVmv/5n3m6utykUmfej15f4JZb+hHFDKK4frTvcDjwer2Ew+ENc7ACgQB2u13eRyqVinw+X0L8XgtJ4bYZV8ntdhdVlR4PXq8XlaqoClMqlezYsaNEdZfNZgmFQiVmoefqjKlUKmyxGJo3vxn8/mIQ5223Ib7lLainpui+5hqy//d/m/79WqTTaSKRCIVCQbZR2KwAs1gsmEwj3H13EpdLvy6q41vfGieVUlzUwNptPHNx0Y6KAwcO8O1vf/tiPf02LgSsVoTf/Q51NMo+t5tCoSAHCwLFTs6z3BnZaDRiMpmYmZmhvLy85EpVWkzUarWsMDobBoMBdaHIUzMHfbzi395Xcv8r/u19fK3jOACf++Lz+Jx0h8cDf/3XZx4Y8HN942EGBiO8uM7MrooiEVXKe5KKFoPBgNFo5oc/NJNKaTEajTzwQBkAf/hDGU5nK5lMmp07q2lrE0q89LRaLW63m6mpKVpaWhgdHUWhULB3796SQs7lctHb28vIyAidnZ0IgoDf76e+vh5RFGWujZSJpdVqS3xbzg6xlFBVVcXdd99NZ2cnfn+UF76wRh4VCYKIKCpIpZSrowobZrOJD384hck0L3v6SIVLKpXioTEfo4baUsNAIKNQF2+fmuWvDlagVCrl5O58Po/b7cZqtbK0tFQivLBYLPz+98ukUvUlz5dMKunr09LVVSyczlb3WCwWbDYbQ0ND7Ny5k4qKChSrTuTj4+MkEokSE0aJ+O3z+WhsbJQ5T5KvkjSS3KwgEQSB2tpa9Hq9zMcqKyujsrKypOD0+XxMTEzIyqpMJoPH45FNIc/uypSXl+N95BEu+chHUKzaT4x8+csUdDoyN9zAng9+EL3fj/6VrzxnFzifzzM+Pk4wGCwxnTWZTLS3t29Isq6srGRycpJf/tJLPF46morH4cEHU7zmNa5zdqpEUZTNF2OxmFzcut3uC2rImUgk5DBbjUZDVVXVpiq5bTw5uGiFzsTExDYR+ZmANbLOde3mZ+m4ai0kLkVfXx+9vb3U19djNpuJRqPMzs6ytLRE+zla9Xq9nnqzhjnflMzRCbsaufaq31D769+i90YY8J0/kTaNkv87HURnB0etQ+bKLCwsYDKZ0M7PszgV4gc/6GZ5WclaPkkqpeTrX3ciigJlZXne8571zTqr1SoXK5FIhLa2tpIiJ5PJEA6HsVgsBAIBUqkULpcLj8cDFMdoKysrqNVFwnAul0OhUBCJRDAYDMzOzjI3N0cul0OtVlNdXU1tbS0ajQa73U51dTVTU1OUlZXx7W8Pc9NNh3jkEQFRlDg1xbrl0KEsH/rQccrK9pDJVJRIsAE8nmk8+s38gorjJo++muBcCLvdTigUIpPJcODAAbmAkKwEJBf4lpYWbr45AcAVV4R573sn+a//auChhxwcOVLBX/1VGfX19fKxIIoi0WiURCIhd1FOnz6NSqVCrVbLXZRdu3aVcGbUajW1tbVMT0+zuLhIPB4nny/Q11fGnj1LCALrxk+JRIJoNIogCBQKBaampkqsEBYXF2WeFSBHbzidThoaGmQfo2AwKGeIna3Mq66uxms2kzSbMTQ2krrjDvRabdH3p6mJ3ptu4pKPfhTFObrAEk9ocXGRpqYmqqurZR8eKeNt37596xRfSqWSXbt28ZWvFD2IXvSiGP/6r8t88pNG7r+/jN7eOt7//s1zv6TXDYVCskRfer89PT20t7c/4dBPSbggddGkQNqZmRlqampobW29qCnq29gcF7TQKRQK+Hw+vv/973PnnXfyghe84EI+/Ta28ZSgrKyMPXv2MD4+Tn9//7r7pSJjs6u2NpOR1ne/AqPfS8RVz/dvvpOfv6Od5MouBAooxKKEXyGsUBAFQMBGmNN0YCZOxFnHz/7rf8gA2liUN7z/bzBGFhj40hflYjQcDrMyOMj+667jsNnMn+66h/d8pJYjR1jHJ9m1a5n/+q8FzOb1uT/S4ij9L/neFAoFJicn8fl8JVyT/v5+Ojo6yOVyMsFY6g6Ioojb7SYWi9Hf3y/HBEhhi7FYTJYDd3d3o9Pp6OzsZHR0lFAoRGUlfPrTf+KVr3xOyajIYBD52teGyeWU6PX6EkPCZDJJJpNhZH6FjOkcgZeCQEbQMBtb5mBzM6FQiEKhwMmTJ9FqtRQKhRLJuMTbeec7K7n00hUuvzxAMinymc8M0tfXzr59LpqazmzjysoKIyMj8rZBcbF2Op2y67WkotpIndTQ0MD8/LxsLnj8eAUf+chumWc1MzNDRUUFuVyO0dFR2aFYglarpbu7G6vVKlshSGR1p9OJx+OhvLxclrtL2+dyuWQvo/r6+pJxrVqtpuPSSzn1xS9CNIpJEFDm8ywuLpLL5dj53Oei+NOfztkFXllZYWFhgY6OjpLCQsp4e/TRR5mdnS3pcEkoKyvjne/Uc+BAkMOHpygU8nzpS0aOHm2is9N+zm5OIBAgFAqxa9euEtFAbW0tw8PDDA8PU1ZW9oTUezMzM3i9Xpqbm3E6nXKnMBAIMDY2hkqlunhZW9s4J7ZU6EhZV5tBFEVsNhtf+tKXtrxh29jG0wllZWXs3LmT3t5eFAoFDocDu91OIpHA5/Nx8uRJuru7N4xr0DkcFGpdJBQCP//6z8k6a/jAT5b4yT+bmelTkV/9GhZEMwIil/IwX6/+ML+//me84t/eh9vr4e0feCM//uYdIAgYImHKvNPs//BH0PzpQcbTaRb7+th33XWoZ2fJO53YlD7uvddFeTkkk2e+qwYDfPnLvdjt60dtoiji8/kwm83yAic58o6NjREMBmloaKCmpoZYLMapU6dQKpX09/fL0Q0VFRXk83msViv19fUYDAby+Tx//vOfEUWRQ4cOlSwmbrebnp4exsbG6OzsRKVS0dHRQVNTE6dPn+ahh4SSIgeKSqeHHsryhjfUE4lEZAff06dPA6u2FqrzG0VkFeoSIrlETJYg5fWp1WoSiQTPfa6C5z7XQi7XRl9fHwaDnn/6p8qS82EsFqO3txej0UhXVxdWq5VMJoPP58Pr9VJXV/eYC97S0hLJZJK2tjYKhQJf+1rx/QwP7+J970tx7NgxuTsmiiJtbW3Y7XZOnjyJKIqydN1qtcpWCABTU1NYLBYSiQTNzc0bnsclJdjCwsI63pXVauXAC14gKw1zuRw1NTU4nc7zSgafm5tDp9NtqFCUSNw+n6+kAFuL5z9fy/OfXw2c6dadT3yVz+fDbreve12FQkFrayvz8/MEg8Et+77l83lmZ2dxuVwl+WUKhQKXy0Umk2F2dpb6+vptHtFTgC3t8SuuuGLDg1ChUGCz2Th48CBvf/vbn3ArcBvbeDphbGwMnU5Hd3e3TAS12+3U1NTQ29vL6OjoOmv95eXlYiDj9dejTqV4boOZ0YUpylpqeOs9Wg61qEqJlcT535q38OPv3FGS9SOnOH/rzjO3zXjgqqto/N73qP3gB1H7fKRcLvpuuolsNstvbxshmWwv2Z5EQmBoyIxaXTQOlPx/UqkUk5OTLC8v09nZidVqRaVS4ff7cblcBAIBWlpaUKvV9Pb2kkgURziSZHtmZgaFQrFq0AZ9fWXs23cCt9tFRUUFoihSKBTWEWh1Oh319fWMjo6WqIikgND/+q9ip+I5z5nnve+d5KtfbeKhhxwcP+7k8st9sjxeCrqcn58vjg4K5zc2r7FZ5bgNaXwkebBAsfgrRj5kWVpakom7fr+fXC7Hnj171p0LJycnUalUaDQafD4f0WiUmpoaWlpaUKlUTE9P43K5NiWwA/j9Qe66q4E//7lomnjPPcXbb79dQVOTgVCoHaUyyotetMzBg/vR6/WEw2EWFxfZvXs3hUKB06dP43K5ZP5YXV0dwWBQ7v5s9voSWXyzQGa1Wk1dXd2WioJsNoter9/0QlkqjDdSqG0VhUKBeDy+qamnWq3GarXK3bOtYHl5mVwut2kmmdPplEeR2+vik48tFTr333//Bd6MbWzj6YFCoUA4HGZubo5MJoNWq6W6uhqtVisHWJ69WKtUKhobG+nv7ycajWI2m2XH35mZGXQ6HeUu16rCZQ6rKKJf8jMfqCEeLz2ZxzHxvX/4IZnq4kl5o2DDtNnCj795B+/+h9egnpxE9bznoQKytbX03XgjqYoKyOe5776i8+0rX5nnU59KcN11cO+9ZgYGmnjRi4KMjY0xOTmJWq2WC5b29nbs9uLIx+124/F4ZC6JxHOQHHWrqqqwWCxMTk6SzWYRBIG2tjaOHavgmmtUfPe7AQqFEZaWloBi0XDqVD/Hjxt5/vOVOJ01aLVa+fXOVrYplUr+3/9zcPnlSQ4fnmd+PslnPjPI/ffXUFWVkouchoYG2bMrFAphMBhwGI1MpDJkBPU6MvLqxqAlT7O9jKNj/UVvGIWCrq4uMpmM3MmanJwkGAzK23f69Gm5o1dXV7duXBmJRORCQpLjT09PMz09TXt7O263m5mZGUKh0IbJ5RKWlrJ861tulpeFTXxjKjGbbdx0U8umzwHFLpdU6EjcI4kEvrS0tKE7ciwWk0NnLzQkK4Ozc8AkRKNR1Gr1ug7ZwsIChUJBzux6PGaEaz2TNkM+n39CYyvpuTdTwkm3bzvNPzXYcgREWVnZOZnq0WhUzlzZxjaeCcjlcvT397O8vIzZbMZgMBCPx+nv75cXhHMlTkORFGo2m5mfn2dmZoampqYS87hMJiN3RL7znTnAyV/9VZZ//udF/vkjCh54yMHA5A52F7JkFMWT47pgQ1GE2lqUP7wNnvMceRvUP/0pnd3dPProo7S0tPDiFydpajrNC14QYmkJPvUpDa961U727i2nra1InJ2fnyeXy6HX69epcurr68lmszLheWJiQvbOqaqqktPIpU6CKIo4HA7uuKP4HH/+cxVXXZWWicrF20y8//1NfPGL/Rw6NE1HR4e8oG608F1+OVx+uR7oIJttJRgMUl5efK3lZUEOxVwLURRpbW1h5NGBorpKFEuLnVWlz0vqLSwvLZHL5WhpaWF8fJzR0VHq6+spFArEYjFUKhWFQgGr1Up3d7dcvGy0rblcjsHBQaDoEl1VVQUUuxijo6Oy149kqrgWyWRSdqguBsaq+OEPT3P99Z0cOSKs843ZuzfBxz7Wx9/8zbrNKMFaQrLEFzIYDFRUVDA7O4vD4Sjp7EhcLIkcfqFRXV2N1+vF7/evG4slk0mCwaBsTJnL5RgaGiIcDstdplQqhVqtlkd15wNBELDb7czNzeF2u9d1iuLxONFo9AmFfkoFbyQSkT/3tZCK32311VODLRU6jY2NfPKTn+QTn/jEpo+55ZZb+MQnPnHOKnob23g6YWxsjFgsxp49e2QSriiKhMNheQHLZDIbXrWd7RczOzuLzWZbV+hrNBp2797No48+ypVXrlBfv8QLXhAik4Fbvmrn+HEzLS3lJBRj9Ip2OetHDjZcXaSfE59F8da3lm7E1Vez8tOfyttx+HCefftyqFSVMqfo8suLC3ShUECv15/zQkQQBFkpMjs7CxQXKqfTKRd+oiiyuLjEz35WRjyu4vbbvfzsZ3ZA4Kc/zZHLxYAKyso0vPGNS5w82QTA0NAu/uqvhjl9+jSVlZWoVKrHdOuV1Ei1tbWk02mOHDmybrGz2Wz4fD5SqRR1ugIW9TIDOTMpzhRwWnK8pN5KFUkWIxGgyEtRKBSMjY0RCATWvbbkf3MufkUwGJT5PdlstmS729vbOXr0KDMzM7LsGNYnmksO1eXl5czPj3D77RFaWsrP8o0R+c//PIFGI3DixAlZHSWKIj09PTLvpK+vj1gsxrFjxzCZTLIvT3l5OSaTiZ6eHk6cOIHL5cJisZBKpfD5fMTjcXbv3n1RFEImkwmn08n4+DjJZJKamhpUKhXhcJjp6Wn5MxZFkdOnT7O8vCxHiygUChKJBBMTEwwMDLB3797zloW73W76+voYGxujqalJ/hwTiQSDg4Ob8obOFwaDgbKyMjweDzabraQ7lM1mmZqawmw2b8jh28bFx5YKnbXeB0/kMdvYxtMF6XSaubk5WlpaShK2Ja+N2tpaWVWxUSCmz+dDqVRis9nI5/NEo9FNgzMNBgMmk4nLL4err24hm61HrVaj0Wjo6io+plDYgW16noeXRNJrvqZmjYJ2Ty873/M28PkoNDYS+s//xH7NNagnJ7G++tXob76ZEZBjBxYWFpifn6ehoYFsNisvyGfLuzeD2+1mdnYWlUq1Tg2TTqdJJAS+9rW96/4ukYD//u/izxpNjkhkll/+Mg8o+eUvFTQ27mR21oBen+EDH3A9rnGE9FjJPE+C3W5Hr9czNDRENpulqVzB8xsrmY1mmQktsBjw0WwzEBmeJLSmGDl+/Lg8cjSbzXJMxMrKCul0momJCaanp6murqZuNYvsbITDYdlrSeI/SQuqQqGgqqoKr9e7aj5YRTAYlNU+u3btQqvVsrS0hNfrJRKJYLVa+cUvZojHS4nj8bjA2JiNF73IgNfrRaFQyETgzs5O+vr6OH36NGq1GqPRiEqlYn5+nkKhQGVlJQqFAp1Ox969e/F4PExPT8sjFZvNxp49ezbtXF4ItLa2otVq10WJVFRU0NraikajKTqKLy6uU0kZDAZ27drF8ePHmZ6eprOz87xe02azsWPHDtkQsqysjFwux/LyMlqtlq6uLnkfbLXA27FjBz09PRw/fhyn04nRaJQNNvP5fInB5jaeXFw0+rfX692uXrfxjIHEI9mo7QzFK/6ZmRkCgQA6nQ6XyyU7zvr9frxeLw0NDSiVynWuuhtBuk+j0Wy4aCoUCi5prOKgKDIbyxLPihjVArVLc/CBd6Hw+Ug6nfR+4Quky8vR/sd/0L2aKN31T/9E+ne/I1ddTTqdpqqqisXFRaampmSJs8FgkOMbfD6fPKJZu/1msxmXy4XdbsdmsxGJRBgcHMTtdqPRaFhaWsLj8WAwPHbXNpNRcttt9bKnTywm8olPKIAGzOYsn/nM4zsVqVQqysvL8fv9cjdG2q+dnZ2cPHlSXshGR4o8oXwqRa3FwsLCPDU1NfL7OHHiBOl0mmQyidvtpqWlRVZOSYqrXC6H0WgkGAwyPz9fEpMhQcoZq6+vp6enh5MnT9LY2CgHmEouwA0NDXL3qKqqqsQTx2KxyA7VWq2W3t7i8fic58zznvdM8LWvNfPQQw5GR9t4xztE5ufn6enpobGxUeaurL3IlIjVGo0Gk8lEKBSipqYGm82GTqeTIzkymYxMoA6Hw/T19cl/W1ZWhtvt3tQU8/FCEATq6+txu91y+KvRaCzZn6FQCI1Gs85JGorfDakrlM/nz7tAdjqdlJeXEwgEiMViqNVqWltbSaVS9PX1kclkEARB5l+dK919IxgMBvbv38/09DQzMzMyD6myspK6urqLwnnaxvnhvM8un/70p0t+34yQLMnsfvrTn3L48OEntHHb2MaTBWlx2OxqTrq9oqKihGQspX+73W7q64uOuUqlEpPJxPz8fIndvoRkMkk0Gt1UoVHyuoJAvXlNIVSwIFZVkcpk6L3xRtKrCo5sdTVDX/0q7f/wD2TKyhicmSG7sCCb3QGyc7IkbV5cXCQQCFAoFOTMKEnxYjKZyOVyDAwM4HQ6aW1t5dFHHy2Rc0PRLddqtXL33XdjMJTxkpfsIp0+02XRaPJ8+cs9fPe7yxw/rqRQEACj7Omzd2+Sf/3XASyWg4+5L85GfX09vb29DA4O0tzcjMFgoFAosLy8TD6fx2g0IggC8XicsrIyHA4HAwMD1NXV0dTUJD9PR0cHJ0+elNVUOp2O0dFReeHbs2cPfr+fdDrNgQMHSuTwa2E0GgkEAkSjUXK5PCdOaIjHB2V6kCAIssosEAiQz+fXBXeKokgsFkOj0fJ//5fhxS9Oc9llKV7+8gLQwKteZeDXv4b6ehWFQprq6mrm5uYYGRlhZGREfh6pYJc6OZlMhqWlJVQqlTxWlbA2ksPj8eDxeDCbzTL3aX5+nlOnTtHY2Cgf4xcCUgd0I0hk8M0uFiRe0eMpdKCo5pOsEHK5nMyXq66uxmq1kk6nCQQCnDx5ks7Ozk2371zPv3PnTlpbW8nlcqhUqm2TwKcBzrvQ+fd//3f5Z0EQuP/++8+pvnI6ndxwww1PZNu2sY0nDdKsf2FhYcOujrS4t7a20tLSIquyJIv3s6/uXS4XIyMjcsdBOmHncjmGh4dRq9Vbk5larSz95CcMHztG2uGQfVoUCgXj4+MM/Nd/kVKryRsM7N27F6vVSjgcpr+/X3bqlXgkg4ODlJWVUVZWxuTkJGVlZXR2dhIKhRgZGaGtrQ1RFBkZGcFisciLqtPpxGazYTabyeVyjI+Po9frOX3aRDptAc5wbTIZ+Id/OPtNFAsvo1Hga187jV6/ucz63LvCyq5duxgZGeHRRx9Fq9WSy+XI5/M4HA7a2tpKFkGv1wuwTu1ksViwWq1cddVV53y9++67D61Wu6EcXhRFMpmMHKMyN7eXa66x8tWvTtLePoNeryeZTMreNclkEp1Oty7UtL+/n1gsRk9PNdde28YNN5zikkvGEMUdcrTE3/5tgfHxcR55pMglWpuRpVKpUCqVxGIxWVItHX8LCwt4PB4WFxc3LBCWl5fxeDw0NDRQX18vH7O1tbV4PB6mpqaw2WwXNC5hMxgMBkKhENlsdkNO3PLy8qaZaeeLqakpkskk+/btK+neuFwuBgYGOH36NJdeeumWChWFQvGEVFzbuLA476PkvvvuA4pf6Oc///n83d/9HW9729vWPU6pVMopxduV7DaeKTAYDNhsNiYnJ7FYLCXmZ/F4nOnp6RKFymNd2VZXVxONRhkdHcXv91NeXi4HKAJ0dXU9rivRtZhLpchUVlLpcJSMEwqFAonycrRaLflUUX5ttVplYqzVamV5eZlsNitnUe3cuVMm31ZVVaFUKqmpqZH9aA4cOEAoFMLn87F3714UCgV+v59AIIBSqSSXy6HRaNixYwff//7j+77H4/DoowJvetPG/ibng4qKCsxmM16vVy48JOJqOp0u8WyR7AI2Wjg3Cmw9GyqVCkEQ5H0ej8flv5M6XVVVVczNzfHjHxfJ6Q8+WMX+/QskEglsNlsJqTmbzcoFhyiK9Pf3k8lk2Lt3L9/8ZnGRHBxs55WvnGBkZASdTofNZpN5Jo2NjbLTciwWY3h4eF0Uht/vR6lUyt2YdDqN3+8nGAzicrnI5/PMzc3JLsxKpZKysrKSToogCDQ0NDA3N4fP53tSCh0pCsTj8dDS0lKyPfF4nEAggNPpPO81RhRFlpaWZCK4xWKR98HZIyqlUklLSwvHjh2TP9NtPLNx3oXO8573PPnnT37yk1x11VVcccUVF2WjtrGNpwJtbW309vZy7NgxHA6HLC+fn5/HYDBsaEu/GSTFkt1ux+/3EwqFZJdUp9N5XgvrZkin07L7+FpIC6bNZpN5CHBm7CZd/UoBmBaLRfYHgtL0cIfDwcjICIVCAYfDwejoKFAkXNbX17OwsEA+n0ev12O321EoFLzrXVBXN8zhw3ejVqvIZnM88EAl9fUC991n4Be/qOXSS+d53/se4VvfauOBB8oYGGikvLxsS/shv7jIzOAgs6tmhBK8Xi+aUIicXo92lR9RXV2NRqMhnU5v2CWQAkUBmpubmZiY4NJLL0WtVhOPx+nt7cVisZDNZuWO2NpF1ucLcMcdVVgstaRSDu69VwPE+fWvc5jN5eTzFqqqzHR2Fn1xKisrmZqakhfbhYVFbrvNgtlcyx//qOPXvy6+nzvvVNPauhO/38zvfhfnX/5FSzAYpLW1tcQAL5PJyEGVoihiMBjkkdv09DRQVMtKOWTBYBC73U5fXx/JZBKbzSaPOHt7e3G5XCUFhiTRjqyq1C42NBoNzc3Ncuip0+lErVYTiUTw+Xxotdrzti6Zn59nfHy8RGqvVqvJ5/Ob8o6MRiNarbYkwmMbz1xsqe/3yU9+8kJvxza28ZRDq9Wyb98+/H4/c3NzhMNhtFotTU1Nsgz28UBaHJ6oH0mhUGB+fl6W/uZyefr6yhDFEcLhMI2NjRiNRpn8Hw6HgTMjDekKXbpdMveTigNJubRW3r22cJB+lhY9rVa7ocvsoUNZCoV5cnk9K0ojokXHS96oQp9aJp+HnTunecELQggC/Pu/n+L732/kyishmdQ+bqKmuLRE6qqrqF5YQPXzn2Pr6mJwcJB0Oo02FGLPNdegrK5m7NZbGR4eJpVK4XQ65dBFiachwWKxYDQa5SLBYDCwND1NYm6O0CphfHFxkSNHjqDX6zFGIljWkH7D4RQ333xg3XYmEvCtb0mvkeHjHy9GQen1eqqrqxkfH0cURebmEnz/+02srKgQhDOuwLEYfOITAqLowmzO8qY3FdV9Z3O/pqamsFqt2O12JicnZX6IxAHyeDyyN1B1dTXhcJiBgQFEUeTgwYMYjUaOHTsmS6DHxsYwGAwln3M+n79gbsXnA7fbjVarZXp6WrZ3UCqVVFVV0djYuKk531osLCwwODiI3W6no6MDk8lEIpFgamqKxcVF5ufnN1SYFQoF2TNpG898PGHV1ezsrEzU2wjbXZ9tPJOgVqupr6+/oKTLJ4JcLsepU6fkrotSqeTkyUquu66DG244xXOfG+XkyZPs3btXLhYkT59CoUAwGCQSiZQocbRaLTabjbm5Oaanp+U4h2w2KzsgSxLcIt9kDpvNds5FTgrEnBeMeMzVZBSr3SERNGorDXuDdOZC8usPDTXwgx/U0Nk5yPHjU+zatesxC8JkMonP52NpaQlxdpbdCwvo/X7cb3kLs7fdRjqfZ39lJfq/+zsUPh85pZKO2lr02Swej4eqqirq6+vxeDykUimsVqsc4DkzMwMUi73x8XGUsRi2f/gHqpaWiN1yC81XXolOp2NiYoL48DB7r70WXC6Wf/5ztJWVWCyPXQD86EenMZv3yL9LHcLx8XEAvvWtRT796XYGBy2IohTEWjQIPHgww3XXnUCrtaPRaErGnlJy+a5du+RiPJPJcOTIkRJpttfrpampiXg8Lhs/7tmzRzaxkxRJLS0tLC8v4/V6S8z75ufnN41RuFhwOBxUVFSQTqfJ5/PodLrzHvlKaeISAVkQBFKpFAqFgsbGRoLBIBMTEzQ1Na17zoWFBXK53EUxTdzGk48tFzq/+c1v+PCHP8zY2Ng5H7dtGLiNbWwdIyMjJBIJdDodGo2GPXv28P3vF0/KDzzg4NJLi6TMoaGhkpOyUqlkbm6OYDAon+h9Ph+ZTIaxsTGZgzQ1NUVFRQUrKysMDg6ya9cuAoGAHHcxNTVFNBp9TL+SmZkZfFk1o8ZaVl0OZWQENaOGWnYkZqnV5jlw4ADf/nbxMadPt/PiFw8yODjI4cOHNyRwFgqF9UZ+Nhu9N91UlNRPTeF4wxvgS1/C+Pa3w9QUabebvhtvJDs9LecmTU5O0lpZyVIsxhzFgEkJarWa7ooKLC4XcZWKmYcfRrO0VJTrf+ADTHznOyyZzSh8PvZdey1an4+kKHL66FHSqwnkd999Nw0NOzhwoIpEYm2QqsjPfvYwu3ad6Zjl83lCoRBqtRqXy7U6Zlzm17+O0tVlOcsgEL7znUlisSKXLBAIyER4QB6lSXlX0viqvLyc5eVl+f1XV1dTWVnJo48+itFolM/NEk/I6XTi8/kYHBykqqqKUCgkR4MMDQ0BnJdS8EJDUqs9XqysrJBMJh+TZN7f309bW5tc5C8uLjI6Okp5efm2RcpfCLacdfWa17yG6upq3v/+93PrrbfyvOc9j7a2Nv785z8zODjIK17xinUBh9vYxjbOH6lUipmZGZxON9/4Rh6Tyc2dd6b4+c+L999/v4GamuIVttGY41WvmpEzkRQKBdXV1dTU1JDJZJiZmSGTydDY2Eg6nSaTyVBZWcni4iLhcBiLxcLKygpHjx4Fig62Y2NjZDIZmpubz3llWygU8Pp8ePSNnF3kACAIFPIi37+9ivpcnv/934T8Hn7xC6ipqcfrVfDAA1H+5V/snD0tGB8fl4ucmpoaWltbOXHiBIX6enpvuom9116L3uej7o1vBCBXX8/JL36RtN1O/SphdWZmhsWpKVJ/8zfsjERYvP12hLo6crkc8Xic5YEBdG98I6LLhfGee4iVlTHzgx/Q+q53ofN4aH33uwl96UtUf+QjqFY9jEa/8Q0KNhtks7LT9B/+sEIiUZpMnkjAzEw1L3pRsUiYn59nZGSEXC6HTqcrSUz/858z6/PP4vDAA0n+v//PSVVVFZOTk0xPT8scGokgv7hYDGqtrKwkkUiwuLhIS0sLZrOZY8eOoVQq6enpAZCdmPv6+lCpVLhcLurr6+ns7GRgYEDm4gwNDRGNRlEoFOzevfsJccuebJwds7EZFhYWOHLkCCaTiXQ6TSqVoqysjPb29sf+4208I7ClQucLX/gCJpOJEydOUFVVxa233spVV10lR0Jcf/31fPazn13nvbONbWzj/LG0tMTLX/7yTe9PJOA73ykAAmZzlle8YhGFIiWPGiQzQCiSKzs7O9cVLNlslrm5ORYWFjCZTHI3QDJOkxxez4V0Ok24oDkzrtoA2ZSC33x5fZbQygp87nPFn63WLB/8YJHDIiGVSuH3+2X+zI4dOxAEAZVKRTwep1BdzdDHP87e979f/ptT112HUFeHYXVEIYoiwWAQZS6HOhJB7/fjevOb4f77oa4OZmfJffjDqGZnySuVKKNR0uk0utZWFA8+CFdeiWZyEvcb3lB8v243M9/7HhGVCvNqyrper+fEiRMcOVLcv895zjwf+MAsN99cKxv8SSaLp0+fxm6309zcjF6vJ5vNMjk5SSAQ4Le/Vcl/v9Yg8OjRKt773qIqrqmpSSbXOp1OtFotRqORqakp1Go1jY2NKJVKhoeHGR4elveL1+st8VWCYhfIaDQyPT1NKpWira2Nw4cPc+rUKTnrq6mpierq6vPixDydIHW8zvYNkhCNRunp6aGtrY1kMkkymcRoNOJwONYpz7bxzMaWCp1jx47x6le/ukR2t5a8+PGPf5y77rqLT3ziE/z6179+4lu5jW08C3G+MSoHDqT58IdPotFkaG5uoaamBqVSSTgcZmZmhuXlZZqbmzdUmKjVatxu9xMKNATIKs59KtEaH/u9/Pzn45jNbSW3LayaHqbTaTmQcXp6WnbtLY/Haf3850v+pv366+m96SaUzc2MjY2h0WhIJpNoKivpv+UW9nzwg2gnJ+HKK+G22+Dqq1FNT5NyufB+97u0uN1o/P4id6m9vfiYyy+Xnz/33e8SNhggk6Grq0suABobG7n00lkuuURPV9cgZWVWfvUrgd/9rkBjY3HRnZ6exmg00tHRIQeiDg0NyTL9yy5boLk5JpO2v/jFce67L4bFEmFmJk1jYyNutxu1Wo3H4+HUqVPydkmp5JFIBIvFgtPpJJvNsrKygsPhIBKJkMvlqK6uxuFwMDw8TCaTIZlMUl1dLQdq5nI5YrEY9fX16wJTn0mQbCLC4TAul2udMePU1BRlZWVyLMY2/nKxpUInkUiUkNLWSlQlHD58mO9973tPbOu2sY1nMSwWC3fffTetra1MTk5SXl7N857XzCp3GACdrsDXvz5CNJqmubmlpGCx2+2Ul5fT09PD9PT0BbPwPxs6nQ6j6rEXik895OFVLguXdWhK3oPBIPI///MQbW3rO0eSekjqMoXDYaampqirqyM+PEzLu9+N3u8n5XJx+mMfo/3669H7/XRfcw2j3/gGoVSKbDYre/4YW1o4dfPNHPzwh2Fy8kwB09TE9De+QXL1yr+qqorp6WkaVSp0V19d+n7f/W6EG26gbMcO1Go1qVRKlvN3dq7Q0BAnGrWTy+VwOCp4y1vOvJdIJMKOHTtQKBSsrKwwMDBAeXm5nJ7e2RnmyivVLC+r0Ol07Nu3j8suU+DxFAs8qYNTVVVFZWUl8Xhclvlns1kmJiZKHJKNRiO7d+9meXlZJte2tRWLya6uLvr6+hAEgWAwiEqlYnBwkEwmg91uPy/5djqdlmXtFovlCRn4XWgIgkBLSwv9/f2cOnWK+vp6OX9qZmaGcDgsF5zb+MvGlo7K6urqEht4l8sly/8khMPhbSLyNrbxBGA0GnE6nYRCIRobG7nnnhiJRGkxkErBww/n6OoSZOfctRAEAafTyfDwcFF6rV3vQiyZyEWjUQRBwGazlQRSroUoimSzWURRRKPRyF2EjppyhuYzZBRqNuTpiCImrZrBh6IkEqULqMRheclL1sdlSAu41Wplfn5e7lY0qtXwj/+I4PcXM79W4zBkgrLfz46//3t6v/xldKtp56IosrKygqKqal2XRvzv/2ZFo8G4Ou5wOp0s9vXBG98Iq4XU0Mc/TtvnP4/e46H7mmuY++lPmZmZYXJyEqVSKRO8PR4PGo1m3ahHOh9Kn8Hs7Cw6nY5du3aRz+cJh8NoNBq0Wi27du2ir6+PpaUlysvLcbvdzMzMEAqFZGdnQRBKzO6KobBdpFIpUqkUarUag8GAKIoMDw+TTCZLvGEUCgUdHR2yclav16NUKmlra3vMLodEal+7DkiE5sbGxqdN8WC32+ns7GR8fJze3l75dp1OR0dHx9bcybfxjMOWjsY9e/YwMDAg/37VVVdx33338ZOf/IR4PM7vfvc7fvazn9ElRTFvYxvb2BKkGAO/38+xY2cCHn/4w0e4/PLiInPiRPEqfzPZrUQglQivaxEKhXjkkUeYnZ2VvXUmJiY4evQoKysrcvZSOBxmcnKSo0eP8tBDD/O1rw3xyCNHmZ2dRRRF6mrddOtSxXSHs0duq783pUP85jfFm5773AXuuKOf5zxnAYCRkZ0lhUGhUCAcDpNOZzh1qpx8vugBs7S0REVFBYLFguhwkHI6Gfyv/yKzGsORqaqi96abyNbWIlRVobHbSaVS8hgwn8+j8PlIr/Jt5Nd7y1vITU3J43j13Bx7PvhBdKuFVM+NN7K8axe9N91E0ulE7/dT/bd/i+/oUWprazl8+LAc6dDZ2Ukmk1lHhlWr1ahUKpaWlshkMszPz6NQKBgZGZHJ1tlsFr1eT1lZGQaDQS4kVCoVWq12UxuPsz/vsrIyOetLIju//OUvZ+fOnZhMJvmf3W6nu7ubl7/85ahUKux2O9XV1ecsVKSMqKWlJVpbWzl8+DAHDx7E5XLh9XoZGho677HrkwG73c6hQ4fYu3cvHR0ddHd3c8kll2wXOc8ibKmj88pXvpL3v//9TE9PU19fzz//8z9z++238xapR0vxi/nZz372gm3oNrbxVEFadCVeiM1mo7y8/AmRFbPZLMlkEoVCIS9IG0Gr1bJ//34CgQBXXLFMY2OUl7xkEaPRwA9/mODBB3NYrSpSqdSmHZvl5WUUCsW6+6LRKENDQzgcDnbs2CF3cNLpNIODg/T19a12ABL09ZWxZ88SggCPPlrOxz7WxVe+Mkk6PUE0GqW9vZ2rOhqx+hb503yOFGeKLq2Yoz4ZoCy3wpVXqujs9PCc58xSKOS56aYMg4NWWlrOqHkWFhYYGxsjnU5z9GjxtW644RSXXlpMVp+ZmWHRZCL+iU+giMfJrEbODA0NodPpSFdVMfqtb5HR6YgLAhQKVFZWMj8/j2Zuju5rrkHr95NyOlH86Eco/u7vUHk87PvQh9A89BDY7WA2k7JYEJxOUr/9LQ0OB4IgkKirk7tGmbIyCkYjFouF/v5+5ubm2LlzJ4uLizK5VXKgzmazBINBFAoFs7OzzM7OAsUOWSKRKJG6V1dXIwgCGo1G7gLlcjk5vuDx4ny7K7lc7rziDnw+H6lUigMHDpQYPTY1NWE0GhkaGmJ5eXlDI77z2Qbpe2EwGC4YIVgQhBJDzG08u7ClQucd73gH73jHO+TfGxsbOXbsGDfeeCOTk5PU19fznve8h+7u7gu1ndvYBvl8Xh5fiKKIxWKhqqrqoqpBotEoAwMDpNNpmSvi9XoxGAzs3r37cTv6ZjIZJicnCYVCMoFfp9NRW1srm7OdDZVKRW1tLe985/rna2iAXK6MI0eUTE1NsXPnzpLnSKfT+Hw+HA7HulGU1+tFq9Wuy6XTarXU1NQwMjJCPp/nxAkHH/7wLm6+eZTDh5d44IGiCd1dd+l5yUtqmZ2dpaKigsrKSva77VQJfk5MzlBWVYNVpyYyOUJ7WxsKhRtBGALCFArFK/5YLMoLXxiSOX+Li4sMDAxgt9vZvXs3//3fxdHM0aNuDh1aBIqL4dLSEgqTCdtqAKVUAEgOyHNzc8UiYTWJPRwOowmFih440rjrpptIA9ovfpH9112HdnYWrroKHniAtMPBic9+FqfFQnVzM1J5YTKZSHd2cuQLXyCn1/OSv/qrc37ek5OTKBQKTp06RTabxWw2l3R6MpkMZrMZjUZDJpNBXI2zyOVyLC8vY7PZGBwcJJFIUCgU5KysxwOVSoXNZuPee+8ll8uhUCioq6vD6XSSz+eZnJwkGAxiNpvPi8cVDAaprKzc8NivrKzE4/EQCAQeV6EjKc+Cc3MsCXqyChUmtYJOdyXOmuonTQEliiKiKD5tRm/buDC4YMyx5uZmvvKVr1yop9vGNkoQi8Xo7+8nnU5jNptRKBRMTEwwNTVFR0fHRXEwTafT9Pb2ygWJlI+Tz+dJJpP09vZy6NCh8yZgZrNZent7yWQy1NfXU15eTi6XIxAIyB2Mpqamx72dKpWKlpYWRkZGSKVSuFwutFoty8vL8kjq7MgDKBYVNTU1607qoiji8XhQq9UUCgX++Mfivv3BD1pZWRF58MFikfLgg5XccIMXtXoHFkuGz30OBEHEOztDq91Cxw43p06dwmqxUFFRIXMkRFGkpaUFURSZnJxkbGwMrVZLRUUFExNT/PrXNZhMRZXML35RZC3/4Q9aXK4mlpejlJWp+ad/0tDYeCZhO5fLyT9LHBGv14tCoUClUlFTU0NgeRmqqkCrJfLjH5NOJtFoNOx95SvRXHppUYVVWQlmM7FYjLzJRMuajL+tIJ/P09/fj0ajYf/+/UxOTpJKpTAajbIKKhKJlCzkJ06cQKvVyuZ1UhEExRyqzs5O2cguk8ng9/uZn1/g2DEDz3lOHpfLWdJxXFpaIhaLlSRq+/1+/H6//JpWq5U9e/acV0GRTqfXBWFKkHhD5zNikyB9L3w5NdOWNpLimePxdCDDwZiX5+6oPcczPHFEIhFmZ2cJhxfp6yvjssuyuN1nkt+38czGBSl0FhcXicfjMkluG9u4kJBiENRqNXv27JGvJNPpNKOjowwODrJ///7H9Ht5vJieniYWi2E2m9mxY4fs5bK0tCQ7FgcCgfM+7r1eL+l0mv3795dcDdtsNtkHpbq6+nF3iaBopCdJjiVhgOSF09TUVMLTCQQCBINBstksgUAAtVpdkuVVDJjUk0xqKRTy3HefHohz8iScPAlFIo6JZFLBt75VBwhYLFn++Z9BoUiQSqXkeIN4PC4rmJLJJN3d3fT19SGKIrW1tSQSCUKhEENDQ3R3dzM/n+Cmm9ZnRq2swK23Fn+2WrO85CVHWFgIYbPZiMZieOM5MioLGjFHPJFAoVAgCAIVFRW0t7czPDyMaLGg+N3vIJXCYDJBb69s2kdtLTzwADFBIBAKyWPKx8KRI0fYvXs3mUwGQRBQq9XFEVciwfHjxykUCqTTabq6utBqtYTDYex2O3Nzc3JIZqFQkD+/6enpdfyeQqFAY2MjDoeDoaEhTp06xaFDh0in0/T19ZHP5xkaauB976vj5ptH6erqp6amhh07dpBIJDh16hRmsxm73c709DT5fB6VSiVztqxWK52dneddsKvVajk25GxIo7jH812cnZ3Fm1UxoncXD601yCjUPBRTUxaK0ll5cVyK/X4/o6OjmEwmvN7dXHNNBV/7modEYpRIJEJHR8d2sfMMx5YLneXlZT7xiU/w05/+VPa6kL44R48e5VOf+hSf+cxntt2Rt/GEEQwGWV5e5tChQ4iiWJIoXF9fTygUwufzPa508fNBKBQ6p2EfFI/18yl0RFEkEAhQVVW1YSHjdruZnZ0lGAxuqasDUFFRgX2VfCst4GvHeplMhr6+PhKJBBUVFeTzeXK5nGxW193djUKhoL9/kq997dBjvSPyeQEQ6eqK8pnPjGM27yUcTsnvF4pKnEwmw8LCAjU1NZjNZlnOvLy8LMdbxONxQqEQBsNjKzXvuWeOnTt3Mzk5Sf9cFI++mozxDHdlfDxOhyKDbrUoPXHiBLFYjPb2dtSro5+F8XHZeFDCVDbL9PQ0arUai8VCLBbj7rvvxmAw0NnZWcJx8vl8TExMyOOmtSOffD7P+Pg4FouFQqGA0WiUF/5CocDKygomk4ldu3YRDAYZHR1lfn6ebDYrP0c6naalpUUeO0nJ9I2NjTz66KMEAgE5xburq4sf/KD4/vv6Wnn9682MjIxgMplYWVmR1ViSKioUCpFIJEin08zPz9PY2Pi4ZOHV1dV4vV7q6urWOSVLF73newyLoog/EGDG2LKuyCmieIz90Z9kl8OE4gIXHKlUitHRUZxOJ62trXzta8XnP368gde9zsjg4CDBYHBDReOTiUKhwPxCmIlwjKQoUG7Us9tlR/00kvM/nbGlvbS4uMhll13G6Ogo+/btk680JHR1dfHQQw/xox/9aLvQ2cYTRjgcfsyC46GHHrrghc5GKqWzcb4t+kKhQCaTwWKxbHi/UqnEZDKRTCYf1zaeDUEQZJnz2RgdHSWTyXDgwAGMRiMLCwsMDAxQV1dHMBhkZGQEQRBQKje+Wt8IOl2BG2/swel0yEocQB7XqFQqmY9kNBo5evQo+XyeQqFANpuVOwMajUZe6CcmJrDZqnC7Wee389Of/pnGRhX5fJ7ppLBptlavaGeHKkF5ZgWtVktLSwsLCwuMjo7KPBhAJt9KAacNDQ3U1dXJo9HZ2VmUyiL/ad++fUDx/BcMBqmvryeZTNLT00NVVRVWq5VMJkMgECCdTrN7925CoVBJN0AqPlpbW1EoFLJS7uDBg+RyOU6ePEkul+OlL33pOff7kSNH+elP7ZSV1fO732n4xS+Kt99+u0BTUw1zcwq02iQve9kczc2N8uuoVCo5r0oURY4ePUooFHpcfBqXy0UwGKS3t5empia5aJ6bm2NyclIm658PCoUC4YKGpHiOoE5BICkKHBubRVgKyseS0+l8wqIAny/AnXe6KS9vRKEQ5P34i19AY6ODYLANgyHD9dezLprkyUIikeCPA5OMKsvJKFa7Wmm4b2Geq2p07HWud33eRim2VOj8+7//O6Ojo/z0pz/lDW94A5/61KdK4h70ej3Pe97z+OMf/3jBNnQbz16sdd1+Io/ZCv74xz9y6ND67oYoijz88MPnnaSsUChQKBSkUqkN7xdFkVQqtaWx1fkglUqxsLBAa2ur3F2w2+2yP4vkIAvF0cTdd9+NXm/lpS/dTTq9+XtMpZQMD1tQqUIYjcYiF2ZVKp3L5UpGMGNjY4iiiFqtpr29nZGRETQajeyRUygUKCsrIxwOMztbTyJR+rqJBMzO1vCyl9np6e1lxuhms2wtRBGvuRZbZJBoNEo0GkWtVsvdIwn5fB5RFJmZmcFut5c4AUu5YKFQiGg0Su/qqCsej2Oz2di5c6dMTg8EAgQCAXlc2NHRgdlsJp1OEwwGSSaT6PV6qqqq5LBJKOZeGY1GVCoVMzMzJVyjcyEaLfD97zexsqJCEM4swrEY/Nu/gShWYTZnueqq2U3zqaSwzPMp6NdCo9HQ3d3N8PAwp0+fLrmvqqpKjuk4HygUCnKP4aotwReO0GGzoNFoWFxcpL//zIhuq8XO/HyC731vJ8vLyk32YzVmc5Z//dfSaJInC7lcjj/0j3NaXVM8rtcgo1Dxu2AOtSrG7sqNOVPbKGJLNeqvf/1rXvGKV/CGs7wo1qKhoQGv17vlDdvGNiSYTCZ+//vfs7KyQiwWW/fvoYce2pQc+USg0+kQBIF4PC6PH4y5HMZIpChVXjV3kxdzrxc24XYIgkBlZSWBQGDDhSUcDpNKpS6at4cU4uhwOEq2qbm5mV27dpXIlq1WK62trfT360mnLYCx5F9XV6bEx+eRRyoxm83U19eXjOdEUUSlUsmLUKFQQBRFuXORz+fZs2eP/J7T6TTNzc0kk0m++90QAK98ZZ6TJ1e46qrifh0cbC4ScJMiqXNdpwkCiYKArelMMGM2m5WLHIPBQG1tLX6/n7m5OZlLtBYKhYL29nb27NkjF6lGo5Guri55FKRSqWhoaODw4cM897nP5YorrpCLHCiqkNRqNcPDw+RyOZnc6vV6OX78OAsLCxgMBnp6evB6vXI217333rvhsb6yssIf/vAHrFYFt902wGWXFbdV8maV/j94MMO3v30co7HA9PS0HOq6Fvl8nlgstmkH8FzQ6/Xs3buXAwcOyLEUu3btYufOnedd/MPq98J6fhVEs7uGnTt30tTUxIEDB9i5c6dcYG4VJpPIj388vOl+3L8/xXe/e/IpKXIA/IEg46qKdUVOEcXb7vUnKDyNfIuejthSRycQCPC3f/u353zMWgfObWzjicDpdOLz+QiFQjQ1NZVcvQWDQTKZDC0tLRf8dWtraxkbG+P06dMEAgEcGg0VV19NIRAgeNNNUFlJNBrlyJEjuAoFmt/5ToTKSrjnHtjAs6O2tpb5+XlOnTolp0oXCgVCoRDj4+PYbLaL7vVxdudL6kBYrVYefvhhBEFg165dCILAsWPFBUQKmLzhhp3099tob4/icqX4zGcG6evrQKkM0tDQwPT0NBqNhtraWvL5fJFk6vWWmMdJijkpPT2VSjEyMoJer5e5K93d3TzveQFqayO84AUhlpfh85/X09PTRleXlXw++pjZWhIW4yk0KhVdXV0sLy8jiiJGo1F2dV5cXJQXyo0WaMkpWqvVYrVaqa2tlQvgsx+30d8rlUp27dpFf38/jzzyCJWVlZhMJqLRKLFYDCh2dcrLy+ns7GRhoWigqFAoWF5elsdMcCafSalUUlNTQyIxwW9+E6OuzsTaU63BIPIf/3EcUcwgCAoSiQRTU1NMTU3R2toqP6fUQaquXu9IfT6Ix+OMj4/L40qv14tGo6G+vn5Tq4SN0N1QzbGRKBmFis1ctbXkWJwY4WTITGdnJxqNhpqaGsLhMF6vd8vqqIqKChYWhrnrrgRut2Hdfrz55lPYbE9RlQOMLUTJKBybP2B1rOf1LVCZWsYrKJiMxEmJCsr0Gna7KiiPx4vtqGexj9CWCh273S4bXm2G4eHhp5zAtY2/DBiNRpqbm5mYmGB5eZmqqioUCgULCwuEw2E5pPBCQ6vVolAqiaBjIVYgGJzgikBAzlIK/uQnOC+5hHBvL7bXvhbB70cEhGh0w5OK1A0YGhri5MmTqFQqCoUChUIBh8OxzgPnQsJqtSIIAqFQaMMMI8mwTpI0WywWDh4McPCghje8QSSVqmHHjgnuvNNAU5NSVu10dxdHFxK5+Kqrrjrndtx3332yeeHMzIy8bQ6Hg/Hxcdkf6R3vsBCPx0mlij5JZrOZw4eL+yad1qAunN+4RUzFKS8vx2KxyCndUogmFAsKKc5CUkSdjZmZGdkAMBgMolQqqa6upqGh4bw8nMrKyjh48CA+n4+FhQXy+bxMLq6urpZtBqQA1h07dhCLxWSSssPhQBRF5ubmWFlZoampCZfLhc/n45e/9BKPlwahxuMCp07pePGL7TQ1NdHb2yuPRSWeVjweZ35+noaGhi11dBKJBD09PWg0Gtrb2ykrK5OjRMbGxsjlctTX15/Xc5lNJq6qyfK7YA4QS7sXq0XyyxptVAvdnD59mv7+fvbt2ycX6dLnuRU/LYfDgcfj4Wc/8xCPd5TcF48LnDyp4q/+SsfY2BhKpRKHwyF3654MJAs85txFG12h/J1/Qz4Y5I/f/BWLzobiHVkYfnicq9/71+hdzk0vwJ4N2FKhc8UVV3DnnXfi9Xo3TD0+ffo099xzD29/+9uf8AZuYxtQ7IYYDAa8Xi9jY2NAcaS1c+dO2Un2QmJhYYEHh2eYNrWSlr4mTbVMf/MO3vTu12Dy+2h8+9vhtttwXn01rJrQJW6/Hfs5ksCtViuXXHIJi4uLsreJ3W6/aNwcCRqNhurqajweDyaTqYQsGolE8Hg8VFVVEY/HmZiYoK2tjc7OFfbsUWCz2YnFYszMzPCKV+RWR2xOmWQsdaXOB1JHIx6Ps7CwIEubBwcHMRqNJZ4+a9VKUBy1TE9PEwgEsOSzaAoZMoJ647a+KGLWKCjPZigUigXlwMAAS0tLOBwOYrGYbMIHyFJ7h8OBzXaG3OnxePB4PAiCUFRtqdUEAgH8fj/hcJh9+/adl1uxTqejubmZ5uZmoMi9kN6L5Gcj7Qu73Y4oilitVrxeL6Ojo0CxYJLuB9i9eze33roEwAtesMLHP77Ipz9t4cEHyzl50s373190c+7u7pZNAaX3pNfr2blz55YvRj0eD0qlkvb2dgqFAvl8HovFgsVS5NB4PB5ZMr+0tEQgECAeT9Dba+WlL9VTU1OapbbXaUOvS/F7b4z4GuGdXlGgJbdAm80B6Ghra+PUqVMsLS2VfE5bhVKppKuri698ZQmAK6+McO21Ab74xUr+/OcKjhxx0Nk5gcFgIJvNMjMzQ3l5OR0dHU9KgKlVp4HMuR+jScQQ5+Yw+b28/j2v58ffvINotQtz0Mfr3/N69N4ZUoKAbpMLsGcDBHELoST9/f0cOnSIyspKPv/5z/PII4/w1a9+lYGBAR5++GH+5V/+hVgsRk9PD62trRdjuy8YVlZWsFqtLC8vb6qI2cbTC9LidLHcS0VR5DeP9nNaU8P6VrqIOeDj7979Soy+NV3Npib6b70Vamvp7Oy8KNv1RJHP5xkYGCASiWA2mzEajcTjcaLRKGVlZbIfjES6lZx4lUoloVAIrVZLKpWira2NpaUlgsEgBoNBjp5IJBIkk0mcTifNzc0cPXoUtVpNJpOho6ODvr4+Kisr5avx4eFh4vE49fX1DAwM0NraKjskb7TtfX19xGIxampqMJlMHJ2aY1i3+vizuwACvKbRgn5ljqmpKZqbmxkfH6elpYXJyUmZozMxMYFarS4Zs9vtdmw2G4lEAr/fjyAIdHV1USgUGB8fL1HGKZVKWltbtzz+kdR4a838NnqMFJ56Nu6/P8upU0tcdtkMhUIeUYT//V8zL3rRDq64onSUlsvl8Pl8TE1NydlcW0Eul+PIPfdgEkWW13Q3zGYzTU1NmJaWeHRoiLrOTpLJJH6/H4PBQF+fk3e/280NN5ziuc+N093dva6blMlm+e0jvVS4anE7ytEmlhgeOs2BAwcwmUyyUsxut6/yyPrlOIoncrHzpz8VGBiI8rzn+RHFAkqlih/+ME9bm56//usadDodoigyPz/PyMgIFouFrq6ui+6vs7S8zHfH4+cMy9UJBQz+GV7/njdg83qIuBv43898hVf82/tWf6/n9m/ezjteuu+Cy/Ofapzv+r2lQgeKhOSrr75anjOLooggCIiiiNls5ic/+cljSoIvFL7yla/wH//xHwSDQfbs2cOtt966oVJmI2wXOn9ZSKVSJJNJlEql7NnyeLEQDvPfnjQZxeZX6vU9D/HG//fqMzc89BDD5eXE4/GntaWCKIqEw2GCwaCcnVRdXY3dbpcLRyk2wuv1UigU0Ol0OJ1OotEo8Xic5uZm+vv7Abj00kvlbCqlUilnM3V0dMgREi0tLSwvLxMOhykUChgMBqqrq5mbmyOTyZDNZqmoqJC5QRthenoaj8fD3r175e9pKpXiz2M+TmX0JZ+VUQkvrjOzs0xLNpvl6NGjiKIoc2hyuRxut1tObO/q6mJ8fBy1Wk0ul0Ov18vFjCiK7Nu3j2w2y6lTp7DZbNTX12M2mxkeHpbf0xPpjlxITExMsLCwwCWXXLLh/ZFIhL6+Pg4dOrTlLuL8+DiaV70K7fIy0V//GsPOnSQSCWZnZ0mPj3Poox8lYTIx9dWvspjPs2PHDmpqanjnOwW++11429tyvPe9J1AoFOsKlEwmw8MPP8yuXbtwOBwUCgW5YJa8jI4fPy4X6uPj47S1tW250NwMfX195HI5uSgvef/z8wwODrJv374nZc14cGSGh+P61TpnfUG/QxFntGDCHPTxpne/GpvXIz8k4m6QOzxvbLZQb3n8WWlPZ5zv+r3l3tsrX/lKpqam+MEPfsDRo0fluf4ll1zC29/+9i1lsmwF//M//8O1117L17/+dS655BK+/OUv85KXvISRkZHtdNpnESRiZCQSkW/T6XQ0NDQ87pPgTDRzziLHHPTx0k9+sPTGq68mc8staDbgvzyVyOfzZDIZOTlbcgs+1/dTq9XS1NREdXU1J0+eRKFQoNPpVg39DPIopa6uDq1Wi9PplFPPJUiyY0EQVscWcVndNTs7y+TkJFAcqUkE2c2KHFEU8fv9VFVVlZzMdDodL+xs5rJkkntPDmKyV9LkqqbWpJavXKUFsqenhyuuuOKc++rRRx8lk8nQ0NCAw+Hg9OnTctzB8ePHKSsrK7mKr6iokDk0k5OTMndMQiQSwefzyS7LZWVluN3ui0o4NxgMMp9oI+5NJBJBqVRuGP56vgiMjtK6tITO70f3+tfD/fdjrK3FnkiQfdWrUHq9qJxOEnPz/KH3Uh56qFgASh41d9yhwu3uIhgMcN99Ca67zijLutVqNRqNhkgkgsPhQKFQ0NnZSV9fH4888gg2m41YLEY6nSYQCOB2u88riPTxQIrl2Ey2XlFRgUajYX5+/kkpdJ67oxatJ8TDEZG0cGbJNqwW9DOzKwBEq13872e+wtVvP5O/9r+f+QrR6mLXM5a7OBYczwScd6GzsrKCTqcraa+Wl5dzzTXXXJQNO1/ceOONvOtd75L5QF//+te56667+O53v8vHPvaxp3TbnlZYXia7uIhfqWI8HCMlCtj0WjprHZiXlp7RrHyJGKlWq2lra8NqtZJKpfD5fAwPD5PP5zcdiUjIZrPMzc2xtLSEP62ETZQOa6+aUvUN6H78I7j6apicpPXd7yZx110X4y0+bqRSKaampgiFQrLqyWAwMjxcxQtfqKaycn3I59kwGAzs3buX0dFRuXCROrhWq1XOzxIEgdraWmKxGIuLiwiCIEuZRVEknU7T0dEhE8ZVKhXJZJJsNsvBgwdRq9WkUikCgQCpVAqVSkVVVZXckZNiFDYztTPo9dQaVWgKMerN6wtUq9V6XoRbKcxR8jpSqVSsrKzInay1RY4oirJCan6+KLPv6emhpaUFq9XKzMwMk5OTGI1GXC4XoigSCoXkcf5jHY9no1AosLCwwPz8PPl8XvYsOrsrU1lZycTEBBMTE3R0dJQUXvF4HJ/PR3V19eOSgK9FPB5n0WBg9BvfYOd73oNucrKYEXbbbSiuvhqt1ysHpkYMDr7ylSqWlljnUfP5z+sQxSas1jzvfe8ZjxpBEHA6nczMzMgmjCaTiUOHDuH3+2URjMlkwu12X5SMO6krudko8exk+YsNQRC4pLGKA/UFppfTxHIFrFo1teZiQR9f0sNS8dz0in97X8nfvuLf3id3dEzqZ29Q6Xm/c5vNxg033FBy29GjR7nlllsu+EadLzKZDCdOnOCFL3yhfJtCoeCFL3whR44c2fBv0uk0KysrJf/+4rG8TP5FLyLz3Cv4Xf8cx3DQL1TwYMrMTx4YInnZc+ClL93UA+bpjqmpKVQqFfv27aO6uhq9Xo/NZmPXrl04nU4mJiZK7PXPxvLyMkePHmViYoJ8Po9+k2+Fec4vFzkRdwPB39xDev9+fD/6EUmnE73fT/nrXlf003kKkUwmOXnyJJFIhIaGBrmzed99Wt72tjp++MN5jhw5gs/ne8znMhqN7N27l4MHD8qLs06nWyexluIEXC4XZWVlmM1mLr/8crq6uoBih+fEiRMcO3aMY8eOkcvl6OrqQqVS4fF4eOSRR/B6vSSTSRYWFjh58iQDAwPk83mZn3K2D4wEqZg61+JdWVnJ3Xffzd13343H4ynxppmbm+Puu+8mlUpRKBTkBc7hcJBKpWQjRYkYLYoip0+fZn5+HkEQ5Nsll+TJyUkmJyepq6vjwIEDNDQ00NjYyKFDh3C5XIyNjeHxeOjt7eMb3xjh9OkhlpaW2IxFkEqlOH78OKdPnyaVSsldskcffVRWrklQKpW0tbURDoc5ceKErPQaHx/n5MmTcpdzq5CKQPell9L35S+TdrlgchIuvxwmJ8nW1tJ7001oW1owGPLcf//yJh41Ap2dK/zmN7PrPGpqa2sxm8309vYyPDzM3NwcwWAQv98vq+UikQiDg4OMjIxselxsFVL3U5LNnw1JtXaxBQRnQ6lQ0GTT0+UwUm/RyF3LTreDcr+HN737VfK56bbv3UXE3YDN6+FN73oVVfNeak2PX5X2l4LzLnSk+Pq1uOeee57Sjo4k1Ty7dVlVVSUrDM7G9ddfj9Vqlf89G4JI80tLpPwBjL4iK98cLC5wMit/dpq0PwirpnJPJ0SjUYaHhzly5AgPP/ywTKaVkM1mmZ+fx+12r5OXCoJAfX29TCLcCJlMhv7+foxGI4cPH2bPnj1c1d2GXijI0lb5sQYTCVsFEVc9P//6z5gKBzhy5Ajj6TS+H/4Qsamp6KPzVLmLrWJsbEzmP0idhPr6eoaGivLZP/+5CofDwdjY2Kbfk7NhNBppamrCaDSSzWYJhUKk02lZjt7X14dKpVr1JVmgoqICtVpNeXk5l156qRyKajabaW9v55JLLsFkMhEIBPB4PNTX13PZZZexb98+Dh8+TEdHB5FIhJGRERQKBRUVFQSDwQ0dsJeWlkgmk+e0GJC6OgaDgVAoJP+cTCZXIydsFAoFWQUHxVFTWVmZbHy6vLxMMBjk+PHj8vFkMpnkromUeTUzM4NOp6OxsbGkGBQEAZermMru8Xh46CEz73nPTv7v/wR6e3vleIq1EEVRLvh2796N2+2WCd11dXVMTk6uO7YrKiro7u5GpyvKogcGBggGgzidTrq7u7ckw5YgdQGVSiVtL3oRE//+7yX3D3z0o6QrK3G5XGi1WrTaOe67D86uCfR6kRtv7KG9fb3Rp6SEamhoIBKJMDQ0xMTEhDxG7OjooLu7W/al6u3tPeeFzOOFQqGQHb7P9oITRZHJyUkEQbjgI7OtQjM3x9ve93ps3mkirnp+/M078O05xI+/eQcRVz023zRv/vvXojiPC5u/VDzrEsE+/vGPc+2118q/r6ys/MUXOwGVmru/8UuZlf+md796DSu/+OW4/eu/4B0u19assi8S5ubmGBoaQqvVUllZiUKhYH5+nr6+PhobG6mvr5ezpjbztiiebLWbRi/4/X4KhQK7d++WFwCFIPCSegt3eKKrhL9V/xazhZ/d+lM0yRjP29dMJQkEQcBqtRa7AA888JSPAFOpFIuLi+zcuRNQcPPNORSKTsrL7fzqV8XH/PGPdm67zUw0akOjSXDDDSJKZVFIEIlE5CtZq9VakiWkVCrZs2cPAwMDrKyscOTIEZmAbDQa2blzJ8PDw7KhnQQpTHKt+R0gRy84HA55DAZnXKRzuRyjo6M0NjZSW1tLT08Pg4ODtLS0oNfr5SJreHgYi8VyTrmxVEBICqs//elPKBQK8vm8TGwNBoOUl5fLi7kgCOzevZvBwUEikci6uAMAi8VCJpMhmUxiMBjkDrFkSHj2NgwPD8t5ZCdPFoMv+/t38jd/Y2VkZERWg0mIRCLEYjEsFgsDAwMlz1dZWUlZWRmzs7PrijxJqp7P5+W08guhUrRYLOh0OrxeL7ssFizXX19y/64bbqDnxhupqKggnU4zOTnJ2FgV8XjpZ5NICExM2Hn+8zfOxFIqldTX11NXV0c6nebo0aNUV1eX8GbKysqoqqri5MmTeDyeC6rwraurY3FxkZMnT+J0OrHZbEVHbr+flZUV2tranlDBeCGR0+vJWS1knS5+/o1fyJycaLWLX33nV7zlPa9DU131lF+APZV4Rhc6kvRVMjuTMDc3tykBVVr4nk2YWIyx6Gzkx9+8Qx69SIS1taz82Wj2acPKTyaTDA8PU1VVxc6dO+WTtOTAOzU1hcVikdvHyWRyQ5KnlLe02UlpcXERu92+7v42m47XCAK/9SyRWhM4qLGX8UK3m51lWuCsq9Fz+OdcTEheNkqlUlYLzc3N0dc3yXe+c4hoVI0giCgUxQUimVRw/fV6RNGA2Zzlgx9cwW7XMDAwQDwel0c3UgbW7t275fGMRqNh3759zM3NMTo6Sj6fl6W3UpBnV1fXeXnLFA0BU6tF2XpUVVUxNjZGOBzG7Xaze/duhoaGOHr0KAaDQf5srVbrORVbgPydb21tJRaL4fV6ZY6FxMGRXnMtpBBMqYuoUCgoFAqy+7M0/mtra0On09Hb2wsUuUyhUIiKigr52F1aWuEHPzCRz9dQKBTWBEiK1NSUEY12oFbH5MITil1rQRDk/SSZB4ZCISYnJ9FoNDLfaaNjXKlUbpmPsxEEQaCxsZHJBx4ge911aGZnoamJzHe+g/DWt6KZnWXfhz6E8pJLcLvdRKNRvvGNKGDjxS+O86EPBfnMZ6z8+c8VDA/veMziSxAEuWN1docMijyympoa/H4/zc3NF8xyQq1W093dLXsdSdwgq9VKV1fXeYeWXmyIosjA7CzJG26gtbqad3R24kvkWYynWJrzI+hWSN99Fxqn8xnLwbwQeEYXOhqNhv3793Pvvffy6le/Giie9O+9917e//73P7Ub9zRCSix++Z9JrHy/349SqWTHjtKToTSOCoVC+Hw+du/eLY8XpK7PWvh8PgqFwqYKvEKhsCkpd2eZFqU5ztjCCvWt7RjVQomi56lGPB5nZmZGJhyrVCp5QU+n07hcFr71reN87nO76e83yRyJQkEBiBw+XOCaa46j1bbQ1zckm8tJBePKygqjo6P09fVx4MCBkuKlqqo4/pqfn5c7QPX19bJS5nwgjaE2K0KlRVoqSOx2O5deeimhUEg2W6yoqMBisTymjYDRaMRkMjE7O0t3dzf19fUsLi7K5OeFhQWWlpbI5/MsLCxgs9lk92KPx4PBYCCfz8sdRGnhk7YvFovJ3RopHf306dOYTCZZFu3zLfG97zWuKTxFQCAWg899TgfoMZttXHNNFJerqOaRjA3379+P0WiUX7+srIzm5mb6+vrQ6/WPGWor+fUolcp1+1tSMC0uLlIoFDCbzTidzk27pFXZLPaPfATV7CxJp5P+L36RBKC/8Ub2fehDqGdm4MorUTzwAB0dHbz5zUt0dU3zvOf5UamU/OAHCv70JystLed3USV1yzYrnqWuVjabvaAXsWq1mpaWFpqammQO2PkU8E8mlpeXWVpaYveBA7KSst6spN6soVBp4vjxFabzeXY/i4sceIYXOgDXXnstb3vb2zhw4ACHDh3iy1/+MvF4fNuVeQ3KjTpYeWax8peXlykvL980f8jhcMiOso2NjfT29tLf309jY6M8TvD5fExPT+N2uzc9AZrNZtkL5ewFWhRFIothao16OsqfXl3AlZUVmRcj2fjPz8/LV78GgwGXy0U4fIp77y1QXy+STJ4pBoxG+MUvFhgbSxONRkmn0xw6dKhEnSRdvR49epRAILDO0l+hUFBVVbVlroJer5fzpjYKZV1ZWSGXy5Xcd/ZY7HwhCAItLS309fXR19dHXV0dFosFlUrF1NSULAEfHh6WX6e2tha73S53e+x2O7lcTi5kFAoFHR0d9Pf3y4Gc0WhU7sJYrVbi8TiDg4Ps3bsXvT7Ht799gs98pp2BAQv5vBR2qkAQRLq7E3zsY30EgxpqavaiUChIp9OP6Ud2//33b7oAr3Vgloi8VquVuro67HY7y8vLnDp1ClEU5Q65lP/V3Ny88VjfbEZVU4OoVBL7+c+pstvRaDRUXH456ksuKaqwVrlqgiDwilfYeMUrbMCZ46ep6fw/O5VKRSaT2fA7CsjF34XsXK2FQqHYUkzGk4H5+Xl0Ot2G6jOJazQxMbHpvnu24HEVOj/84Q955JFH5N/Hx8cBF59fzAAAojFJREFUNv0iCoLAXRdZbvs3f/M3zM/P84lPfIJgMEh3dzf33HPP04Yo9nRAV20lPb8/xevf89dFTs5ZzplveteruOM7d1Dbveep3lQZ0pXxZpAMKuEMH2FkZET2fZG+2LW1tTSd46zqcrkIBAJMTU2tCwz1er2yQd7TCaIoMjQ0hMFgYM+ePXLu1OzsrNyFCIfDGAwGtFotd901TzJZekUXjwv89rdh9u8vmm3Z7fYNT+ZarRaHwyETmh83lpcpLC8T1uuZm5sjl8uh0+moqanBsrJCtV7P7OwsFRUVJSqWfD7PxMQEWq32go0JysrK2LNnD+Pj47LhoQStVktLS0sJF8Pj8ciBn5LDs0ajQRRFUqkUSqWSkZERoFhY2u12PB4PCoVC5isJgsDKygq9vb2srKxQWSnywx/6OXzYRCp1ZmE2GAR+9CM/Cws5otGigq2qquqc3wEJarV6w45WLpejt7eXZDJJTU0NNpuNbDaL3++XCfjxeByVSkVraytVVVWynH9qaoqJiQmMRuP6/W+1wj33IESjOM4e19bWXnCumsPhYGZmRt4na1EoFPD7/SXcqmcTcrnchnwwCdIFXj6ff1YXOuftjLyVnSQIwpPmNbBVPCuckb1eUpc/F92Mp8jK/9adchbKm971Kmy+aTINjWj+9OBTxjM5Gx6Ph5mZGS699NJ1rXbJBt5qtdLe3l5y++LiouyMLCl/Hguzs7NMTExgMpmorKyUeQErKyvU1dWds1B6KiC523Z3d1NWVobf75el8VKRJ0EQBL7+9UZ++tM6nvOced73Pg/f//5ufvc7PW984yzf/KaNoaEhrFYrO3bs2PD1JiYmmJubo729Hb1ef/7RAcvLFF7yErJeLydvvBFNczM6nY5oNIo4M8P+665D5XRy8nOfI7maRm2xWEilUvj9fjKZDF1dXZv652wVoijKpnN+v594PM6BAwdKjhVRFOnp6ZHJxWVlZbJJnKSuWlxclB+vVqtl5U9HR4eczC55v0hp28FgkBMn9Lz//esvKm69tYf9+1OyXFpyas7lcjIHp6qqSjbUC4fDcsCoJONfi8nJSXw+H3v37pW7Yvl8nv7+/hLptMlkIhaLYbVaqa+vR61WYzQaOXnypMy5eqohbXNra6s8opYUc+FwmD179lzw4+SZgOnpaaanp7nssss2LPSkYNjLLrvsosdVPBW44M7IU1NTF2TDtvEUwGxG56wmLcAvv3470aozrPw7vnsnb/771zztWPk1NTXMzs5y+vRpOjo65EUon88zNjZGKpVi165dJX8jCMKWDMRqa2sxGo14vV48Ho8cqCjZ0D/dIPFTrFarTAquqakhEolgt9uprKykp6cHKC7QL395jra2Ma64wocgwEc/epQrr2xi//4KTCYDBoOB5eXlki4ZICdme71eRFGkr68PKBqFtrS0PLaPSDRK1udD6/Nx6KMfRfngg1BbizgzQ/5v/xbV7CxZQWBPUxMzhQKBQACv1yuPJuvq6taNtAqFAqlUSk5AX7u9UrioFG8hFQYbGeRJXimLi4s0NTWtK4iDwWCJgiqVStHR0UFzczPHjx9ncXERs9lMdNWSQbqg0+l0jIyMMDo6Snl5OW63m1AohMPhoKGhgYqKCm6+uVggvfCFUf71X5f59383cf/9ZTz0kJ29e2flLk4mk0EQBBQKBQaDAZvNxuLioqxya2lpwefzbTjKE0WRQCBAdXV1yT4cGxsjGo2ya9cuBgcH0ev1dHV1cfr0aSJLS8wMTpBVqDCqFLgNOsLhhXN/xhcYkvIvHA7LcUKVlZV0dHQwNDTE8PAwY2NjssmkSqWio6PjWVnkAHJQ79TUFC0tLSXfh1gsRjAYxO12/0UWOY8HW866+kvBs6KjA0UzwGiUgsvFbCxLPCueIdf6fE+5LHojRCIRBgYGEEVRzmIKh8PkcrmLkm/zTIHP52NsbIzLL7+cEydOYDKZ2LVrF2NjY8zPz5cEaIbDYS699FIAHn74YaqqqmhoaCjhLC0uLnLq1Cna2tpkYqc0ZpJQVlYmE3QlxdK+ffvOyV2Ix+OcuusuDn7kI6imp4vEjNtuk52kM7W1nLr5Zva96lUoFApEUSSXy6FUKtd1kNcml0udE4PBQF1dHVVVVRQKBU6dOsXy8rJsWJhIJAiHwxiNRnnE5/V68fp8hLIq+vrK2LNniY7qMlpbzywSoihy/PhxOXnbYrHIXUK3241KpWJ4eLikeyaRki0WCxUVFeTzeUKhkKyCk7o8AN/5zjA+n4oXvzhMPp8DBO65x8auXSaqq4vjIsn4b23AqlqtZt++fUCRm+HxeORwybP319mZUdJtR44coampidraWllir1KpCIo6prTVpFijMCxkaEgGee1z9p3nkfnEkEqlGBgYIBaLodPpUCqV8mito6OD8tUsubXu0A6NBmUiQdJuJxqNlto9eL1Py/PahYbX62V8fBybzYbT6UStVrO4uIjP50Ov19Pd3f0XO9a76FlX23iGwWoFqxUFrLfJf5qMq86GzWbj0KFDBAIBIpEIoihSXV2N0+l80l1Jn06w2+2MjY0xPT0tp4lLZnSBQIDh4WE5ryoUCjE3NyfHFdTX168jZttsNqqrq2VOiUKhoKysTHYEhqIp39LSEoIgUFNTQzgcZmpqio6Ojk23c3FxkWx1NYoHHoDnP/+Mgy5AUxOpX/+a2Py87BMjCMKGo0apiIlGo1RVVcmckbm5OYaHh0kmk2QyGWKxmDzOkxCLxejr62NoaAilUsnocoYZQxN9J3R8/wNW/u7WZSaNcfYPz/C89iIHKZfLEY/H2bFjB0tLS3K448TEhMxLhDNSc4vFwsrKCm63m5aWFvl+t9vNo48+SjabLemqvOxlFkZHR9m9+wB6vZ6HH36Yt79dy8JCAI2mTB7RGAwGWltbGRwclF/j6NGjQLF7WV1dTUtLy4a0AqmDtdY1WHJfrqyslLtG2WyWecHIsH59JEVGUDNqqKU/FKWz8uJ2e6XPOJ/Py8o/QRBIJpOMjo4yMDAgK88kqwNpNJr2+ej90pdIrxaSgiDgKhRofuc7iwae99zzF13sSGKL6elpBgcHAeSRZmNj419skfN4sL0HtvG0hlarpaGh4QnZ1v+lQafTUV1dLXu4SIWLTqeTgyYBeXw1Pj4uhyNuxK8RBIEdO3YUC5Nslnw+TzgcJplMyvt/amoKk8mE2WxmYmICq9XK/Py8zB3ZqBsjjcKEurpiJ0cqcoDMF77A3KpSyOfzoVQqiwvYBlfhUjCmXq8nEAgQCAQwGAy43W5MJhMejwdBEGhoaFg3wjCZTDQ3NzM8PMyiysKosRYQGPhDcZ8N3Ktl52UZjiTVWPwR9jrPGNtJPJZEIiF3ynK5HOl0moGBAbLZLGazGYVCgVKpxOfzyZlc6XSaYDAo86aCwaDM9aqqqsLn89HX14fT6SSfz8v5WJlMBoPBIJNupU5mZWWlfJ/T6cRisZxT6qxUKikvLycQCKwLTJU6o/l8HhGY0m0i3BAEEEX+6E+yy2G6qLYK8/Pzsox+raxd8nF69NFHmZ2dpa2tTb4vF4mQ83rR+Xwc/MhHEP/4RwouFws9PZS/7nUIfj8iIESjf9GFDhQJ25JJY6FQQKvVXjQV2jMR24XONrbxDERrayvpdJpIJPL/s/fe4ZHe5bn/553epSkaSaNeV13bbK9tDHYMsUk4oZoEgtMpCTkQQwiQHEgI4XBMABNyEocS4IeBJIcANhCDQ7ON7bW3Slqtep3eVKb3eX9/jObdnZW0xV7bu+v5XNdetjTtnaL5Pu/zvZ/75vjx4+j1euLxuKQVUSgUFbb4e/bs2dU5uFAosL6+TjablcwBT548yW233XbeY/jFL35BKpXC7Xbj8/mk7oHVaqWtrQ2TyUShUCAyOUnt3XdX3FbxlrcQ/fznYWCAtbU1AoEATcUi3W9/+7az8NXVVaC06JUL3lAoxNzcHPX19dLUWV1dHfF4nFAoRD6fR6fTYbfbqaur4/TUDN/4QReJeOkr79RPVdJ/LY5Sd/CoMc9fvXmCsTEDXV0ygsEgTU1NyOVylpaWcLvd1NTUkEqlyGQyqNVqaRFubW1FLpfj9XoJh8PI5XLsdjvNzc0sLS1JWh444zA9MzMjPbfyFJhGo2F4eBiFQiFleBWLRSlwVKvVSltjuVxOSqTfidbWVsbGxpiamqKrq0sqIMphrzU1NTjjeTLCeQT7gkBKFHDFczsGpl4uwuEwJpNpR++ecnfC7XZXFDo+uRzPffdx/Qc/iGJ5GV71KnjgAZruvhu8XlIOB6nvfhfLFdqxvtwIgnDxgwIvMaqFTpUqVyHlxfLo0aOS8BaQFl+9Xs+pU6dIJBIYDAZmZmYq2/6UtjVWVla2Og9FxsdrUanmsdmsZDIXF5Q4OztLKpWioaGB2tpaaTT75MmTDAwMYI7H0bztbeDxQGcnwQ99CNsf/zGyQoF973kPJz//eVS33IIpEsH+m7+JsOWNxNZZeCQSIZ/PY7PZGBoakh63nGc3MzODVqsln8+zsLDA+vo6CoUClUolTaOZzWZCOSM//hcjqagMBFFK0s6lBP77fh2IAlpTkR6Dlns/0sm998a5/vp1VCoVra2t1NXVSdlH5dHy6667Tio0isUibW1tNO+wqBaLxW3FSHmaKRaLceLECWpra0kmk+h0OpRKJaurq3i9XtLpDOPjtajVHjKZNHV1dUxMTEgTX2q1msbGRlpaWradwdfW1jIwMMDs7CyhUAidTocgCHi9XoxGIwMDAywd2x5rsROJ3PMr5SwUCuedkFSpVNtMEf1+P6bBwdLW6K23btsanf/855HJ5VwZHsZVXkyqhU6VKlcgqVRKytWBko6msbFxm76mv7+fkydPEolEKBQK9PX1kUwmmZubIx6PS87RzzzzDG63W4pbyGaznDx5UjJbO3LEwoc+NMK9905w/fVejhyxAHE+/vFTvPrVSjKZjGSqV0Ymk5FOp9m3b1/FmbjD4WBqaorlX/6Sg+9/PzKPh5TDgfMLX8CnUGD8/OfZ9573ICsU2P/e9zL/iU9g/4d/QLt1Fi575BHUWwVD2RRyJ01WefsumUwCJfF6X1+fNH6cyWRYWFggFAqhMNTwnn/b5N/+0ohzXEGxbNZXEACR1tEcb/lkjNNfLT3uqVN7uPHGI1L3w2KxUCgUiMViyGSyCoGnxWIhGAzS3t6+raApd91282IyGo00NzfjdrtpaGjA5/ORTCZJJBJYrVaefNLEBz4wyN///SQHD6ZZXV3FYDDQ09ODUqlkY2MDp9PJxsYGIyMj24odu92OXq9nenqaeDwu/T4Wi3H69GmM6ovLa9Irn9+pHb1ej8/no1Ao7LjlsrGxse0zkM1mSwLvlpZtW6M88AAqi0X6bFR5afPSdRCqck2TTCaZn5/nyJEjPPPMM0xNTW1bqK9UAoEAR44cwefzoVarUSqVOJ1Ojhw5UpHcDiUNyr59+6SfT58+zfT0NDKZjNHRUaxWq9T6LwuSoeRTVN4WMZvNnDxZWoifeKIBjUbDY4/VAXoOH24jFouRzWbR6/UMDw9jNpul2AGbzbZtu0Emk9HV1UVGpSJvtSJ2dBD8j//Av3XGnt23j+B3v4uoUCDk8/R+8INovV7STU2M3Xcfa2ctaIlEAp1OJ+ldzqUczVBGo9FIGqHyawegEvPUNhZ5+xcjKM8ZFJMroffGLCd/qObRH5da/z/4gZpHHjnIN77Ryn/+Zz3BYJh4PE5LSwvXXXddxXNubm4mlUoxOztbcSyZTIbTp0+jUCjOa2Da0dGB2WzG5/Mhl8ulgiQcDvOLX5T6EY8+esY2oa+vj6amJux2O3v27GF0dJRYLCbFUpxNOp1mYmKCXC5Hd3c3Bw8eZHBwEL1eTzQaRZ3cQFXMlsJrd0TEqJTRYnh+AywbGxslF+dzB4HX19cJh8PbQmFVKlXJtdrlKk3ync3dd5NdXLziIht2IplMSuGtL/Eh6OeNakenyjVHOByWFphy9lI4HCYYDNLZ2Ulra+uLfYi7EovFmJ6epr6+nt7eXunsNpfLMTU1xeTkJNdff31FZ8dgMKDX65HJZLS3t6NSqbbt1SuVSqn1XygU8Hr9fO97FpLJUjL8979fABL86Eca1tZ6OHKktEA89lgdjY2prccp8Bu/sYBSeeaM+2ztydlotVrUdjvuL32Jzro67FYry1sTQ6Ojo6Wz829/G17/euk2Ux/6EBm7HafTic/nw2g0IooiarWaTCbDyZMnpekllUolxV5AaSvPYDAwNjZGbW0tBoOBZDLJ+vo6giBgzCdQFXOsnNKQS1V2Jwo5gZ/+ix4EEfnWqV88Dv/7f2sQxU5qagr8r//VuqvNlMlkoq+vT9oiqq2tpVgssrm5iUKhYHh4+LzbMmWheDgcZmpqhu99z0EiUfpqfvTROum/VusaMpmcRx4J8Zd/KUjbbwqFAqPRKMV0nN1VKvtCHThwQPrMGAwGbDYbCwsLeL1eXm5X8dOQWCp2KjpSpSyuVzbrn/d8N51OR2dnJ0tLS0SjUcn7qKzfslgs2/yCGhoa8Dz9NMUPfhDZ8vI2+4Ked7yD1MMPP6/H/VyIxWIsLCxUnIDp9Xo6Ojqk3Koql4dqoVPlmiKTyTA1NYXVaqW/v18qFLq6ulhZWWFpaQmj0birMPfFxuPxoFarKxLboVSoDAwMcPjwYXw+37YpNIPBQCAQwGAw7DhuvL6+LulzMpkMyaTA5z8/vO16+Tw89VT5J5FUSs6//msHIGAy5XnjGxMUCpu0tbWxurpKMpnkxIkTpFIpybCxubkZnU5XEkPbbNDcTOosF+GNjQ10a2vw/vdXPHb/Jz/J2H33oe7pQavVEg6HyWazJBIJySsjHo9viwcxGAzk83lGR0cJhUL4/X7W1tZQqVSYzWai0ShiocDNVhkP/bK02A/cmuHX7knw8H16ph5VY6orEA3JpPypQqEk7hwZifO5z/kxGrs5HzabjWg0it/vJxxeY3y8luuuU2Iw6CWhtsVi2dVhvmySmEjMnBP8Wbo8nZbz9a+feb/+z//Zfh+/+MUvyOfzFeaawWCQ1tbWbVue5XBcr9dLPSle11HHT1xxEmc1zYxKOa9s1rOn9oXJeWttbUWr1eJ0OqXMsfLUX0tLy7bXrrFQoO6ee5B5POTb2hB/8pPS1NU3v4nljW9E6/WiecMbSpEUV5ggORaLcfLkSXQ6HQMDA5Lvk9vtZnJyssJ3qcpzp1roVLmmKGcT9fX1Vez1l8ePw+Ewbrf7BSt0crkc2Wy2Iln8fGxsbOyYwg6lYsdqtbKxsbGt0HE4HLjd7h0zu0KhkKRfKf+s011cNEuxWNKwDA5G+OhHp1AqBXp6+qivr8fr9ZLL5baS0psoFAoEAgH8fj8tLS3kcjnpzLT8XtTU1OA/ehTH+96HsHUWnv/qV8m95S1ovV723nMPmsOHEVpbKRaLzM/P4/P5iEQitLW1odPpiMfj5HI51tbWpMTqcqTDuSGj8XicY8eOIQgCB5qtvPM3C7TtidJ/RxZBgLd9JsbpHyU52JLhr/7YTjJ55nXTakU++9kT9PScPwIkl8tJmVJ1dXX8+McC73tf35beaR21Wo3P55NciHczWYzFYuh0Bb797QX+9m/7OXxYkBLnywXYhTj7c1MOwtzNSK3cFUun0/S1aOitVW83E72ITk4ul8Pn80lGfuUReLPZfMmOvHV1ddTV1ZHL5SgWi+fNcVKYzciam8kKAsc/9SkyTic4nQiCQPM3v0nnH/5haYLvCnJ8L7OwsIBOp2Pfvn3S34ZWq8VisXD69GkWFhaw2Wwv6Xyqy0m10KlyTbG5ublrwJ8gCNjt9h21DJebVCrF0tIS4XBY6j6YzWba29upOY+nR3mMeDfKDsLnotPp6OrqYnFxkWg0Sn19PXK5nHA4TCgUoq6ujvr6etLpNCsrKygUCh5++GGamjq48cbmigW+vGVx5r7hH/5hnPb2JqmICgaD0vi6wWCgqakJpVJJe3s74+PjOJ1OampqMJlMFItFyVkYt5uBd78bwesl19pK7LvfxSOTEb/vPvbecw9arxduuw0eewxZczPt7e1S8bq6uipNDiUSCVQqFSaTSdItHTt2THKHLS+ycrlc6gD5/X7e/KoGfutOI3PBKNNLK8jyWQ7dnCCd2k8yWfm6J5MCMzMmXv7y8wcEr6yskE6nsVgsBAIBfvKTkuD7scfquP76dUnwnUqlOHr0KAMDAztuTQSDQWQyGUbjBj/9aYG6OjlbwekAqNURvv3tp1CpBFpaWjCbzeTz+a0uUhitVltR3Jf/BtLp9I7HXSgUyGazUgdIJgiXPEKeSCQYHx+XilqVSsXm5iYTExM0NjbS29v7rOIHLiajjpoaZI88gioWY99WR63CGfkyh4teLpLJJJFIhIGBgW3Ca0EQ6Ojo4OjRo6ytrV2RETRXI9VCp8o1xYW+VF8IsV8ymeTkyZPIZDI6OzulCAG3283Y2BjDw8O7JnKbTCbC4fCOEzxlI7/doi9aWlrQbqWBz83NAaWzxO7ubpqamhAEAb/fj0wmo7e3l6mpKR5/PE0yadjx/s48n/KC3yodk9vtRqVSkc/nWV9f5/DhwxgMBrLZrLSw1tbWsr6+zvT0tOT5EhcEsrW1CMD4Zz5DqiyutttxP/AAPW9/O5x1Fl4eo5bL5ezZs0cqampra9nY2CASiUpRDmU/oHA4jNlsxmg04vV6UavVGI1GFhYWWFxcRC6Xk8/nMVOamEomC9z/z15AzitfmeIDH9jkYx9T89RTFk6d6jjvolvWOz30UB1ra3kEoY5HH9UBCR59VCcVNBaLhve+V8XKyhKTk5M7Rpjkcjm0Wi2pVIp///clEomeisszGRMrK3Ze+1obLS0tCIIgOUInEglSqRSpVErqGCmVSiwWCx6Ph4aGhm0FdDnm49lukRSLRU6dOoVSqazQAJWLytnZWakIft7YcnzXwHYPmStsu6pMufDdyTMIkPR25etVee5UC50q1xS1tbWsrq5Kjr1nI4oiwWDweQ8AXFhYQKFQsH//fukYampqsNvtnDp1itnZWQ4dOrRjUdbU1MT4+Dirq6sVwlJRFJmfnyefz2+bPjkbm80mGcqJoih1NMokEgkpKDGdTvOFL5R+f8stYd75zgU++MERPB4dTU1Jvv71EB/7mInHHzdz7JiDd76zdD+5XE4ae+/q6sJut+P3+0kmkxiNRurq6lhZWWFzcxOn04nZbKarq4t0Os3i4iIT996LIpUiW1eHbMuDRq1W03XDDdvOwssC6nJ0gd1ux+v1Mjc3h0wm4/jxOj7wgUH+5V9W6e8/M7GzsbHB5uYmjY2NkkA7nU5LjsDl7KzR0coU8Z/+tPSvzB13BLa9xqIoSmPQmUyGRALuu69/2/WSSfj610v/bzRmee97o5hMJjKZDPPz89hstorOo0ajIRQKMTg4yBe+UBKAv+IV6/zpn67yuc818+STdTz1lI3h4SV8Pl+pcNzSLO3Zs4fFxUV8Pp/kwAzQ3t7OyZMnOXXqFJ2dnRiNRvL5PD6fj6WlJerr6591nMr68jKiy4V5/wGOL3nJyhQ0mE301ploLBTY1Ghwu93bnJlf6pS/E84uSs8mnU5L2WZVLg/VQqfKNUVjYyOrq6tMT08zMDAgLSTFYpHl5WWSySS9vb2X5bHK2wZra2sUi0UMBgNWq5X19XX27Nmz7Yuq3OE5fvw46+vrOyatl7e3VlZWCIVC2Gw2qUAr51pdzMK0m/27XC6XvEVaW1v5gz9IMjCwyMte5tpKNp/hZz+z8yu/EkQmi3LvvVoefbQRvT7MU0/NoNFopKBKlUrNL34hcvvtazQ1NVUs2qIoSl/k/f39TE9PS4Joc3t7KXdpSzhrs9nOxCWccxZeFlCXn3M2m2V+fl4SJz/1VKnoe/rpJn77t62cPHmShoYG0uk0iUSCnp4eaZHVaDRSd2FjY0NyJT4fjY1L5HJmlEolyWQSp9NJMBikWCxKU30Xo3f68pePEYnoUKlUyGQyNjc3CQaDFUVrOYk6Go3yzne2cvPNm7zylWvIZEb+4z9y3H//FN3dSkZGRgiHwxSLRex2Ow0NDSiVSgKBwLZtKpPJxPDwMDMzMxw/fhyFQiEVwY2NjfT09Jx7qBdHJIL2DW9gOLzGt774PdYdHaXfJ3PYjp/kd/7kTXRbLTz9N39DNpu9KH3aSwW9Xo9Op8Plcu2oY3K73cjl8h2/H6o8O6qFTpVrCpVKxdDQEJOTkxw+fFgaL19bWyOTydDd3X1ZOjrxeFzyJzGbzajVaoLBoJQ/tZsOp5yNVC4WdqKs4/F4PHi9XgRBwGw2Mzg4uGu7+2IpFxWRSISamhpe9Sodr3pVF+vrZtxuN8PD64yOxqmrq8Nub8NisXDokEA6bScYDJJMJsnn82SzWZ54wsAHP9jKvfdOcOONiwwMDGC1Wkmn09LIbEtLC8vLy2xubjI0NITVapWchA8fPkw2m5VS0mdnZxkYGKjIyirfT6FQIJ/Ps7Li5Lvfbdwav67hkUdKr8d3viOjq0vP+no/EOFDH2pkamqSdDq941mzyWRCLpfz3//93+TzeRQKBU1NTWxublZEaeRyORYXF6VOm1wup3VLKL2xsUEgUOr4PPzwwzQ3d3L99Y2k02eKTK22yH/8x5MYjRkyGTmpdJq40kBaVctp3zq1ZjO6rePTaDTSNFt9fZq3vrURlaqJ9fV1VlaWeeUrc7S2tmKxWLZtfYqiSDqd3rEILr2Hh1hfXyeZTCKXy7HZbKjV6oqMsrMXXFEU2dzcJJ1Oo1QqpeT6MhtOJ8rwGgavh7ve9Wa+9cUHiTU0YfR7eOPb34DKs0q6WERxns/5c6FQKEgmmeXC4WpBEAQ6OzuZnJxkamqK9vZ29Ho96XQat9uN2+2uhnFeZqqvZJUrivIXbDlpuaamBovFckmtb4vFwvXXX4/X62V9fR1RFDGbzTQ1NT3nQgFKX7ITExOoVCr2798vaQOKxSIzMzMEg0HC4fCOfj3lSZgLBe6ZzebnZTLMarViMBg4ffo0/f391NbW4vF4pOBPKG3/hcNhwuEwQ0NDmM1mNBoNzc3N0gRTV1cXn/pU6etjfLybO+6YZ3JykuHhYZaXl6X8KYVCgd/vp62trUKAW85tUqvVhEIh9uzZw+zsLE8//bQ0dba2tkYikaChoYFQKMSRI0eIRIp89as3EIspAZHyy5hIwEc/CqJow2is4d3v3jj3qVcgl8sls8HyNFswGJRG0hNbKmCZTEYgEJBCRXt7e5mZmZHE0AqFgmw2i1ar5Ze/zJBOV044pVIQCnVgNPpwZxWs6LvJys4Ifk9NbXJLXYLrWkuvTXmbzel0SkWUIAjSaxcIBGhra9v2+VlbWyOdTu+qt5HJZBWvfzqdZm5ujkAgIG3D1dfX09raSiKRYH5+vqI7VBaalztiy/k8x7/0EG96xxsxu1d46ztexw8//k+85iPvxuxZZaOpje/8y3cYsuQv2bRvc3MTl8uNM54lixyzXstISx0Ws5lCocDs7CzBYIixsRpGRzcRhNJntre396opeGw2GwMDA8zPz3P06FFkMpn0vdDR0XFJXl9lC4aSkN1YndTagWqhU+WKIZVKMTk5KS0iAE6nE61Wy+DgoGQWdzFoNBo6Ozsr9AqXi2AwSDabZe/evRUCSJlMRl9fH6FQCJfLJQlGz6bcoXmx2tKCIDA8PMzk5CTj4+MolcqK8M+hoSFsNhv5fJ7Tp08zOTnJDTfcgEqlIhgM881v1mIytZJMJnnssdKi/tBDKrRaI2BErw/zhjckaWtrwePxEAqFKBaL25yB8/k88XicpqYm4vE4MpmMgwcP4vF4pG0Zk8lEd3c3ZrOZlpYWTp06hVab5UtfOsbf/d0Ak5Mmaey6WJQBIgcOpPmLvzhJNluLWq1Go9FInaHy/er1eqxWK4lEQjIjXFtbQ6PRUCgUSCQSWCwW1tfXpW2eVCrF0NAQp0+fBkqmh7W1tQiCwMLCAm63m1/+shY4o3e6//4unnyyjp/+VMeb/sTEnK7l7GE2ALIyBT8Li2g1cYbsBgRBoKmpCYfDQSwWo1gsotPpJBfg48ePMzExQXd3N0ajkUKhQCgUYn5+HrPZfN6JvjLJZJKxsTFEUaSpqQmDwUAikcDn80mFj9lspr+/H6PRKAnp5+fnJa2UK55nrbGDb33pId76jtdhdq9w9+//OgAbze1Sh0dRk72kkxS3282RlSCrOgcZzdbyVIATSymuM8QRQqvk83mOHas7KxojTCKR4OTJkxw4cOCqCba02+3YbDapSC1v415sJycbCrFy6hReuZyITEdOpkArExlotNIulyGYTFfcxNmLRbXQqXJFkM/nGR8fB84sIgDRaJS5uTnGx8e57rrrnhdL93Q6TSAQIJPJoFKpqK+v39XrBEr6DpPJtOPZo0wmo66ujmAwyPz8vHSGns/n8Xq9rKys0NLS8rxb0yeTSWKxGIIgUFtbW/F4arWa/fv3s7m5yczMDJlMBr1ej0KhwOPxkM/nMRqNtLa28swzz+D3+2ltbcXlWudrX+smGlUAaqmbkkrJJFNBozHHHXcEWFlZQRAEaUrq7LNMURRZWVmRCiCXy4Uoiuj1+l31UxqNhkwms+WO6+NHP8rQ01Os2CbSaIp85jMn0OtVBAIBOjs7yefzTE5OEolEUKlUKJVKKeyzrHFxuVxoNBpMJpP0/huNRg4fPoxOp5OeQzqdJhcOc6C3l6wg4NzybKmpqcHtdnPrwAI97w/zqtcmkckEPv7x0/zsZ3bq69OsaBu2ipxzF/2ST9HPvEkG6s44EAuCsM3/Rq/XMzo6ytTUFMePH0cul1MoFBkbq+FlL9PR399/UUXF3Nwccrmcffv2VXwuHA4HTz/9NHK5nOHhYek90+v17NmzB0EQWF5epra2lpystHTEGpr44cf/SSpyAH748X8i1lDq/GhrLy5SUxRF1tfXObISZE7fsu11ysqUPJlQ0ouO4SYjDzxQ0hZNTw/w+tcv43K5UCgUrK6uSnluVwPl74tLJb+2RvZXfoWmjU2e+NfvE7S3SJd5Ti9z97vehLbZAT/+cbXYoVroVLlCKAspb7jhhooio6amhtHRUZ5++mm8Xu82o7zngiiKLC0t4XK5kMvlaDQayWemubmZrq6uHReOC3nd1NbWEgwG8fv9Ul5VecuqqanpeekylUmn08zOzlZkYgmCQH19PT09PdKWR3khzWQy3Hnnnee9z7GxMVpbW9FocnzrW1N88INtnD69vZtSNhVsbDRg34pyKI/Injx5Ugq2LG8pdnV1SRESu5nalclms4iiiM1mI51O89BDPtLpym2adFrOxISG4eEodrud5uZmxsfHSSQSFfqgTCbD3NycZDgIpS29s4W5xWKRfD5fkZi9trTE/r/8S2Tr60x/9rPktyIJCoUC6mCQ3/3C+8jW1DB+673kDAYEAV75yiARuZ5p2XkKW0EgJQq44rkL+tiU/x7GxsbIZrMcPWrjL/5iiHvvnSCXO87g4OB5X8tEIsHm5iatra2k02lcLhehUEga/y8L1Y8dO4Zer6exsVESzLa2tuL1eonFYmiE0uti9Ht4zUfeXfEYr/nIu6WOjkF5xvdpp7+lYrGIy+UqJbVnMqwYe8+1cdq6nsCT38zz81gj1zfo+fa3S1uL//mf0NRUTyAABoPA//gfbnp6eq757Rvf3Bzm9U30Xjev/6M3VGik7nrXXWjdTjJyGepYrFroUC10qlwhhEIhrFbrjp0UlUqF3W6XEqIvF06nE5fLRUdHB83NzVtnyAU8Hg9LS0soFArp8fL5PMFgkHg8TjabJRqNkslkdpwmCYfDGI1GRkZGCAaDZDIZFAoFdrv9eW2rlx16RVGkr68Pm81GsVgkEAiwvLxMJpNhZGREWnDKXjsXi16vx2Bwcf/9KX71Vw9uE90+8ICLaDRLJFJKOjcYDCiVSuLxuLQtWb6fsu39yZMnsVgs5+2gQeVI7uDgIJ/7XMlf55Zbwrz73Sv84z+28eSTdTzzTD1veUsrVquVSCRCJBJheHi4YqtQrVYzODjIE088IQWd+v1+6urqpE5ieQosGo1K+ol0KIRsbQ2N18t1f/EXyB9/HFpamP7v/6bjnnvQeL2Iosh1fX0ktvQk8/Pz5C7yazaRu7DHUz6fZ2JiQurIfP3rpaLm9Ol+XvnKU0xMTHDw4MFdP2dl7dFuaeplTpw4QTKZZGJiArvdTn9/vxSYms/n6bWZ8M6vcNe77sLsXmGjuf2MRse9wlvf/lq+9+Xv4ctmWU6lpM5FS0uLtAVdLBY5ffo06+vrNDQ0sLSZqtAvnU0uJfDwfaXC8idn/T4ahY9/vPT/RmOW228vdSSvhjDP54JbEHjkXx/ijW/fQSPlLmmkvvsv3+H3m5qqyd1UC50qVwj5fP68i51ard4xvfrZUigUcLlcNDc309bWJv2+PFWTzWYlnc3GxgbT09PShEcul0MURY4ePcqBAwcqjtvn87G+vk5fXx9KpfL5NUs7B4/HQyQSkY6p3E2xWCyIosjp06dpbm6WJqPOnhg6daqRD36wh49//BS/+qsyVCqVZOlfXvwbGxtxOp2cOqWtKHIAUik5TzyR5YYbtCSTSXQ6HQcOHCCXy3H48GFkMhmFQkFyp15fX2dmZkbK9boQCoUCm82Gx+OhsbGRP/ojOy97WYrbbotRLNbyL/8S5N//PcSv/EoXNlup+AyFQqjV6h3NGWUyGfX19ZLrskwmY2xsDKPRiCAIkk9Q2ZgQIGW1MlZ2cF5dJXPzzazddx8d730vWq+XlMPBzP33M9zeTmhhAb/fD4BSnr+o90+vvPC2k88X4Otf11Bb287DDyv4z/8sdWAefBBaWrrxeNz89KcxPvpRDTs1NS6206FSqdi7dy/BYJDp6Wl0Oh12u13yPGrI52l65+vRe9xsNLdJHYVvffFB3vr212L2rPLmP/wfeB/4Osb+fjKZDH6/n1AoxNDQEBaLhWAwyNramlSIzh2b2vV41PoLF4Ff/vIx9PriNT+tJIoiwZyccH1r6fXeTSNV33RRXcKXAtf2J6LKVYNWqyUSiSCK4o4t7s3NzQue9V8Km5ub5zXfK2dHeTwelpeXsVqtdHd3S+JWp9PJ8vIyR44cobm5GYVCwdraGtFolMbGxm3i2xeCQCBwwW2oyclJrFar5CFTFt0eP94F6JmeHuXlLz8q6VlUKpXk4KvVatHpdJLo9tWvTvPhD6/z4Q8refLJOk6caGZ0dEbaHhIEQZpMamhooFgs4vF4WF1dRa1W09bWhsPhuGhjtPb2dk6cOMH4+DgDAx3cdFMt2awDr9dLOBzid37HQW/vmQ5boVA4b1aSxWKRCp1cLodKpSIej0uJ6eUgWChNwUUiETJ2O6c+/3lG3vteNG43jrvuAiDlcDB2331kTCaOHz8ueceo1Wr6m1tYdGXJCspz0sG3EEUMShkthgu/Di7XOvffv2/b76NR+MQnSv9vMmV5//t3jniqra1FJpPx8MMP09/fT11dHdFolLGxMQYGBlhcXCSTybCxsYEoitTX1xOJRHC73SSTSRQKBVarFblajby5iZRMxrfv/09JkxNraOI7X/ouv/VHr0XT1EjvgQPS1klLSwunT59mamqKG2+8Ea/Xi9lslrptNqMOkrs/9489uUI+B39/p4V0+kzBptPBz342Qzodw26vv+a3rQRBoKgsfc4vpJG6mC7hS4FqoVPlisDhcDA+Po7f798SnJ4hHA5L2TCXi3J3aLcWd/n3oVAIjUZT4e9STn5Wq9XMzMxIi6XBYGBwcBCbzfaiOMFms9mLuo4oioRCa3zvew7q6rrZ3Izwwx+Wisgf/EBFbW03mUwavV7He9+rqtiea2tr46abPPT0JLntNj+FQmnr4MiRLkZGaqSppnI3KZ1Ok8vlkMvlkrZJrVbT2dmJ1Wq9pEXJYDAwOjrK7OysJFyHUpeipaVlm/ZJr9cTCATIZrM7vs/lbCm1WsPhwypGRzfRajWSOLTsRK3RaBgeHuaZZ55BJpORtFqZ/8hHGH7Xu6T7mv7whxGbm5Hl86RSKWmaK5PJEJ+Zpk9vY4I6EMXKYkcUQYBXtRguKkBTo8ld8Dpf/eoYRuN1klWD3+8nk8mgVCppaGiQ8scUCgVarZa1tTUMBgMKhUIa+8/n83g8Hurr6zEYDHi9XoLBIHv27CnpvLZyprSxGL/f0MDKZpqUKGBSK3AnU4T+/Vt0jIxU6EPkcjk9PT0888wzhEIhkskkLS1nRLQjLXYOT0fIyhRsF22DSqMjNC2QTldWcMkkHD0qMDoqq+jOXsvU15qYTV1YI3UxXcKXAtVCp8oVQW1tLY2NjczOzrK5uYndbkcQBEKhEH6/H5vNdlkD7soTUxsbGzve7+bmJlBKlO7s7NxxQa6vr8fpdGIymaRk8BcTlUrFsWPHdjwWURQ5ceIEarWaVCpFNFrgq1/tIBaTIQhmZLLSmV8yKeOf/7mR8gTVRz9aeUZYV1fHwYNLZDJROjo6qK+vZ2ZmhltucSEIbjIZJBPF8nSVIAisrKxInZvy6LrBYGBkZOSi9RTlxXlwcJBsNisFhVoslh27QvX19SwtLbG0tCRNDZWZm5sjFAohl8uZmHBwzz3NUtp4eYKn7CfU1NSETCZDo9GURLmCQO3f/m3FYw3//d8z9U//RKy2lmKxKE2yFQoFGhsb8Xg89MtyLCrtpc7OFmoK/FqHmT21F+ccrNPp+PnPf87o6HW0tAgkk2dfBj/60QRGo4JiscjU1BThcBidTofBYCCZTHLq1CnpeSwsLLC6uiptK87Pz9PQ0IDRaGR+fp7FxUUWFxel+29vb688CdnKmVICPbaS7iadTrOSy2EaHt5RBFvuCsZiMeRyeUVxrtfpeLk9yU9DIrBzQej+eWkb8GUvC/Gudy1KI/yHD9fxO7/TddX46DxX9rbVM/nz09z1zjeVfIvO1Ui947V8/6s/oGVv1V0ZqOqUqlwZCIJAb28v3d3dRCIRTp0qCSvX1tZob29nYGDgsnZJDAYDJpOJlZWVCh8ZKC3Ey8vLkrngbgtxeZJqY2ODubk5yZzwxaKhoYFEIoEgCOj1+op/5fyc8haSTlfggQcmGRmJAaI0QVUoCAgCDA5G+OY3T2O1Vj53mUzG3r17pVHjp59+mkgkQjabJZvNSkGTZrOZqakp/H4/oijS0dHB4OAgxWKRPXv2sG/fPjKZjORLcz7K8R2HDx/m6NGjHD16lJmZGQqFAna7fdetL5VKxZ49e/D7/Zw8eRKfz0c4HGZiYgKv1ysZPv7Xf5W6WY89dqbgzefzklDZ5XIRCARobGwkNTdH3ZvfjNbrJd/ayvSXv0y2pQWl00nvO9+JfOt+ofSZTqfTZLNZ9u3bh11McnPBxUjGxW1W6I8v85Ym2UUXOVDSSQmCwKOPJkkm9cCZf8mknvFxNQ6Hg+XlZdbW1hgYGOC6665jYGCAAwcOMDIyInX1ent7aWhokLaEe3t76evrI5PJIJPJ2LdvH4ODg9jtduRyeUX3Bc5kfp39mS+fEJTdrs+l7MRcFieXg0XLHGyx8ZoWLVpZseJ2BqWM13eY+JPfM/GpT3n4+MenaGpKc++983zmM37e9S7HRXkIXSvo1tb43XffJZkzfuuLD+IZvZ5vffFBNprbMLtXecvbX4tsy6n9pY4gvpjfzFcA0WhUys250IhrlReGsp29KIrSpMfzQTweZ2xsDLlcTlNTE3q9nmQyKXnJ7N27l8nJSWpqaujvrwxtLLsJl/Uc5VgHg8FAb28vBoPhBdcK5PN5Tpw4QT6fp729XZq68vv9rK6uYrFYGBoaolAo8NRTT211GkK8+tU3nONHU+AHP3iCgYGeXTVM0WiUiYkJ8vk8Op0OuVwujYqXKUcMKBQKuru7mZycpFgscvDgQQRBIBwOMzU1xc0337zr316xWGRycpKNjQ0cDoeU/RUIBKTio7e397xF8Pr6Ok6nU+rSiaLAgw9aMRia8fsD/Nu/NZBKKTAaRd74RhfFYoHaWhW/8RteTp2qldx3e7RabG96E2q3m5TDQeTBB5lNJjHH4/S84x2SIHnsc58jU1eHQqGQigGZTIbVaiUUCkl5U+X341IL+IWFBT7yERX//u+t/NqvZfibv0nw4Q8r+dnPjPz+74f4whdqefrppzGbzXR0dGy7vdvtZmlpCbPZzN69e1Gr1Rw/fpxCoUBHRwczMzM4HA66u7vZ2Njg1KlTNDU1SZNaZaG+z+eTipayq7JWq+X48eMIgoDRaCQajUpeTg6HQ5rkKj9ueYx9z5496PV6ydxxemaGiExLc2cvRrWcFoNy29bebnq+lwSRCNx5J1l/gG9+4XsE6s4MPTSu+XjL21+LqqH+mvfRudj1u1roVAudlzTJZFIK0Cx/cdbV1dHe3o5Op5NEx2ebGIbDYSYnJ9Hr9SQSCW7o62PT5WIplyNcUEoOpf0NFsmhNCoIrK2tIYoiBoNByuC63GSzWebm5qRuBJTOshsbG+nq6pIec2ZmZks8PcKv/dp21eo//dM473rX8HmPMZfL4ff7pU6W0WjEbDbjcrnY2NiQfIluu+228x7z0tLSjgsylMa8Z2ZmGBkZ2TY9VU4x37t370Xll+VyOQqFAj//+VF+/ddfft7rlgS9s/z1Xw9JW1ryeJybP/5x8j4fxz/9aTJnxS2og0H23nMP2dpaJu69l4LBQF9fH/X19SwsLODdGj2HM5qisp6k7LlU1hI1NDRIMRg7IYoi3//+GhMTESmMVaVSc+xYD/v2WRgc3GRiYuKCr/svf/lLisUidXV1yOVyfD4foihKponxeJyNjQ3MZjNDQ0NSWvvJkyfJ5/M0NDRgMBhIpVL4fD6KxSJ79+7F5/Ph8XgqYifKwbfl6I19+/ZJ022Tk5NSjMbZ235DQ0OXdQDhmiMSgViMYlNpuiqRE9ErhVJR6PGU1OjXcJEDF79+VzU6VV7S6HQ6BgYGKBQK5HI5lEplRY5QU1MTa2trTExMUF9fj9VqZXFxEblcTiKRoLe+HuHVr8YYDDH95e8TbjiTUeOZWuFt73oDRXMtE//7fyMzm1EoFLhcLhYWFhgYGLjseVblUNN0Oi05I9fU1Gzb3uns7CQSifCNb0QAI7/2axk+/OF1/tf/0vDYY2ZmZnovWIgplUpaWlq2bWmYzWY2NjZwOp3b0rR34nznWl6vF41Gg1qtZmNjg2g0KhVV5S82n893UYVO+b29mLTx7353mf/7f0vdrKeeauT669cpGAyM33svTSYTuXgctswEGxoaaLvhBlbMZsKZDIUtnxin04nBYJCE60tLSwCMjIxQW1sreeJEo1Fqa2uljK2ZmRm8Xi8jIyM7jkoLgsBrX2vjN37DSjbbLHUVb7qp1N1YW7u4c9f29nYKhYK0fWQwGFCr1SQSCQKBAFqtlr6+voqiqxwDca5XT3NzM2NjY5w+fVrqbMbjcdbX1zEajajVaikQ9uxEeZPJxKFDhwiHw1L3p5zz9pLt1lwsWxopGWwfIW9uflEO6UqlWuhUqUJpImSnoE25XM7IyIjk3lqesNJqtXR3d6MKBskHQxi8Ht74jjducyjVuV0kiiIDLS2Yt2z1k8kk8/PznDp1igMHDqDX6y/b8ygWi4RCISKRKEeP6rjjDs2Oi6VKpWLfvn38j/8RoKtrhttu85PPw+c/b+XoUTV9fc9e1CkIAhaLhZqaGg4fPsz4+PiOBnXxeJwTJ06cN2g1lUrxspe97LyPd+zYsYs+tnLw4eHDh4lG07z2tQcqRpUViiK/9Vur/Nd/WfnpT0tnwz/7qRmbrQ0Q0evzvPa1XlQqBcpAAMFkor6+viScV6spnlVQJpPJimOTyWRSUC2UioZEIsG+ffsq9CWRSISJiQnm5ubOO2koCMKOhpVlQ77Z2dkdfZyCwSAzMzPU1tZKhdjFkMlkCIfD9Pb2bjMkVCqVdHV1MTExgVKpZP/+/WQyGXw+H8lkEqPRSFtbmyQCP/s9l8lk2O32XQNJryoiEcRolHW9ntlAhGQRzDo1w811qAKBl0SX5UqkWuhUuWREUbxgDMK1hFwup729nba2NmKxGCdOnKC7uxur1cp0MMQvv/Qgd73zrh0cSlfYaGrj21/4Nj0bG+iPHcPhcOBwOBgaGuLIkSO4XK7LNrF19jbA2Fgj99zTxL33TnDrrYsMDw9v2wZQqVT81m+1UCwWyeU6kMvlKBQKRkae23Gsra3hdrslo73yWX17e7t0lp7P55mbm6O2tva8AacXY/52oST4c2lubmZ6eprl5bpto8r5PHzjG0OAiHxrEi2VgK/8azvi1iTa7/wOZBfH2HvPPeQtFsY++Umpi1OmpaUFl8sldTbK7XWFQiH5DAWDQbq6uraJaGtqaujo6JA8bXYqZs6HWq2mrq6OUCgkac/KlI0iGxsbLykkF864Ku9kwAhI3Um9Xi+NqZ878r++vl4RT3JNEYlQvOMOUm4v3/nCd1h3bG3HZuH41Di/8ydvQuNovOZ1M1ci1UKnysURiRDzelktFFnaTJIVFBiUMvobLLQgIttqo17LCIIgxRqsr69jtVrxpousN7af36G0oYlaSwFVPMzCwgKbm5sMDg5KTsPnjj4/G9LpNOPj41Lw4wMPlBa3yck+XvGKk4yPj3Pw4EGpcDg7f6jsbXM5cDqdUnzG2ayurkpZZWWX3EKhwMjISMWkzrmaH61Wy8MPPyxtoZzNysoKTqeTSCTCE088gdlsprm5+YLTN3a7nWg0yhe+UHrOt922yR/+4Yw0qtzQUMDvl1Eolo6rgAIBkeHeMB//lJMD9jqyr/9zVF4vBZWKnoYGZuJxdDqdlPztcrkAJD+hSCSCRqORis3yFtxuXQy73c7CwgKRSORZdTp6enoYGxvj2LFj2O12abw8EAigVCqfVXFdfp9yudyOERPl6anznQBdy9tRYjRKyu1F73Fx17veXNndfeeb0HhWSSOgqeZPveBUC50qFyYSIXf77Qg+P4e/9BBrjWeEo85TJR2KtrkJ4SVwplIW9rrdburr68kJShAv7FCqNtYy0FYvCZnLYZ9nh0Y+F1wuD9/7ngOzuZ0f/UjOf/5n6fff/76Kzs59uN1ufv7zOO98p4jb7WI1liErKKjRKBl02GhsqH/Oi1A8HmdpaUnaBmxvb8dsNpNOp5mbmyOTyTA/P49CoZByj8q+J7FYjImJCcmDRy6X4/F4KBQKkqmdxWKRdDnT09OEQiG0Wi0KhYKmpiYCgQAnT56kt7d312kxKC223d3dvO1tEXp7Z7n1Vh+CAJ/5zDI/+EGIhoYiH/hAf8Ukmo4ET8QOkMh/Fm69C5XLRcrhYOULX0BtsaDMZOju7mZiYoJCoYDD4ZCcfwVBkEJry1t4z/cMSHl03uv14vf7CYfDKJVKWltbcTgczyoLymQyoVQq8fl86HQ6AoEA4XBYMt8sd3zW19dZWFigubm5oiAqFAqsra1dG1tUOxDSaHnwC9/hrne9eXt3d2sM/Nv//P94eTxBb7H4kumIXwlUC50qFyS/sUHWF8Dg9fCmd75pRx1KShDQvkTOVNra2tjc3GRsbAylsTRVcrEOpTabrdQJ8nrR6/VotdrLcpbrdK7xla8cIBKRIwhIOUfxOPzt36oQxU5MpjxtBycJ2hrI6M/86Z/yZtm7vsxtAx3P6Vi8Xi8ymQyZTMb+/fulLpFer+fGG2/kqaeeIpvNMjg4iFqtlrobZVGuRqPhwIED0uKYz+d55plnyOVy5HI5Tp48iUqlolAolBLDt7ZoAoGAtLU4Pz/P3NwcNTU159U+iaLI0FCEmpoQZRuXVCrJK1+Z5NSpmm1ZXgkMnPI1c/Ob3lS6fWcnE/feS06nw741Yj07OwuU3LTLlL10oJSQXp5CKnedyttL51K+j+cyCapQKGhtbaW1tfXCV74IZDIZzc3NLC8vEwwGyefz1NbWkkgkpG6OUqkkl8vh9XoJBAKMjo5iMBgoFoulgNNc7gXNf3shmQ1GWHd0XLC7OxtaplCYZnBw8EU+4pcO1ZKyygXxyhV884vfY6O5XTpTaRo/Iv0xbzS38Y1/+Q6F85xFX0vI5XJGR0dpbW1Fk9rE4l0uBRlupTg/8NX/OvNavf211AVcFTlGFouFeDxOMBjcFnfxbNFocvzXf3m56abSz+X80/J/9+5N8PdfmcZV10RGqDy/ycqUHMkYOeoM8WzJ5XLSCLHZbN7WMShPtAGMj49z5MgRjh49it/vJxAIkMvlGBwcrOgAKBQKTCYTgiBgMpkYHh6msbERlUqFRqPhhhtuqIh3KHdqlEolXq9312MVRZGZmZkKU8jW1lbpsQ8fLmmGXvayEN/4xtPcfHPpdfk+vyHdh/DAA9DSIhkLZjIZVCoVnZ2dFc8hEAhICehnm16Wi7Tl5eVt/kOxWIzl5WVp7NvlcnHy5EmOHz/OzMyMFDh6ITY2Njh9+jTPPPMMR48elRLsnwvNzc3I5XLy+TwKhYJUKiUVOTqdjlwuR319PcVikXw+z9jYGAsLCzzzzDP4/X76+vquWffi1NbfWrm7ezZnd3dtjhZCodBFv49VnjtVH52qj84F+eXpRZ7M1mD0e6TipszZZypvbtfTaX5p+V6ILhfZW16OerUkPP7Wlx6Sul3lFOe4ownX176Kbe9e5HI5KysrRKNRTCYTo6Ojlyym3YmTJ08iCAIDA3uxWGBrFwEAvV7k+z94kjFTF1nZbsGRIhoKvGdv/UVlLkm3EkWWlpZwu90V2zEajYY9e/ZgNpvJ5/OcPHmSZDKJKIrYbDYaGxslp2KtVotGo2F0dHTb/YdCIU6fPo1MJuPlLy953zz11FM0NDTQ0NDA0aNH6ezsrBhxn56eJplMcuDAgR2PeW1tjVOnTkkTTVNTpdTsssHh8eMagkEtv/EbCRKJOKpAkKU/fYKO8HFu5ikACu3tHLn3Xhquuw6n01nx3E0mE52dneh0OmZnZ1lbW6OpqYmenp6K48jlcoyPjxOPx7FYLJIv0/r6OgaDge7ubk6fPk0+n8dqtaJQKNjY2CCTydDW1rar91D5PXG5XOh0OiwWC/l8XuoSjYyMPGsX4fL7MTAwQDQaxePxoNfrJZPMiYkJisUiXV1dLC8vs7m5iVKpxGq10tTUdN4Ju6udZ+Zd/CKuveD35Fu6THhPH8dms237TFS5NC52/a52dKpckKxQWogvdKaSvLA9yTWHYDKhbmwg297Bg195qCLF+aGvPkS2vQNVYwMphYLTp09Lvik6ne6yFTlQCkXd3Nzkv/97s6LIAUgkBI5MW89T5AAIpFHgil84NPJsFhYWcLlctLW1ScVGY2MjGo1Geq5lP53ytpZer8dqtTI0NERrayupVGrX+7darWg0GorFIi6XS3LMLidua7XabV2xYrG44xZcOp1mZWWFubk5afppcXFR6hjdcMMN3HTTTdx0k8iv/mqYZDKBJhRi3/vu4W3hf+SmTj+Fxx8n39aGfGWF/e97H9pwuEJUrNVqS9qtXI7V1VVpwminbTSlUsm+ffvo7e2VCpF8Pk9vby+jo6NMT0+jVqs5dOgQQ0ND9PX1cejQITo6OlhdXa3YIjubUCiEy+Wiq6uL6667ju7ubum2BoOByclJSVdzqWxsbKDT6bDb7dTX1yOKIj09PZhMJskhORqNsrGxQaFQZGysFrVaQ3Nz8zVd5ACMtNRh8ZZypnbr7tqDLlqMSrRa7bbomSrPH9VCp8oFsdeUxlB306EY/aU8FaP68izaVxU1NfDjH6P65eP87qtGeEu3ide06tmb89BnSpP90cOofvYz9t16KwcOHJBGcE0mE16v96IM9S4Gu92OzWbjm98stcN/7dcyPPPMGrfdFgHgyNO2i7qfRO7iG7zpdBqPx0NXVxft7e20trZKwtuurlLA4vLyMj6fD4WiFDRZLBYrxKjl22xubu6YjySTyVCpVCgUChYXFzn89NOECioe+qWeDUFLT29vxYRXeQvt3BFol8vF008/jcvlIpfLIYoip0+fJpPJ0N7eTjQaZWpqilgsRm1tbelxg0FG/+zPpGiHI/feyxPFIkc/9SnSTU2oPR5qXvc61KEQwWAQs9mMRqNhfn6e06dPEwwGaW5uRhCEXQsLuVyOw+Fg//79HDp0iP379+NwOFhfXyeTydDf318xEScIAm1tbdTW1kqTXVDq4sRiMZaWlpiZmQFKjtPj4+OSS7ZSqaS/v59cLkcgELjo9/lszraVKBeTZwvqy1tjKysrPPOMmXvu2cujj5aiHpxO57N6zKsFbTjM7/zxmzC7d8ifamrD7Fnlbe96I7hcJBKJyzbpWOXCVMXIVS7IQKOFp8dP8qZ3vHHnpNy3v5YHv/LQSzcpdweH0i5dLxMTExzz+9HHYggyGZ5kkZxMgVKuR7m+TjAYZHFxUcoVei5TGKVtqwHe9KYgfX3zvPzlHpJJ+D//R8/Ro91o6gQuRoFTFk1fDMFgUJpCA6Sx5enpaY4fP45KpZImccrHWF9fX9HdUCgUGAwGYrEYCwsL20btvV4v0WgUuVxOVGNhSV3P+JMavvaeGn7vHyPMqpLc3iQw2lBDNptlamoKQRAqujzl17m5uZn29nZOnTqFXC4nl8sRj8fZ3NxkYGCAhYUFjh8/Lt1OqdeT2ypect//Po4tvdC62czYffdx4P3vR1FfT16rxW63s76+jkaj4cYbb0QQBFKpFJFIBFEUdw0e3Y2NjQ0MBsOugur6+npmZ2cpFArEYjHJfLBMOTQzlUoxOTkpbXVpNBpMJhObm5vnnUzbDaPRiM/nI5VKodPpUKvVBAIBaYuynIZ+ww038KUvlQqgiYle3vAGHUtLS1I375rEaETT1EhaEPj2/d+u6O5+78vf421//EZUDfW4YzFyudxl0+dVuTDVQqfKBZF7vfzun9yF6qyk3FhDU2m6YEuH8tvvfD2yXz5etR7fQqvVct111xEKhTi6GmIOC1nDGYGuqpjjlmYFDUJaigbo7e19To8pk8l44xsbeMMb6slmS5M2KpWK668XyOZy/N+JMFlBATtpcEQRw1ZOzsWSy+VQq9UVHZX6+noUCgXT09Nks9mK6zc0NGzTJIiiSC6Xo7a2Fr/fTyQSob6+HplMxtraGpFIBJVKxbrSxJSiAYDJn5bOhCd/pmbPTVl+5M0SCMyj2vBIWWXhcBi73Y5CocDpdGKxWOjq6kIQBOx2O/Pz8xgMBoxGIxsbG3R2dnLo0CGCwSCzs7PU1dWh1+s5/elPc+PQEKbmZkzA5uYmCwsL9L/85SifegqMRgxLSySTSUZGRjh58iQul4vNzU3i8bj0POfm5kilUhWmiefjQoGV5csikQinTp2SBL7Nzc243W5p/Luvrw+r1cry8jJms/miojLOh91uZ2lpibm5OYaGhmhubmZxcXErwDPOd7/biFJp4yc/EXnwwdJn6fvfV9Hb24HXq+aRR1J84hNnpgKvKba6u5pYjN+pq+MXY9NkkNNit9Lf10f2Rw/jTCRwh0I0Nzdfs6LsK5FqoVPlwhiNqBrryQrw4Be+S6zubB3K93nrO15XSsq9xvfgLxWZTMZkKM6kon7bZVmZgp+F4Y4GA52dnSwuLlZM/jwXdooGUCmV3N6k40feLIhiZbEjiiDAq1qMlyREVqvVpNPpisknKOlqbr75ZmZnZ/H7/ej1evL5/I5dq7W1NdLpNH19fchkMtxutyRsNhqNdHd3Mzu3wNd+0EYsWrrtqZ+qpP9aHKXF4qhBxZ/c4UGpKAVFhkIhFhcXaWlpIR6PMzg4KBUH9fX1uN1uUqkUgiCgUCgkfYzT6USlUtHT08PU1BRqux2aS3lS8Xic5eVlaWKqvFp3dXUxNjbG/Pw8er0et9uNVqvFZDIRjUbp7OyUNDuFQoHu7m7p+RcKhS09SwGdTofBYJDyycreOzt9JkKhEHq9XpocK+uYurq6pMwou93O4uIihw4dwu/34/V6UavVRKNRGhoaLvp9PhuFQsHg4CCnTp3imWeeob6+HpPJxPz8PMmknK9+9RCxmBIQKcvP4nH46EcFRLEJozHHhz8sYjJdo8aBW91dDXDbaB8LCwuEV+c4slq6WKlUbhPPV3n+qU5dVaeuLo5qUu4lE4vH+dJsdEsEvHMXRSMU+JMhK08fPkxnZyfNz3NHbHo9xU9ccZLFM8djVAi8ssXAntpL0wzkcjkOHz5MY2PjjhNFx44do6amhtbWVk6cOIHJZKK7u1vyVQkGg8zPz2MymRgZGdmxgzE3N8eJ5Rh/8OZ9pKIyEERkMigWBGRysZSrKQpoTUX+6zEvtww1oFAoyGazOJ1O3G43AKOjo5jNZmk6KpPJcOrUKWm7RyaTUSwW0ev1DA4OkkqlOHXqFH19fajVahYWFiq2hsrxBnV1dUCps7KwsFAxKq7RaOjs7JQ0SWXX6EOHDqFWq3G5XDidzgptksFgoLe3F51Ox9NPP43BYGBoaKiia1ZOdG9vb2dlZYWhoSGWlpYwm8309PQQDAaZmpqSYigGBweJRCKEw2FUKhWpVIpDhw49JyF8MpnE7XZLhoEajWbL8VrFJz4xyNiYjrM/84IABw5k+MAHTnDXXYeelV9TsVgkkUhQLBbR6XSXvB34YpFOp0kmk8hkMkm0XeXy8JJIL//EJz7Bf/3XfzE2NoZKpWJzc/PFPqRrlxczKTcSobC5SVClkrxaDAYDDocDTTh8xRZZU951srLztKeF0qSTO17yJNlJjHu56bdo2WPWbC9Wn8XCo1QqpUymbDZLU1MTarWazc1NnE4nxWKRjo4OtFotIyMjTE1NcezYsQrTP6vVSn9//44LXzlIVWGo4T3/tsm//aUR57iCYmFLBFsQAJHW0Rxv+WSM+tY6qSBQqVR0d3eTyWQIhUL4fD68Xi/hrSkpnU4niX7X19dRKBRS/pPT6SQQCGC1WlEqlUxMTEjFmMfjIZlMotVqpTFru91OTU0No6OjPPHEE8hkMkZHRyUPoDJNTU2srq4SCAQoFousrq7S1NREU1MTKpWKSCTC8vIy4+Pj7Nu3j6GhIU6dOsXTTz+N3W6XokdisRiNjY3SFFM5W6oseC67TpfFym63m0wmQzqdJp/PMzw8/Jyn/XQ6Hb29vRXbrS6Xi0JhiV/+UklDg1Ax/afTwT//8zRyufqSixxRFPF4PLhcLknsXO5YdXV1PSuX5xcSjUZzWTq1VZ49V3Whk81mueuuu7jxxhv513/91xf7cIDSmazf75ecQ3U6HY2NjVit1ms65+V5IxKh8Ku/Ss7tZuW++9D09KBQKPB4PASOHeO6v/gLFI1XZlBeIn9x8Q5r8STZbPYF+zKUCcL2YvVZ0tLSgkKhYHV1lbGxMen3FouF7u5uyf24traWQ4cOsba2RjweRyaTYbPZdhXb5nI5lpeXaWpqIh6KUdtY5O1fjPC3t1rJnTWNrtLCO74YQa48I6Qui4wFQcDhcBDamopSq9V0dHRIfjQLCwsolUpkMpn0HKC0Jdfe3k5zc7PUiRodHZW6PpOTk/T29iKTyVhYWMBms0mp9FByv97Jp0Yul6PRaEilUgQCgW1eOFarlZqaGo4fPy51ag4ePIjH42FtbY1CoSB1eKxWq9RhSiaTWCwWPB4P3d3dKBQKurq6MBgMkqdQLpfDZDJJrtQXS6FQIBAIbDvBODcgFkoarJWVFb7zHReJRGVafSIBTz9d5Dd/89JPipaXl3E6ndTX19PY2CgVfE6nk2g0yv79+6+a7k6VF4erutD52Mc+BsDXvva1F/dAtkgmk4yPj5PNZrHZbKjVaiKRCJOTk9jt9l3PXKvsTmFzk5zbjcbr5YYPfQjZY4+VHGmXlyn+9m+jcLkoCALyKzB+wqRRwUUY0SY21qT8p6uRxsZGGhoaiMViUjbVTkVbeRLoYp5nMBhEFEXa2tpQKH3MrWVZmdSSS1X+/WRTAq5JOcPXizRqBGZnZwkEAhQKRcbHa9m3Lyo9djabJZVKYTQaMRgMRCIRstksjY2N9Pb2ks1mEUURtbrUdYjFYiQSCbq6uiSvH7VajUql4ujRozgcDiKRCBsbG4iiyMLCAsCORQCUIi1SqZR0/zttUyoUCpqbm6W4BK1WS3d3d4Wup4xer0ev1+NyudizZw8ej4fJyUlpJH1zcxO5XI5erycWizEwMHBJRU4ikWBiYoJMJkNtbS0KhQKfz4fL5doxT0ypVDIwMMD995cKvle+Ms5f/dUGf/M3Bh57zMypU+386Z+aL/rxofSd6nQ66ejooK2treK5W61Wjh8/jsvl2paSXqXK2VzVhc6VRNmXozxaefYXfXnPXK/XV/yxVrkwIbWa5fvuKxU5y8tw663wwAMo7r4bXC7STU2sfPGL9F2B015DTVYe31gnK1Owm0ZHLeYRI156BwYum3ngi0HZdK+MKIqEQiE8Ho8kjrVYLDQ3N1/U5E86nZaKiva2Vg6knTz0eOl2A7dm+LV7Ejx8n56pR9VMP67m7b+aYnJLc9PW1saJE/Xcc4+Gz31ultFRn9Q58vl8+Hw+oFS01NTUSKZ+5xYB5W2SC2VF/eIXvwBK3kg6nQ6/309zc/O2LoPb7aZYLKJWq1Gr1bt2IcrHms1mz9upEASBrq4uJiYmmJ+fp7Ozk6WlJQ4fPoxKpZKm3mKxGENDQ5fUMSwUCkxMTKBQKNi7d69UvBUKBRYXF5mbm0Or1Uq+UGWsVit/+Id6Dh70c+ONK4hikc9/3sjhwwoGB82XfKJX9mDaqSjU6XQ0NDTg8/no6Hh2OW35fJ719XXy+TxarZba2trqyeg1yEuu0MlkMhV5L5crb2Rzc5NEIsHevXu3faHY7XY2NjbweDy0tLRUxWiXwNraGuru7lIn59ZbYWkJbr65dGFnJ2vf/CaBTIY9FxjHfTHQqNUcqhV5PAIIIhXFzpYodo+4wcjw8FXlLVIsFgmHw/j9AQ4fVnHTTTkcjkYsFguCIEjdDY/HQ01NDZ2dnRSLRQKBAGNjYxdMFwekhbqcqfSKvjb+8E1J2vZE6L8jhyDA2z4TY/a/swxYQ+TcQdLpNPv378dkMvG3f1u6n5/8pIZ9+wLEYjFkMpkUQ5BOp/H5fESjUURR5PHHHwdKYuCmpibq6+svWvvR2NiIw+HAaDSSTCY5ceIEJ0+elNLbs9ksHo8Hr9dLa2srSqVSyvfaqZApb0ldzONbLBaGhoZYWFhgfX1d+n0ul0Ov19PY2Eh9ff0lb+2EQiEymQyjo6MVHSq5XE5PTw/RaBS3272t0AG4/XYNt9/eAJyZ7BoZuaSHl0in0xgMhl1PAoxGIx6Ph2KxeEknCqIosrKygtvtrjBz1Gq17Nmz5zmP4Ve5srjiCp0PfehD3Hvvvee9zvT0NH19fc/q/j/5yU9KW16Xk3Kmy24ZMna7HZ/PRzqdrvonXAKiKJa+wFpa4IEHzhQ5AA88gNDaijg39+Id4AW4qcuBfCXAU+tiRZimRijwcruK/U0DL+LRXTq5XI5Tp04RjUaZnGzhf/7PLv7hH+YYGTmF1WplcHCQ9fV1PB4PPT09FUnVra2tUrp4bW3tef8O6urqWFxcxOPx4HA4CIfD3Daa547rNSRUBk4vLKNXCHzwg31EIwVOnHDygx808+MfCyiVaf7f/1MBMh591EZjYwpRBLtdxd/9XZPk4aJWq6XE8ZaWlpJfz/o6MzMzbGxssGfPHrRaLYcPH2ZoaKiikBZFkdnZWTY2Nujp6ZFOXnQ6HXv37mV+fl7K0ILSllR5rDibzUr5YOfmVeXzedxuNzab7aKLE5vNhtVqZXNzk3Q6jVKpxGKxPKcTqvX1dalDdS5l48elpaUL+v08V5RKJbFYbNfHOTta5FIoZ4G1tLRIIvqyGHxiYoK9e/dWp3CvIa64Quf9738/v/d7v3fe6zyX/dgPf/jDvO9975N+jkajVU+DKxij0cjq6iq5pSWUd99deeHddxO5/34MW52EK5Ub2us52FpkYS1OPFugVqemo1b7rCadXmxmZ2dJJpPs27ePBx4oFfXj4z289a0WTp8+zdLSEolEApPJVFHkwJmtlmAwiM/no6ura6eHAEqTKs3NzSwvL7OysiIVvIVCAUEQMIoi+/fvRyYI1NbWks+r+cpX2ohGSx4uMlmpY5ZOy/nyl9sBAZMpz4c/XBrSy2QyzM7OSvdZW1srba0FAgGmp6epra2ls7OT06dPs7KyQltbGwaDgWQyicvlIhaL0dfXx9raGplMBqVSic1mw2AwsG/fPhKJBMlkErlcTk1NjdRxUKvVtLa2lj7XuVzFtNrKygrZbJbBwcELvheZTIZgMEgymUStVuNwOLZ1WERRJJlMSj49Z4+pn49isXje4kEul/NCOJPY7XZpWu5cbVc+n8fn82G32y/p7z+TyUhF5tlSgtraWkZGRjhx4gQrKyuMPNs2VJUrjiuu0LlYseKzpbw/frmpqalhdXWVSCSyY9szGAyiUqmqY4aXSGNjI74jRxDf9jZwuaCzs9TZuftuWFqi/fd/n+hDD73Yh3lB5DIZe+qu7jPERCLFl76kQqMZ4bHHTPznf5Z+/53vCHR22tjYGKZQWOf1r4/R1rbzyYNcLsdsNl/UlnG5MCgvqOUthvL22NmhiLW1cr73vVX+6q86eeYZgWJRtnWb0gj64GCET33KidE4DJSiJcr3KQJjzgDK9TQNtSa67HYCgQBer5cDBw4wMDDA4uJiZTyEUklDQ4NUrJQnsuRyOR0dHTQ3N0ti4Z1ob2+XJr3KxwKlwn7v3r0YDIZdX5disSh1u85mZWUFi8XC4OAgMpkMn88nBaoCUuhmZ2fnBbtFJpOJ5eXlXbfXwuGwZG74fFJTU4PFYmF6eppcLie5ZkejURYWFsjn8xfUUJ1LMBhEEIRthTiUPnPNzc3Mzs5uM8KscvVyxRU6l4LT6ZTGDAuFgjTeWjYleyExm83o9Xrm5uYYGRnZJkYuC+aq+pxLQxUMct0HPoB8S3gc2tquiv7zP9PxB3+A1utF85u/CY89Vo2feJ7xeiN89asdxGJKBOGMjX88Dh/5CIiiBaPRyKtfHTpvOnahULjg30Eul8PlctHa2kpraytra2uSXUNNTQ0TExMsLy9LuqD6+nrS6VUeeaQZh0NT4eGi0RT53OfGUChEnn76aYrFoiTU3VDVsKyuJyuqIAbE0mhcCa4zWsm556VkcpvNxsbGBplMBpVKRT6fZ2ZmBrvdTnt7OzqdjlQqhcvlkqavzmf+KAgCLS0tUup8eVrtYhK+zy5yHA4HjY2NpNOlKJH19XVOnDiB1WrF6XRSV1dHb2+vNJLtcrmIRqPs27fvvN2d8qj43Nwc/f39Fe9XIBBgfX2dPXv2XPBYnyuCIDA4OMjs7Cxzc3PMz89LnkFarZbR0dFLlgKUC5jdnn/5/nK5XLXQuUa4qgudj370o/x//9//J/28b98+oDQFceutt76gx1L+gxwfH+eZZ56pGC+PxWKSiVeVS8RoRN7YSFEQcH75ywQKBYqLixjr6oh9//to3vxmBLu9Gj/xAqDXF/nSl47xD/9wiKefFijXMoVCyfn20KEC99xzjPr6Us5Se3v7toImk8lI2VLnIxwOUywWaW5uRqFQUF9fGaPR3NzM5OQkyWQSvV6Pw+HA5/Pxb/+2SCJRue2TTsuZnjYyPBytSItfV5iY02wvRtKijF9GVfQqz3TgZDKZJBgXRVH6Gz/bMkKr1dLb2ysJXRsbGy8okJXL5ZckRC8nxgOSWSGUOkE2m41jx46RSCRIJBK0t7fT3t4u3bZ8nRMnTuByubbpg85GpVLR39/P1NQUR44ckTLM1tbW2NzcpL6+/lnHSFwqcrmcgYEBOjo6WF9flxyszeZLn+ICJBfn3To25YyyapFz7XBVtxe+9rWvIYritn8vdJFTRqfTcfDgQTo6Okin06ytraFUKhkaGmJgYKDazXk2bAXlyX75S3pvv51bbrmFV7ziFezfvx/7gQMIjz12RZoFPp+kUimWl5c5fXqKBx5wsbGx+YLoJUwmE/X1Gf7f/wtx7km0Tgff+IYHuz2D2Wwmk8lw7Ngx/H4/xWLJODGdTjM5OYlCobjgIpnL5VAoFLsuNuVJoPL2lVKpZHR0lMOHS0XDy14W4hvfeJqbby5ltj/1lA1BEGhra6OhoQERWNFuHcO5i+XWz06dg51e1Wi0VDA1NzfvuNC2tLRIY8uXm1Co9Hx0Ot22Lf7y8zv7OM5Fr9dTX1+Pz+e74Gemrq6O/fv3U1NTg8fjYXl5mWKxSH9/P319fS+4Lk6r1dLU1ERLS4vUyXs2nB3JcS7PRgxe5crnqu7oXIkolUqp3V7lMrEVP7EjL6HtKlEUWV1dZWVlBblczvi4g//5P1u4994J7ryzdIafz+fx+/0V7sNl597nisFgoLa2lh/+MEgiYa+4LJGARx7ZYGREwdLSEgqFgmQyyczMDHNzc5JpnVKpZHh4+IKLiEajIZ/Pk0wmd9yaKGdKnb1FrNVqefvbtdxyS4o7DoVIBpI4Pn6aX/yigbq6JKIo4na7qY3HSaIhW3OeM/ateA5XPLfNRbpcXO22ZXJuEXY5yefzUujnTgv9uRrAsqOxTqeT9EI1NTV4vd6LGsk2Go309/dfvidwBVCOLllaWqoQg0ciEUlzdb5uV5Wrj2qhU6XKVYLf75emf1pbW/na10qL1MREDzfeeIyxsTESiYQUHpjJZJiamkKn023TjV2IYrEoLYRnL6h9fX185jOlTsXtt0f5yEeifOxjRn7xixqeeMLM/v0phoaGqKmpIZvNStlO8XhcilW4mMkfq9WKQqFgZWVlm6N4OWXcbDZve0433ww3D2VJ3/Y2xECA9c99jt/4DQOJRAJBkKH0++m95x4ctRbm/vlBMsbzC8QTue1dj/IwQywW23Hbaaci7HKh0WgQRbEiYPRszhZ5P/HEExVdG5PJxJ49e571SPYVQSSCGI2yuTX9Vt76UyqV4HZfdO5da2urJAYPBALS72tqaujv799VRF7l6qRa6FSpchUgiiLLy6s8/HALWq0dSPPtb5cu+8EPwGxu27JKaOKjH61DpSr9acdiMU6fPs3ExAQHDx684OKWSCRwOp1SBINSqaSxsZGWlhaUSiUajYY/+iM7110X5tChZXK5LPfeq+YXv2hAqw0zMjIidTrUajW9vb10dHTwzDPPUCgULnq8uWxMNz09TTabRa/XE4lESKfTFItFRFHcVQy7vrqKNhBA6/Wy//3vx/etb5FXqzlYX0/ht38btcdDXgRVMn7BQqecnyWKIn6/H6/XKxUy09PTDA4OSiPd6XQar9eLz+dDJpORTqcpFAqX1fG6rq6O+fl5otEo0Wi0wuulnNheRiaTSYaF0WiUWCzGyZMnpSiOK9mSYUciEfKvehV5r5eZz36WbH295K/TJpPR9nu/V9LrXeRWtsPhoKGhgWg0Kombqx5n1yaC+EJs7l/BXGzMe5WrF1EUSaVSFItFNBrNRS+2VxKJRILHHjvBr//6y897vdraPE6nvEKbHY1GOXHiBIODg+e1btjc3GRiYgKVSkVjYyMajYZoNIrf70etVrN3795dNTPj4+MAjI6O7nj53Nwc6+vrHDp06ALPtJJAIMDs7Kyk84HS1kPZsn90dHSbXcT4+Dgyj4fed74TtdtNoa2N8T//c/Z+9rPIlpdJORzMf+lL/LR+H1lBsV2jAyCKGFUy/njQgkCpqAkGg1gsFqxWK/F4XIqSsFgsKBQKgsGgdHOdTif524yMjFzWDoHX62Vubk7Ky6qrqyMWi7GyslKhWSoUCvT29lJXV0cymWRsbEzyITp48OBV17WIz8wgv/12tF4vhfZ2ZI89Rq6hgcCxY9juugut11uyn6hOYL5kuNj1++r7xq9S5RIIBAI4nU6p1X8pXiIvBKIoEolEpLHlmpqaHbsuJcO33Ue2yzz8sA+jsfJL3mQyodfrWVtb27XQEUWR6elpjEYjIyMjUheivr6epqYmTp48ydLS0q6O5GVDut1Qq9XnHTnfjY2NDQRBoL+/X/Kh0mq10sI9MzNTUVyJosjm5iadw8Nsfu97mF77WrSrq+z/n/+zdHlnJ8v//M+IDQ20x3zM6VpKcRxnFzuiCAK8stmATBDw+XwEg8GKKadcLkcqlWJzc7NCdKxQKOjr68Nms5FMJpmcnGRiYoLrr7/+snV2HA4HMpmM+fl5XC4XLper4vJyITM/Py9ppMrGiGWuRj+vlXye/L/8C6N/9mfIl5bgtttQPfAALXffDV4vKYcD4cc/RlMtcqqcQ7XQqXLN4nK5WFxcxGKx0NHRgVKpZGNjA7fbTSQSYd++fS9qsRMOh1lYWKgYeVar1XR2dm5ze9XpdMhkMqampmhoaKW5GZJJzrpdgW9/+yl6enZewC7kZFt29x0aGtq2IOt0Opqbm1ldXaWrq2vH10yn07G5ubmrVf/m5uaz8jsJBAJ0dHRsGy/X6XR0dXUxPT29q2DZtm8fM3/zNwy+4x3S705/8INEjUbykQhWUaQ36WJF20BWONOp0ivgV1tN7KktdYo8Hg8Wi0UqcsqeXdlsVgrSlMlkJXNLnw+3243FYkGn0zE4OMjRo0cJhUKXdRy7oaGB+vp6adxbLpej0WiYnZ1Fo9GgVqsZGhoimUyytrZGoVBAr9czNTWFKIrk8/mrKkQ2n88TDofp2b8f4dFHt+XeiZ2dTNx7L/VKJe0v5oFWuSKpFjpVrkkymQxLS0s0NzfT1dUlLb41NTXY7XaOHz+O0+k8bwzB88na2hqTk5NYLBb6+/sxGAysra2xtLTE9PQ009PTaLVaHA4HDocDhUKB3W4nHA7j8XSQTFYWNJkMOJ0NvOY128Wx2WxW8nLajUQigUKh2NWwzmKxsLy8TCqV2rHQaWxsxO/34/F4thnlra2tsbGxccn5dOWMo92O22azARCJRKRCR9iKhAgGgzSLIv2f/GTFbbo+9jHG7ruPot2OSqXiQJOVO+1mnNEsKVHAotPQYlRK8RyiKBKPx2lrayMWi6HVavH7/SSTSQ4cOIBer2dpaQmNRkNPTw82m43x8XGpe6bX6zGZTKyvr1923xlBEKSpuvLrAKX3u6wN0ul00mtzdqF7tW3flrfktFotWCzbcu+EBx5AplQ+L5NuVa5+rkLZfZUqF8bv90u+Iud2GHQ6nXT2fbb244WinO5tNpsZHh6mpqaGeDwuaVF0Oh1yuRyj0cjS0hLj4+MUCgW6urpQqVR85SslL5VXvzrNY495ePnLS1snTzxh2ebdUiwWmZ+fRxAETCYToVBIMl07m3KEwW7bS+UFZLcuQE1NDU1NTSwsLHD69GnC4TBra2vMzs4yOTmJ1Wrd1pW5EMJZxcal0NzcTHZxkfwttyBbXkbs7CT6ox+RbWlB6/Wy9557ONTUxE033URbWxs6rZa++hr2NZhoM6kqMsjKupvV1VWOHz/OU089xcrKCmazucJ9vbzdaDabMRqN+P1+6TK5XP6CfM70er3kGnx2rESZUCiEKIpYLJarqpsDJfM+QRBKQnCXqxQBcxbi3XdTXF19XuJ9qlz9XF1lfZUqF0kqlUKv1++6NVVTU4Pb7Safz7/gDqixWIxUKkVvby+CIFAsFpmamsJgMDA8PEw6nebYsWPU19fT3NzM2NgYy8vLdHd3s2/fPl73uiA9PbPceqsPURS4/347hw9rUSpLyeI2mw2LxSKFHubCYYzFIidPnpSOoez31AwIJhNWq5XFxUWCwSCNjY3bjtnn811wKqW7uxu9Xo/L5ZKM7VQqFe3t7bS0tFzylI/RaEQmkxEMBiscfsuUx4LPzZazplIc/MAHUDqdpJua8H31q2TsdiKf/Swj731vSbR6550XFK2Wtz7Li+zg4CCbm5ssLS0RjUbJZrPk8/lttzMYDJK7bi6XIxKJVBj5PV8oFAoaGxvxeDwsLi6Sy+VwOBwolUqCwSBzc3MAL1oX87kgl8ux2+2ETpyg9f3vR1hersi9E5aWGHnve5E99tiLfahVrkCqhU6VaxKFQkEmk9lVM5LJZIDdOxTPJ+WcpfLUS1kfMzw8jEKhkH6fzWaxWq00NTVJWWlKpZI3v7kJURQpFLokP5SBASgWO/D5NBVTORa5nLYPfhDV5iaJH/4QU3Mz6VCIxUwG9+HD1L3vfQj19SgfeYTGQoHlsTEUCgU2W8lJuFAo4HQ6CYVC7Nmz57zFiiAIUvZS+bVXq9XP2q+lHJzpdDoxmUxYLBbpsmg0ytLSEjabTTLokzAaUTocFGQyXP/6r2xoNAixGHVlfcedd8IFYkPO3vq02WyMjY3h9Xrp7u7G7/eTSqVYXFwkFouhUCiIx+MEg0HsdjuJRAKVSkWxWGRhYQFRFHcsHp8POjs7icViRKNRnE5nxbi5IAgMDQ1dddNWZdoVCvjTP0Xwesm3tZH/8Y9Z1+vxf/az9P/Jn6D1esnffju5Rx9FWTX8q3IW1UKnyjWJ3W7H7XYTCoUkEWmZYrGI1+vFZrM9L4VOoVCQghp3SrAud5DKC2IsFkOtVktbIeUJsfL1rFYrLpeLdDot3ZcgCNt0FjKZjKamJpqamqTtnrmf/xzV5iYajwfN619PoaYGZShE4a/+in2f+AQar5eUKDL1ne8w8slP0lxTw4lPfAKF1YpGoyEej1MoFGhra0Or1bK2toZOp6soLpLJJNFoVHLs1Wg0l22qp6uri1QqxcTEBCaTCcOWUdzm5iZGo3FnL52t2BB5LEbPTh2bxx67oLFcIBCQtj6VSiV9fX3Mzs4SDAYl075AIIBKpWLv3r04nU6mpqZwuVzEYjHsdjtHjx4llUpJE2MvBHK5nL1790rp62VTPZvNJhXKVxLpdBqfz0c6nZZ0aCaTaceCWmu3U2huJiOTceJTnyJTTm+vqWHhS1+i953vJGMwMD0/z5DdftUWdFUuP9VCp8o1idFoxGKxSLoXu92OTCYjkUiwuLhIKpW6ZHHshRBFsXQW7XKxLqrJyRQoi3ma9XL69uyRvniNRiM6nQ6n00ltba2kqygXJ6urq6hUKsmIrrw9cimdEUEQyOVy+BUKTN/9Lg1veQvC0hKCXI6mUGDfe96DrFAg5XCw/o//yMB734vc7Ubb0cFoZyc+uZxYLIZer0cul+Pz+VhdXZXuv7a2lvb2dpxO5zZdkN1up7e397IIXuVyOSMjI4TDYfx+P5FIRAqcrKur2/01OSc2pFgsSpNG8nOKn3w+z9raOo8/LnDbbTIsFjOpVAqdTicVBg0NDZjNZnw+n5R1VSwWpfiA8nZQWdMTCoWk0M8X2p+rPAH2QnWRni2rq6ssLy8jl8sxGAxSYKnFYmFgYGD756emBvl//zfyWIxmUWRxcZGmpiY6OztLfyOPPopSr0fmcnHq1Cmuv/76q9P9ucplp2oYWDUMvGbJ5/PMzs4SCoWQy+XSdpZSqaS/v79iK+RysLi4yLgvgsvQTEo88wWrFvN0ZPzcsXeP1AlZW1vj1KlTmM1m6urqmJubo7Ozk2g0Sjgcpr+/XxLvllO6r7vuukvSuSSTSY4cOcLw8DC+I0fo+qM/KulTthDlcib/+q/p/eIXUbvdpB0OPN/8JpqeHhYXFxFFEYVCIQmRrVYr3d3dRKNRVlZWpAmsrq4u6urqKBaLBINBlpaWMBgMjI6OvugLTS6Xw+l04vf7pedhsVhoa2vDZDLhcrlYXV3lqadq+NCHRrj33gluuSWB0WgkGo1y6NChHZ/DysoKKysrFb8TBAG73U5PT89VN9X0QuP3+5mZmZFyAQVBIBAI4PF4pE5nb28vVqt1x8/8sWPHUCqV2Gw2XG43/oyM8fFarrsuSY9Vj8fjrvA9qnJtUjUMrPKSR6FQMDg4SCKRqPASuVwhl2eTSqUY90WY07eAWPnFnBEUzKibMC56uX2odOZvtVoZHh5mYWFBEokuLS2hVCqlL+hisYjL5SIcDl9QH7MT5W6E1+tlXadD+Xd/x54/+APpcqFQYPijHwVA7Ogg8PWv4xVFCvPzOBwOmpqaOH78OA6HA51Ox+LiIm63m56eHlKpFCsrKxgMBmlsWi6X09TUhF6vZ2xsjHA4fMGFRhRFYrEY6XQapVK5q2HisyGXyzE2NkY6naaxsZHa2loymQxer5exsTHq6uoIBoM0NTUxPV3SdJw+3cedd84QDoeBUmfm3GmxckFns9no6uqq2LarTv1cmHI4rc1mo7Ozk2w2y/j4OIlEAovFglKpZHNzU5rWGxwcrPhM5HI54vE4ZrOZZ5YDOPXtjB/V8LX31PB7/xhh+MYEnapaNjY2qoVOFaBa6FR5CbCTTuZy4/MHWNE2ArsUIwKMZ7S8PJ9HuXW2b7VasVgsRCIREokEbrebVCqF0+kkEAgQjUbJ5XK0tbU9Kw8WpVKJxVIaOXcUCrRuFTU7Efj0p6GlhcLyMjabjZ6eHrxeL6Io0t7ejkqlolAoSKGioVAIg8HAxsYGuVyuQvtRW1uLyWQiEAicd6HZ2Nhgfn6e5FnOhyqVio6Ojsuy7bKyskI6nWb//v0V739jYyMTE5P83/+bRS7vwGKx8d3vZoAMDz4IbW0d+P06DAYBmKVQKFBfX49cLicej7O0tCRtfWq12u1i6GsAURTJZDIUi0XUavVl1bIlk0lSqRTd3d0ATE1NkcvlOHjwIAaDgUKhwJNPPikVoisrK3R2dm67n8VYoXRigcDkT0sF5uTP1Oy5OcuMpgltap2d09CqvNSoFjpVqlwGfOkiWdn5hJ4CWZmK1WiGbsuZP7uywV1tbS0Oh4O1tTWCwaC0uDY2Nj6nIq2trY3EzAwt73sfao+nZJP/6U+jvvtuhLM8cyx/9mfM3H8/6PU4HA4EQSCTyaBWqyUhrcPhYHl5mXA4TDabxWazEY/HyWaz20Suer1eGrHeiXKulslkYmRkBJPJRCqVwuVyMTs7iyiKOBwO6frFYlESaZd9hs5HoVDA7/dLHaazkclkqFRm7r+/ddvtolH4+MdL/280ZrnrrhRzc3MsLCygUCjIZrOoVCqGh4ev2a3uQCDAqtOJLw05mQKNILKnzkRHR/tl2ZIrewoplUri8Tibm5sMDAxIYvzyNrNWq6W5uRmv10tbW5v0nisUChDkfO07DSQSIiAy8ZMcUGDiJ0VMdSU1xlFLI7cPiyjkV1l4aZXLTrXQqVLlMpCXX9xUTbq4+7bMuU63lwNjJMLee+4pTVc5HEz91V8x8Od/jlAoICoUCPk8RbkclctFzzvewdh990nbL0qlUvKKUSgUKJVK5HI5+XwetVotpXjvNMkTj8fPu42zk47HaDTS39+PTCZjaWmJ+vp6BEHA6XTi8XgkjU3ZL6a9vX3XgqfsDlwWdJ+LwXBhaeKXv3xsa2Kqk3A4TCKRkFKuywnqV10C+AVwOp0cc4Zx6ltJG868tnPRHH3jc/zq6M4i82KxSCaT2SoiVed9XbRaLTKZjPX1dRQKhfS5LxOLxaTEeo1Gg8vlIh6PU7MlLhcEgbVCDT/4XNO2+84m4Odf2nocU4HZ9+QYdLywPllVrjyqhU6VKpcBh6UWEukLXs+ofmF9e2Q1NRRtNtKCQO5rX2P4D/4AlddLuqmJub/5G3r++q/J6fUoYzHJNdjf2EjHLbdgt9tZXFzE4/FIEQjl8M76+noWFxcxGo3bRqfX1taIxWK7muSVx9HP1V4A0ki33++X3JWDwSAOh0MqfEKhEB6Ph3g8zvDw8I6anvLvyp5F56JSqXj44YexWhu57baeitwwnQ5Ongzg9TqlYi0YDBKPxyU7AJfLhVarZXBwsMIh+WomlUpxzBmWtoPOJitTMiHWYVr287KeM1Nr5e1Mn88nTQcaDAZaW1t33bZUKBTU19fjdrtpbGxEEASpMCoUCpJJo9VqrdjWPBtN7YWLl/f8+yaCpjpiXqVa6FSpclnosurRupOkikJlEnYZUcSglNFieIF9TGpqyH3/+0wcOYLZaKTX4aAglzP+939PymZj7HOfo6jX01VXh/o3f5OcToc7EqF2YwOz2UxLSwvLy8vk83mi0ShqtRqFQiGJdZPJJG63u2LqanV1FbPZjNW6PXcLzpg17rYlVz7j39zcJBgMVkygAZJ54Pj4OMFgcEf9klqtxmg04vP5tgWknv04U1MGksnK40gm4fHHMxw8WItSqeTYsWMAjI6OUltbiyAIRKNR5ubmGB8f5+DBg9eECNnr819QZ3Y0JufGYhH5liXC+Pg48Xgch8MhuXH7/X6mpqZIp9O0tm7fHoSSsWEkEsHj8VAsFiUhvtfrJZvNMjIygkwmkyYmz/2s1NcY+diTK+Rz8Mk7reTTZ45ZqRH58I/X0JqK6JXXVsetyrOjWuhUqXIZkAkCd7SZeHAlBqJYWexs/fyqFkNFjtILRW1bG51bydbhj3wEfbFIassVWNnRwcjISKkr8/jjpQVsbo5Tp07R3t6OxWIhmUzicrmk+xsbG0Oj0TA4OEgoFGJxcZGFhQWg1ElpaGioCFI9l3IHaLfU8VQqRbFYJB6Po9frd+wMmM1mzGYzXq93V6F2W1sbk5OTzM/PS2Z5oigSDoeZn59Hr9fzyCOlY/n1X8/yqU+J/Pmfw49+pObnPzfwm7/ZTCAQIJ1Oc/3111cca1lb9Mwzz+D1eul4npx4C4UCwWCQSCSCIAiYzebnZWoQwJ3IkZXt7hYNAhlBiTOWpaNGg8fjIRaLsW/fvgq9Ul1dHcvLyywtLVFXV7ejWFupVLJv3z5cLpf0D0oeTK2trRgMBjY3N3G5XDQ2Nm7bLhtuqePxyBpz0xry6cqOWi4NgcUcQ9cVX/gTiypXJNVCp0qVy0SfWcPrBYGfuOPEc2c0IEaVnFc269lT++Kd9dfX12OxWAgEArjdbpSFAgMDA1KHAoDmZvRAUyKBx+NheXlZMjGsra2lpqYGlUqFTqeTbldXV0cmkyEWi0nBoRdy39Xr9RiNRpxOJxaLZdui7XQ6pSDM3VxyoVRs+Hy+XR/HZrPR29vL/Pw8Pp8Pg8FANpslk8lgNpsZHBzkt387Rn//Arfc4iYYhA98AG6+uY3rrrNjNOpZXFzEYrHsWJCpVCrq6uoIhULPS6FTHrHO5/MYDAZEUcTn86HRaBgeHr7sk4S584rpz5Dc0rB7vV7JyfhsytuPXq8Xn8+348QUlIqdzs5OGhsbGR8fl2JDgsEgi4uLbGxsUFtbu+Pt1SoVr2zS89DnS0vYwK0Zfu2eBA/fp2fqUTXTj6u55w3yF+XEosqVR7XQqVLlMrKnVk1PjQpXPEciJ6JXCrQYlFfEF65SqaS5uZmNjQ1EUdxVqFteQG+66SZyuRwKheK8EQZqtfqSt246OzuZmJhgYmKC9vZ2jEajNHUVCATo6ekhHA6TTu+ueyrHBpwPh8OBzWYjEAhIcQh1dXVSAfWa15j59V+vJRazk8vl0Gg03HbbmQIin89jPE8mllqt3jHY87mSSqU4deqUFHNR7orE43Gmp6cZGxujo6MDrVZbWaw+BxrMJghcWKRtUJaS7tPp9K46LLlcjtFo3FVjczZarZYDBw7g9/slWwWNRkNfX5/kaL4TI/Um3vmbGdr7YvT9agZBgLd9JsbsT7LcMapmz0XoeKq8NKgWOlWqXGZkgkCb8cr9ktXr9Xi9XgqFwo5TSxsbG1L8wfOVjWQ2mxkeHmZ+fp6xsTHp90qlkt7eXhwOBzKZjNnZWeLx+DbBbyaTIRQKXVQquEqloqWlZdfLy52ondDpdEQikV0nrCKRyHkT3Z8tHo8HmUzG0NBQRTGXTqfJ5/PkcjnJaLIcQfFczfH6G8z8xB8kg/w8OrNS4S5Q2qbcTewtiiLZbPaihdpKpZKWlpbzvk878dZXq/mtO1W44uozJxb7rowTiypXDtUgkCpVrjEKhYJk9rYTjY2N5PN5VlZWODcBZnNzk3A4XOFh83xhsVi4/vrr2bt3L/39/QwPD3PjjTdKj22329HpdExMTBAKhaSR7vX1dcbGxlAqlc97nlNjYyPJZHLHLbJwOMzm5ubzcgxlV+mzi5xwOMzk5CR6vR6TyURNTQ379+/HaDQyNTVFIBB4To8pl8m4o9VU0iKfmwwk6cyMyLampOrq6vD5fBTO8mMqUzbBfCGcicsnFgMWNW1GVbXIqbKNakenSpVrhFgsxurqqjQRJZfLaWhooK2trWLrSavV0tXVxeLiIrFYjIaGBhQKBWtra/j9fmpqal6QQgfOGCbuhFwuZ3R0lKmpKU6fPi11nwqFAgaDgeHh4V231ERRZGNjA7/fTzqdRqVSUV9fj9VqvSQhb21tLY2NjczNzRGJRKQJrlAohN/vx2azPS+LeaFQkLpp5UmmpaUlFAoFer2eVCpFNpvFZDIxODjI1NQUi4uL5w86vQgGbDrkCjn/7YyROKt+MapkvLLZUKEza2lpIRQKMTk5SU9PDzqdDlEUWVtbY3Z2VgrWrVLlxaYa6lkN9axyDbCxscHExARarRaHw4FGoyEajeL1elEoFOzbt2+bjiYUCuFyuYhGo0Bpi8fhcNDa2vqih3GeSywWY2NjA0DqZuymSykWi0xNTREOh9Hr9RgMBpLJJLFYTJqWuhSHX1EU8Xg8uN1uSTOkUqloamqipaXleXmtxsbGEEWR7u5uJiYmJLPEmpoaYrEYxWKRmpoa9u3bB5Ren+PHjzM8PLzrWP+lUBTFi9KZbWxsSBEOWq1W2larqalhcHDwvNquKlWeKxe7flcLnWqhU+Uqp1gs8vTTT6PX67cZ6KVSKU6cOIHFYqG/v3/H2+dyOYrF4gUdba8WyuGjAwMD2Gw26TmVp5jKE1eXiiiKpNNpRFFEo9FsK3DKi7xSqawopPL5PKFQqEIMfaGJqWAwyNTUFHK5HJ1OJ3WVbrrpJjweD6urqwDs27ePmpoaisUijz/+OHv27Hnet/POpVAoEA6HicViyGQyrFbreaflqlS5XFTTy6tUeYmwtrZWYbJ2NlqtVjL96+7u3lFc/HwJjl8M8vk8Xq8Xq9WKTqermPpRKpU0NDQwPz9PZ2fnJYdxCoKw422SySQrKyuEQiFJ82Sz2WhvbyeRSDA3N0ehUECj0ZDL5VhZWcFut7Nnz55dIyzq6uowGo3EYjGUSqVksjgxMUE8HpeCVd1uNzU1NVIO2IvRQZHL5dTX129Lea9S5UqhWuhUqXKVk0wmUSqVu064mM1mKXH7WipqdqIcUzE8PHze63m93suSOp5IJDh58iQKhYLOzk4MBgOJLR+iEydOUCwWsdvtdHZ2otFoKBaLBAIB5ufnARgYGNjxfgVBQKlUotVqSafTrK+vA6UO3cDAgDR27XQ6EUURp9OJSqXa1TKgSpWXMtVCp0qVqxzZlh3/buPiZX3HhRK/rwUudif+cu3Yz83NoVKp2Ldvn1REGo1G1Go109PTCIJAX1+f1GmTyWTS1tLs7CxtbW3n3cbS6XQMDQ1RKBRYX19namoKv98vdW6KxSKnT58mHA5LgaiXC1EUiUQiku+SyWTCarVWt6SqXHVUC50qVa5ybDYbi4uL+P1+mpoqE51FUcTr9aLT6Z4Xv5crDYPBgCAIzMzM0NzcvO3yUCjE9PT0ZdHjJRIJIpEIAwMDKJVKihsbrE5O4hLFitH+U6dOMWAyobRYYCuBu76+noWFBUKh0K6Fjslkwul0UigUUCgUUhdncXGxwnsoFotJXZ7LRSaTYXJyUto6K3ePytEf5zNRrFLlSuPKGq2oUqXKJaPVaqU08UAgIC2yuVyOpaUlwuEwra2tl3wmXigUyOfzl6378UKgUqmw2+2SXkav10v/5HI5fr+fhoaGy5I4Xtb/1NbWIm5ukr71Vhp+67dol8srts7S8/MUbrkF8Y47IBIBSp0dlUq1owdNmcbGRkRRZH5+XnpPbTYb119/vWSs19bWxqFDhy5rkVMO6yzrvm666SZuvPFG9u/fj1KpZHx8/LyO1VWqXGlUOzpVqlwD9Pb2UigUmJ6eZmFhAbVaTTKZRBRFurq6dg2+3IlwOIzT5cIVz5OTKTAoZQw0Wmlpbroqti26u7tJJBIcP34cm82GwWAglUoRDAZRqVS7Tp9dKuWtwGw2S8LlQhMOo/V6af2d36Hws58hCAKqQIADH/gACo+HvFyOIhaDmhrS6TSpVOq8OiG1Wk1fXx/T09NEIhHq6+uRy+Wsra0RiURwOBy0t7df9vekPCF28ODBioLw7CBTj8dDV1fXZX3cKlWeL6qFTpUq1wByuZyhoSFisRjBYJB8Po/dbqe+vv6ScqhcLhdHV0Os6h1kDGe+HqaCWUY2F7l9aPdU8iuFcjK2z+fD5/OxsbGBUqmktbWVpqamyybIrq2tRalU4vF4KMjl5L7wBUbe+16EpSXkt9+O/S//kvaPfhSF10u2pYXpf/onRpubEUWR5eVl5HL5BTsx9fX16HQ63G43Ho9HCjodGBigrq7ueXkvgsEgtbW1O3a9lEol9fX1hEKhaqFT5aqhWuhUqXINYTQan7V+IplMcnQ1xJy+hVIOwBmyMiXHcjUYV4Lc0HHljxHL5XKam5t31OlcLmQyGa2trSwuLqJWqzF1dCA8+ijirbciLC3R/0d/BEDK4WD5S18iqtMRCATwer1EIhH6+/svyrjQaDReti7UxZDP5y/YaXo+gkyrVHm+qBY6VapUAcDj8TJLDbnUbonTIk9taLiuXazmCW3R3NxMPp9ndXWVUCjEkUQC1fvfz953v1u6TvDTnyaoVsPW1mJ5C+hKjUfQ6XRsbm7uGmS6ubl5WUbzqwCRCMlAADcC7mSevExFvdnIoMOKwucDo1ESsFd59lQLnSpVqgDgSuT4y1t29nUp88kTIVzx3LNOZy8UChUuwTab7YIuwVcygiDQ0dGBRqNhdnaWmmiUznvvrbhOy1/9Ff5PfQrr3r20tLRc0lbii0FjYyN+vx+v17ttim9jY4P19XX27NnzIh3dtYO4uUnmV36FYiDIo198kHVHOxSAMBw5Ncbv/sldqBrr4cc/rhY7z5Hq1FWVKlUAyAoXd96TyD27KaxwOMzhw4eZmZkhGAzidDo5evQop0+fPu/00ZVINptlY2ODSCRCsVikvr4eWypF6+/+LkqnE7Gzk+Ivf0mhrQ3Z8jKjf/ZntMlkV3yRA6U8raamJubn55mammJtbY2NjQ3m5+eZmJjAbDZXXZAvA6GlJfKBIAavh7vedRdGvwcAo9/Dm97xRlSry2T9AYjFXuQjvfqpZl1Vs66qVAHg5IqfH3gz572OSqvnLd2mS+7obG5uMj4+jtVqpaurC61WS7FYJBgMMjc3h8ViYWho6Lkc/gtCNptlYWGBYChERKYjJ1OglYmMCDmaf/utCEtLpBwOxu67j4zdjjoYZP/734/a7YbOTnjsMXgedUOXi7L/ksvlkkbJlUolDoeDtra2Ky709WpDFEWOHjvGRFjOG9/xRszuFTaa2/nhx/+J13zk3aWfm9p48CsP8buvGqluFe9CNeuqSpUql8RQs41H10NkUMBOX6yiiEEBLYZLn1pyOp3o9XoGBgYqXIIbGhoQBIHp6WlisdgVbUSXy+UYGxvDV1SzWttPsnhmsV+OhrnbWENNZyfCj39Mh9FYchO+7jrUN94It94KdntJc3EVIAgCTU1NOByO8waZVtlOPp8nnU4jl8vRaDQ76pwymQy+NIQbWvnWFx/kre94HWb3Cnf//q8DsNHczre++CCxuqbntFVcpUS10KlSpQoASoWC25v0POzJgChWFjtbP7+qxXjJZ5f5fJ719XV6e3t3XCjr6uokl+ArtdApFovMzc3hzimY0zqgWHl53GTlK//wbe4wZhjo6aHCtUivL3VyrkJh6W5BplW2k81mWV5erjDt1Ov1tLW1bbMREEWRnKy0/MYamvjhx/9JKnIAfvjxfyLWUNJHPdut4ipnqJbnVapUkRipN/G6diP6c06BjCoZr+8wsqf20jUm5VHk3fQpZZfgF3tkuVAoSGLbbDYr/T6fzzM+Pk4wFGJF07g1eX9usSeQMZr4icxGcSc1QHPzVVfkVLl4stksJ0+eJBwO09bWxr59+xgaGkKtVjM1NYXb7a64vlqtRisrfU6Mfg+v+ci7Ky5/zUfeLWl29MrqttVzpdrRqVKlSgV9Fg29ZjWueI5ETkSvFGgxKJ+1TkClUiGXy4lEIlit1m2XZ7NZksnkJbk3X06KxSIrKyt4vF7WRTU5mQKVmKfLrKe3t4eFhQVisRhRuZ6s7DzbdoJAShSqWw0vQZxOJ7lcjv3791dkylmtVhYWFlhcXMRut0thrDKZjL56M57pFe561107anTe+vbX8v2vfZ+Wvdv/ZqpcGldtR2dlZYU//MM/pKOjA61WS1dXF3/9139dcSZWpUqVZ4dMEGgzqhiwqGkzqp6TGLKsxfF6vVI+VJmyS7AgCC9KoSOKIjMzM4x5Nzlh6GXa0MGCroUpfQePpM08cnKWQCBAR0cHBcXFFS/VrYaXFsViEZ/PR2Nj47bgXEEQpJgOv99fcVm7XMbb3vWGrSKnjW998UE8o9fzrS8+yEZTG2bPKm95++uQeTwv5NO5JrlqOzozMzMUi0W+8IUv0N3dzeTkJG9/+9tJJBJ8+tOffrEPr0qV50YkArEYsZoa1tbWEEURg8GA1WpF5vVedXqP9vZ21tfXOXHiBM3NzdTW1pLL5fB6vWxsbNDb23vZohkuhUgkwsx6uuQGLW53g54U6ulVZLm5oQF7LMvc+YfSgOpWw0uNXC5HoVCgZpe/R6VSiU6nI5VKVfxeXluLtrmJtCDjP//lO5ImJ9bQxENf/T5vfcfrUDXUXzUC9iuZq7bQufPOO7nzzjulnzs7O5mdneX++++vFjpVrm4iEYp33EHO42HyM5+h4HAgk8nIZrMYNzfZe889yBsariojsXL+1PLyMk6nk5WVFaAUbzA0NITNZntRjsvn87Oqc7Bdc3OGFW0DPn8Acd2HSqslKyh3nkpDxKiUP6uptCpXL+Vw10xm5yq4WCySzWa3x33U1CD8+MdoYjH+sKmpcqt4rxXZLx+/6k5orlSu2kJnJyKRyAVt1TOZTMUHMhqNPt+HVaXKJSFGo+TcbtQeD9f/xV8gPPYYsrY24tPTKN/2NuQeD0VBQLaVhH21oFKp2LNnD11dXWQyGWn89sXElxHJnM8oURDICipOriyzp87GLTolPwuzfSoNERB4ZbP+pet5EokgRqNETSb8fj/ZbBa1Wk1DQwOmaPSaXbQVCgVWqxWv10tjY+O2ycJwOEw2m905wLWmBmpqkMF2XddV4Ld0tXDVanTOZWFhgX/8x3/kne9853mv98lPfpKamhrpX0tLywt0hFWqXBxrWi0nPvtZCu3tyFdXkf3Kr8BTT2F4zWtQezykHQ6Wv/KVq/aLUKFQoNfrX/QiByAvvzjdTV5eSj+/rrWO13UY0SsqixmjUv6sp9KuCSIRxDvvJHfTTUw98ggbGxuIosja2hqnf/xjsjfdhHjnnaUt2WuQtrY2kskkk5OTJBIJoDTF5/P5mJmZwWq1XrHWCS8Frjhn5A996EPce05WzLlMT0/T19cn/ezxeHjFK17Brbfeype//OXz3nanjk5LS0vVGbnKFcP09DTxeJzrGhpKRnNLS2cu7OzE+fWvs1oscsstt7xox3itcMoT5r+CF77eaNaNLh3Bbrej0+mIxeIsbSYRlRrIprl1dA81L+XvD7eb7E03oXK5SrEXjz+O0NqK6HRSePnLUayukmttRfnkk1dtgX4h1tbWmJmZIZfLSQnvhUKBuro6+vr6pC2uKpePi3VGvuIKnVAoxNra2nmv09nZKY3peb1ebr31Vg4dOsTXvva1S3burEZAVLnSOHXqFKIoMjIyAk89BTfffObCJ5/E297O3Nwcr3jFK3Z0Xa1y8RSKRT4/HiQjynd1g1aJOd49bCPg91dsyTQ2NmI2mzl69CjDw8M7js6/VMhms5x46CEO/Pmfo3Q6S3EXDzwAd98NS0vkWlv///buPSjK634D+PO+wMICy02Xy4bdBbGN5mdCGhWNWIUEI2lqoLVa05YQ62SKRZ0krU1vCdpJRydNNRPiWCedorVNsaZRTB1vo1xaKyZeUNFogoLIogERYVmQhd3z+wPdZOUiJLu8y/J8ZnaM73t298sZsvt43vOegxN//CMmZ2b2nqviRex2e69Na+++E4tcZ8RuAaHVaqHVagfV1mQyITU1FZMnT0ZBQQGXJyevoFare1ZXvXwZclaW88msLFjeeQfqoCCGHBfwkWXMNYRgV62ln9Wggbj2a+juCoXBYIDBYHB6/vXr1wH0vxjiaNHc3IxbWi3EoUPAE0/0jELeCejjxqF7zx501Nf3u5aSt5BlmRueeqARmwxMJhNSUlJgMBjwxhtvoLGxEddu/4uLaCSLiYmBbDLBNmtWzxfGuHHA4cM9f166hNisLMR61kDsiPbAmEB8Jz4EwX7OH4calQ8yjRpESR2oqanB3YPfdrsdtbW1CA4ORlBQ0HCW7HHu9I1PXFzPSM4Xbd3acxxwbI1ANJw8bkRnsA4cOICqqipUVVUh9q5rvh52NY5oSIKamzFl5Ur41dbCGhsLy44dkI1G3NyyBZHf/z7U9fXQ/fCHI2Yn7JHg/jB/fC1U1edq0J+NH4+PP/4YlZWV0Ov1t+fomFFbWwuz2YzExMRRP7oWHBwMALh55gzG9DEK2bxtm1M7ouHkcXN0hhvn6JArWSwWXLlSh6obFnQKCRp/P0yMDsd9ut63nfbr9h0stqtXceatt9By+/fSx8cHegDG556DFBk5otbRGekaGhpw6dIl3Lp1y3EsKCgI48ePR3h4uIKVDay9vR3t7e2QZRmhoaFunRBbuWcPxj//PAJMpl5zdG7pdKjZvBkT5sxx2/vT6DNiJyMPNwYdcpXm5maUfFyD6oDonkXlblPZrZjk24a0B8cPKezAbIa47z50dHTAbrdDrVb3fFHV1XntmiSeTAiB1tZWWK1WBAQEIDg42GNHctrb2/HJJ5/g5s2bEAI4dSoMU6ZYYDDoodfrXV93XR3ss2ZBrq5Gh06HzwoLoUpIQGdVFaKfeQbq+nrY4+Mhl5VxFJJcZsRORiYaiWw2G8ou1OKCOhZ3r7JrlVU4YQtH4MV6zPzaID/kby8kJgG979rgF4UiJEnqd5l/T9LR0YGTJ0/C19cXEydOxNGjEXjxRT+8804durur0NXVhYSEBNe+qUYDOSoKAsBnW7bAJMvo+uQTqFQqyNu2wfDss5CjuJ0BKYNBh8gFPmtoxEU/LfrdSkACPjL74FG7HT68O5Dc6PLly5AkCY888gj8/PxQVNRzvLw8FnPm2FBdXY377rvPtQs2hoYCe/dCMpsRFxuLOPSMgDlGjsq4nQEph0GHyAWqb7bDKg906VNCp+SH6psdGB8xuu/QIfex2Wy4dq0BBw/GYd8+KwArtm/vObd9OxATE44rVywoK7Pgt78NgEsz9+1RyDucLo9xFJIUxKBD5AKdGNwkz3abmwvxMkIItLS2oup6GzqEBG1IEL6uDRm9+0ndQ3d3N9rbJbz2mrHXudZW4LXXev47NLQbL77IK0k0OjDoELlAZGgwcOve8/pDA7iz9WB1dHSg+Fw1ziMMVvn2gnzmLgSYPsMcvQb/N5YjY3fr2Ufs3mvV7N5tgkZjuGc7Im/AyQJELjAxOhz+ortnNd2+CIEgHwF9MIPOYHR1deHA6U9xWtLCKjtvvHlL+OCD2nZ8fKNDoeo8l4+PD7RaLQ4dOoSGhpsIDGwD8PlDrW7Frl178I1vjFW4UqLhw6BD5AI+sow5sbcXQ7s77NzeSuAJAy+5DFadqR5Vvtq+95+6fezAlTbYR/fqGH0yGo3w9fVFUdFVtLcHAfj80dGhQVvbA9x/iUYVBh0iF5kUGYzMOA0C75quE+wn4TvxIbg/bHTvhzQUnzS2wCoPMPolSWi3S7jS1jV8RY0QQUFBePjhh/Gf//RMDJ45sxF/+1s5Zs7s2Zfr5Em9kuURDTvO0SFyoQkRAfh6uH+fWwnQ4HXYB9dfli6O6PRFo9Hg+eeDMWtWO558shu+vuOwcGEYtm8HjEb+LtLowqBD5GKyJMGoUd27IfXr7g02+xPkxy/t/sycKWHmzEAAn1+m+sEPlKuHSCkMOkTkfi0tuNXYCJMkobGxEd3d3QgMDIROp0Ok1Qr5rjVYJkZH4PRVa6+JyA5CIMhX4uRuIronztEhIvdqaYFtzhyI2bPRVFGBiIgI6PV6+Pj4oLqsDF3JyRDp6T37e90WEx2FB+TW2xO7+57cPUcfzEuCRHRPHNEhIreyt7Sgy2SCur4eU3/xC0glJYBeD6Msw/byy/Cpq0OXLMPPbHaM6siyjDkPfQ0Bn1zBiXZ/p4nJallgriEEE8JduIUBEXktBh0icqsmtRpV69dj2ssvQ750CUhJAbZuBbKy4FNTA6tej9NvvolHdDqnIWYfHx+kTIzDjK4uVDW1od0GjAlWwxjiz5EcIho0Bh0icqvW1lZAr4dcVtYTci5dApKTe06OG4f2nTvR1tSEzs5OqNXqXs9X+fnhgejw4S2aiLwG5+gQkVtJkgQhBERsbM9Izhdt3YrumBhHOyIiV2PQISK3Cg8Ph9VqRUtlJZCV5XwyKwtNFRVQq9Xw9+eCikTkegw6RORWYWFhCG9rQ0B6es9lq3HjgMOHIcaNAy5dgiE7G0ZZ5ogOEbkFgw4RuZVkMuHBFSsQUF+PDp0OZzdswMfh4Ti5bh06dDqo6+sRtWgRUFendKlE5IU4GZmI3EujgRwVBSFJaN22DTaVCp0dHQi8/350HzgAzJsHKTIS0GiUrpSIvBCDDhG5V2gosHcvJLMZUbGxiLr7fGlpT8j5wsrIRESuwqBDRO531xYPTmJjh7cWIhpVOEeHiIiIvBaDDhEREXktBh0iIiLyWgw6RERE5LUYdIiIiMhrMegQERGR12LQISIiIq/FoENERERei0GHiIiIvNaoXxlZCAEAaG1tVbgSIiIiGqw739t3vsf7M+qDjtlsBgDo9XqFKyEiIqKhMpvNCB1grzxJ3CsKeTm73Y76+npoNBpIkqR0Ob20trZCr9fjypUrCAkJUbocj8K+6R/7ZmDsn/6xb/rHvhnYcPePEAJmsxk6nQ6y3P9MnFE/oiPLMmJHwKaCISEh/B+rH+yb/rFvBsb+6R/7pn/sm4ENZ/8MNJJzBycjExERkddi0CEiIiKvxaDj4fz9/ZGXlwd/f3+lS/E47Jv+sW8Gxv7pH/umf+ybgXlq/4z6ychERETkvTiiQ0RERF6LQYeIiIi8FoMOEREReS0GHSIiIvJaDDojyNNPPw2DwYCAgADExMQgKysL9fX1SpeluJqaGixZsgTx8fFQq9VISEhAXl4erFar0qV5hN///veYMWMGAgMDERYWpnQ5ituwYQPi4uIQEBCAadOm4cMPP1S6JI9QVlaGefPmQafTQZIk7Ny5U+mSPMaaNWswdepUaDQaREZGIjMzExcuXFC6LI+wceNGPPTQQ45FAh999FHs2bNH6bKcMOiMIKmpqfjnP/+JCxcu4F//+hcuXryI733ve0qXpbjz58/Dbrdj06ZNOHv2LNavX48//elP+PWvf610aR7BarViwYIFWLp0qdKlKG7btm146aWXkJeXhxMnTiAxMRFz585FQ0OD0qUpzmKxIDExERs2bFC6FI9TWlqK3NxclJeX48CBA+jq6sITTzwBi8WidGmKi42Nxdq1a3H8+HEcO3YMjz32GDIyMnD27FmlS/ucoBGrqKhISJIkrFar0qV4nNdff13Ex8crXYZHKSgoEKGhoUqXoaikpCSRm5vr+LvNZhM6nU6sWbNGwao8DwCxY8cOpcvwWA0NDQKAKC0tVboUjxQeHi7+/Oc/K12GA0d0RqgbN27g73//O2bMmAE/Pz+ly/E4LS0tiIiIULoM8iBWqxXHjx9HWlqa45gsy0hLS8ORI0cUrIxGmpaWFgDgZ8xdbDYbCgsLYbFY8OijjypdjgODzgjz8ssvIygoCGPGjEFtbS2KioqULsnjVFVVIT8/Hz/5yU+ULoU8yPXr12Gz2RAVFeV0PCoqCteuXVOoKhpp7HY7XnjhBSQnJ2PSpElKl+MRzpw5g+DgYPj7+yMnJwc7duzAAw88oHRZDgw6CvvlL38JSZIGfJw/f97RfuXKlTh58iT2798PHx8fPPvssxBeurj1UPsGAEwmE9LT07FgwQI8//zzClXufl+mb4joq8vNzUVlZSUKCwuVLsVj3H///aioqMDRo0exdOlSZGdn49y5c0qX5cAtIBTW2NiIpqamAduMGzcOKpWq1/G6ujro9Xr873//86hhQlcZat/U19cjJSUF06dPx+bNmyHL3pvjv8zvzebNm/HCCy/g5s2bbq7OM1mtVgQGBuK9995DZmam43h2djZu3rzJ0dEvkCQJO3bscOonApYtW4aioiKUlZUhPj5e6XI8VlpaGhISErBp0yalSwEA+CpdwGin1Wqh1Wq/1HPtdjsAoLOz05UleYyh9I3JZEJqaiomT56MgoICrw45wFf7vRmtVCoVJk+ejIMHDzq+wO12Ow4ePIhly5YpWxx5NCEEli9fjh07dqCkpIQh5x7sdrtHfS8x6IwQR48exUcffYSZM2ciPDwcFy9exCuvvIKEhASvHM0ZCpPJhJSUFBiNRrzxxhtobGx0nIuOjlawMs9QW1uLGzduoLa2FjabDRUVFQCA8ePHIzg4WNnihtlLL72E7OxsTJkyBUlJSXjzzTdhsViwePFipUtTXFtbG6qqqhx/r66uRkVFBSIiImAwGBSsTHm5ubl49913UVRUBI1G45jTFRoaCrVarXB1yvrVr36FJ598EgaDAWazGe+++y5KSkqwb98+pUv7nLI3fdFgnT59WqSmpoqIiAjh7+8v4uLiRE5Ojqirq1O6NMUVFBQIAH0+SIjs7Ow++6a4uFjp0hSRn58vDAaDUKlUIikpSZSXlytdkkcoLi7u8/ckOztb6dIU19/nS0FBgdKlKe7HP/6xMBqNQqVSCa1WKx5//HGxf/9+pctywjk6RERE5LW8eyIDERERjWoMOkREROS1GHSIiIjIazHoEBERkddi0CEiIiKvxaBDREREXotBh4iIiLwWgw4RERF5LQYdIhq0mpqae+6aPhybhpaUlECSJKxatcrt7+Vq+fn5WLx4MR566CH4+vpCkiSUlJQoXRaR1+JeV0Q0ZAkJCfjRj37U57mAgIBhrmZkWbFiBQAgJiYGWq3WsW8SEbkHgw4RDdn48eNH5GiKJ/j3v/+NyZMnIzo6Gjk5Odi0aZPSJRF5NV66IiK3OX36NBYtWoSYmBioVCoYjUYsX74cTU1Nvdr+5S9/QUZGBuLi4hAQEICIiAjMnTsXxcXFTu1WrVqF1NRUAMDq1audLpvV1NQAAFJSUiBJUp81Pffcc05tAWDz5s2QJAmbN2/GBx98gOTkZGg0GsTFxTnaWK1WrFu3Do888giCgoKg0WjwzW9+E7t27RpSnzz11FOIjo4e0nOI6MvjiA4RucWuXbuwcOFCyLKMjIwM6PV6nDt3Dm+//Tb27duHo0ePIjw83NE+NzcXiYmJSEtLg1arhclkws6dO5GWlob3338fGRkZAHpCTE1NDbZs2YLZs2cjJSXF8RphYWFfqebt27dj//79+Pa3v42f/vSnaG1tBQB0dnYiPT0dJSUlePjhh7FkyRJ0dXVh9+7dyMjIQH5+PpYtW/aV3puI3INBh4iGrKqqqs9LV+np6Zg+fTqampqQlZWFsWPH4vDhwzAajY42hYWFeOaZZ/Dqq68iPz/fcfzcuXOIj493er2rV69iypQpWLlypVPQAYAtW7YgJSXFpZfQ9u7di3379iEtLc3p+O9+9zuUlJTglVdecYwiAYDZbMZjjz2Gn/3sZ/jud78LnU7nslqIyDUYdIhoyC5evIjVq1f3Oh4WFobp06fjr3/9K1pbW/H22287hRwAWLRoEf7whz+gsLDQKejcHXKAngm78+fPR35+Pi5fvtzrtVwtIyOjV8ix2+3YuHEjEhISnEIOAGg0Grz66qt4+umn8f7773NUh8gDMegQ0ZDNnTsXe/fu7fd8eXk5AODo0aO4ePFir/O3bt3C9evXcf36dYwdOxYAcOnSJaxZswaHDh2CyWRCZ2en03Pq6+vdHnSSkpJ6Hbtw4QKam5uh0+n6DHeNjY0AgPPnz7u1NiL6chh0iMjlbty4AQDYsGHDgO0sFgvGjh2LqqoqJCUlobW1FampqZg3bx5CQkIgyzJKSkpQWlraK/i4Q1RUVK9jd36Ws2fP4uzZs/0+12KxuK0uIvryGHSIyOVCQkIAAGfOnMGkSZPu2X79+vVobm7G1q1be63Pk5OTg9LS0iG9vyz33FDa3d0NX1/nj7mWlpZ+n9fXnVp3fpb58+fjvffeG1IdRKQ83l5ORC43bdo0AMCRI0cG1f7O5a07E47vEELg8OHDvdr7+PgAAGw2W5+vd+duLpPJ5HTcbrfj1KlTg6rpjokTJyIkJATHjh1DV1fXkJ5LRMpj0CEil1u8eDE0Gg1+85vf9Hm5p7293TGPB4Bj7s1///tfp3Zr165FZWVlr+dHREQAAK5cudLn+0+dOhVAz/o4X7Ru3TpUV1cP/gcB4Ovri6VLl+Ly5cv4+c9/3mfYqaysRENDw5Bel4iGBy9dEZHLabVa/OMf/8CCBQuQmJiI9PR0TJgwAZ2dnaipqUFpaSlmzJjhmNCck5ODgoICzJ8/HwsXLsSYMWNQXl6OEydO4KmnnsLu3budXn/ChAnQ6XQoLCyEv78/YmNjIUkSli9fjtDQUCxevBivv/46Vq1ahYqKCiQkJODYsWOorKzE7Nmzh3wpbPXq1Thx4gTeeust7N69G7NmzUJkZCRMJhPOnDmDU6dO4ciRI4iMjLzna61du9YxcfnOiNfatWsdoSwzMxOZmZlDqo+IBiCIiAapurpaABBz584dVPvz58+LJUuWCKPRKFQqlQgPDxcPPvigWLFihfjwww+d2hYXF4vk5GSh0WhEWFiY+Na3viWOHz8u8vLyBABRXFzs1L68vFzMnj1baDQaAUAAENXV1Y7zFRUV4vHHHxeBgYEiJCREZGRkiE8//VRkZ2f3altQUCAAiIKCgn5/lu7ubrFp0yaRnJwsQkJChL+/vzAYDCI9PV1s3LhRtLW1DapPZs+e7ai3r0deXt6gXoeIBkcSQghFEhYRERGRm3GODhEREXktBh0iIiLyWgw6RERE5LUYdIiIiMhrMegQERGR12LQISIiIq/FoENERERei0GHiIiIvBaDDhEREXktBh0iIiLyWgw6RERE5LUYdIiIiMhrMegQERGR1/p/bHmcZVeuujUAAAAASUVORK5CYII=", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "# select data using grid partitioning methods\n", - "# -------------------------------------------\n", - "size = 50\n", - "\n", - "# selector = Medoid()\n", - "# selected_medoid = selector.select(X, size=size)\n", - "\n", - "selector = GridPartition(nbins_axis=6, bin_method=\"equisized_independent\")\n", - "selected_p1 = selector.select(X, size=size)\n", - "\n", - "selector = GridPartition(nbins_axis=6, bin_method=\"equisized_dependent\")\n", - "selected_p2 = selector.select(X, size=size)\n", - "\n", - "selector = GridPartition(nbins_axis=6, bin_method=\"equifrequent_independent\")\n", - "selected_p3 = selector.select(X, size=size)\n", - "\n", - "selector = GridPartition(nbins_axis=6, bin_method=\"equifrequent_dependent\")\n", - "selected_p4 = selector.select(X, size=size)\n", - "\n", - "\n", - "graph_data(\n", - " X,\n", - " indices=[selected_p1, selected_p2, selected_p3, selected_p4],\n", - " labels=[\n", - " # \"Medoid\",\n", - " \"equis_independent\",\n", - " \"equis_dependent\",\n", - " \"equif_independent\",\n", - " \"equif_dependent\",\n", - " ],\n", - " title=\"Comparing Partition-Based Selectors\",\n", - " xlabel=\"Feature 1\",\n", - " ylabel=\"Feature 2\",\n", - " fname=\"quick_start_compare_partition_methods\",\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Compute diversity of selected points" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "data": { - "text/markdown": [ - "**Diversity of Selected Sets**\n", - "\n", - "| | logdet | wdud |\n", - "|-------------------|-------------------|---------------------|\n", - "| equis_independent | 90.84 | 0.072 |\n", - "| equis_dependent | 90.513 | 0.063 |\n", - "| equif_independent | 75.536 | 0.085 |\n", - "| equif_dependent | 78.987 | 0.09 |\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "div_measure = [\"logdet\", \"wdud\"]\n", - "set_labels = [\n", - " # \"Medoid\",\n", - " \"equis_independent\",\n", - " \"equis_dependent\",\n", - " \"equif_independent\",\n", - " \"equif_dependent\",\n", - "]\n", - "set_indices = [selected_p1, selected_p2, selected_p3, selected_p4]\n", - "seleced_sets = zip(set_labels, set_indices)\n", - "\n", - "# compute the diversity of the selected sets and render the results in a table\n", - "table_data = [[\"\"] + div_measure]\n", - "for i in seleced_sets:\n", - " # print([i[0]] + [compute_diversity(X_dist[i[1]], div_type=m) for m in div_measure])\n", - " table_data.append([i[0]] + [compute_diversity(X_dist[i[1]], div_type=m) for m in div_measure])\n", - "\n", - "render_table(table_data, caption=\"Diversity of Selected Sets\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Comparing Multiple Selection Methods (Multiple Clusters)\n", - "\n", - "Each cluster is treated independently, and if possible, equal number of samples are selected from each cluster. However, if a cluster is underpopulated, then all points from that cluster are selected. This is to ensure that the selected subset is representative of the entire dataset.\n" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Shape of data = (500, 2)\n", - "Shape of labels = (500,)\n", - "Unique labels = [0 1]\n", - "Cluster sizes = 250 250\n", - "Shape of the distance array = (500, 500)\n" - ] - } - ], - "source": [ - "# generate n_sample data in 2D feature space forming 3 clusters\n", - "X, labels = make_blobs(n_samples=500, n_features=2, centers=2, random_state=42)\n", - "\n", - "# compute the (n_sample, n_sample) pairwise distance matrix\n", - "X_dist = pairwise_distances(X, metric=\"euclidean\")\n", - "\n", - "print(\"Shape of data = \", X.shape)\n", - "print(\"Shape of labels = \", labels.shape)\n", - "print(\"Unique labels = \", np.unique(labels))\n", - "size_0, size_1 = np.count_nonzero(labels == 0), np.count_nonzero(labels == 1)\n", - "print(\"Cluster sizes = \", size_0, size_1)\n", - "print(\"Shape of the distance array = \", X_dist.shape)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To select from multiple clusters provide the `labels` argument to the `select` method.\n", - "Check Documentation: **[Medoid](https://selector.qcdevs.org/api_methods_partition.html#selector.methods.partition.Medoid) | [GridParition](https://selector.qcdevs.org/api_methods_partition.html#selector.methods.partition.GridPartition)**\n" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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KVP967ewsJDx48cTFxeHp6dng2vyt99+Y/jw4URERKDVavH29iY2Nparr76a119/nZKSktMYyVbkfM+LXSzk5+dL/jQPPPDA32pr9erVwsfHx23u3svLy80XY926dQ32qz+v/e2330pteHt7C5VKJZUNGDBAWK1W8fPPPwtPT08BCJPJJBQKhVTnjjvuaFS2QYMGCUA8++yzYsCAAQIQarXaTV5AvPjii43uP3LkSKmOWq0Wfn5+bnPpOp1OLF68uNl977vvPnHLLbcIQCiVSuHr6yuUSqXkB9Lc/H59n5Y//vhD8oMwGo1ucoSFhTXpr7NkyRKh0WikugaDQXh4eAhAhIaGik8++UQqO13qy9fUnPq+ffukOtOnT2+wn+ucG41Gt2233XabsNvtzfa5ePFi6di8vb2Fh4eHGDRokHjttddEcHCw9Bv39vZ28ycJDg52a7OxY7j55ptFQECAVBYQEOC2/80339yoTI3RGtfIzz//LIKCggQgPD09hU6ncxu/Xbt2nep0NcqprgEhhBgzZowkZ2O4rjNAaLVa4e/v7+avZzKZGj0+IYS4//773c67wWCQrvOmrgshhFi+fLnbmGo0Grcx1Wq14tNPP220z+3btwtfX1+prl6vl64tb29v8fXXX5+xz41L9rvuuuu09qvPzp07RUREhCSDSqVyuz4UCoWYMWNGo/s2dz1WV1eLW2+9tcG1V/9e2qdPH1FSUtJo25999pl076h/ruvfi3bu3CmEEGLs2LEiODjY7Tde//rp2bOnW9spKSlux+zh4eF2zM3da111PvzwQ6nP+vu7eOmll9yO3dPTs4Fv2fnyDZKVm1biq6++crtpnimZmZnSDSYxMVGsX79eKlu7dq2Ij48XgPDz82vw8K1/4/bx8RFXXHGF2LdvnxDCeRG+9dZbkpLzn//8R5hMJnHHHXeIjIwMIYQQFRUV4rnnnpPaWL58eQP5XDddk8kkdDqdmD9/vqipqZFkr3+h//DDDw32nzZtmnjttdfE3r17hc1mE0IIYbfbRUpKirj77rulB1VOTk6DfV3KjcFgEGq1Wrz++uvCbDZLsufm5jYYh+aUG19fX/Gvf/1LHDhwQAghhMViEV9//bV0Ad97770NZEhNTZVutj169BDbtm0TQgjhcDjE8uXLRbt27dxu8qdLS5SbX375Raozb948IYTTAffhhx8Wy5cvl8ZECCGOHz8u5s6dKzkkz507t9k+DQaDuPbaa6UxEUKIw4cPS/+31KG4qWNoqWNpc8pNa10jvr6+ol+/fmLr1q1CCCFsNptYvny5CA0NFeB8CTgTmlNujh8/LmbNmiUpKk09UJ988knx7rvvisOHD0sKqc1mE5s3bxbDhg0T4FTAq6ur3fZbt26dAKfSP2vWLHH8+HGprLi4WPz2229i5MiRDa6vPXv2SM65Dz74oNi/f7+oq6sTQghx7Ngx8dhjjwlwvpC4xstFeXm5iIqKEoCIiooSv//+u3A4HEIIITZu3Cg6d+7spjSdrnIzePBgqe8vvviiUQW9OXJzcyUldvjw4WLbtm3CarUKIYQoKCgQzz//vKRMfPfddw32b+56vOeeewQgYmNjxRdffCFdezU1NeKHH34QsbGxAhA33XRTg31//vlnSQnq16+fWLdunXRsFotFrFu3Tjz44IPSPbwl8rgoLy8XMTExAhDh4eHil19+kdretWuX6NOnj6TgNKbE178fxMfHi5UrV0r7Hzp0SAghREZGhvQ7Hj9+vNtvqqysTKxbt0489thj0j3yXCMrN63Ef/7zH+kH0diDuaU88sgj0o03Ly+vQXlWVpb0oPr3v//tVlb/xt25c2dRW1vbYP97771XqnPVVVdJN6H6uCwyjVmg6r9RfvTRRw3K7Xa7GDhwoCTD6XLdddcJQEybNq1BWX2rz1tvvdVkGy1VboYMGdLojfKtt96S3j5dCpiLBx54QAAiKCjI7cHh4uDBg24WgNOlJcqNa4zqv9Wdim+++UaAc5VVc3326tVLeqg1RltQblrrGunUqVMD5UAIIX788UepTlZWVrPH2RiufU9eLVX/rTk5OVm8//77p922EELU1dWJbt26CUB8/vnnbmWzZs0SgLj66qtPq83LL79cgNMi2xRjx44VgLjxxhsb7VOr1Yr9+/c32C8vL89N4T9d5Wb16tVuloyQkBBx++23i1dffVX88ccforKystn9R48eLaB5y88bb7whAJGUlNSgrKnf8tq1a6V7QWZmZqPtZmVlSdav+teqzWaTlI/+/fuf1orZlig3r7zyigCn9W3v3r0NysvLy0V0dLQAxHXXXddkH97e3k1eAy5rXFxcXItlP5fIyk0r8eijj0o/CJcl43RxOBzCz8/vlDeZSZMmCUD4+/u7ba9/416wYEGj+/73v/+V6qxcubLROi+//LIAxKWXXtqgzKXcREZGNqoYCSHE77//LvWxZ8+eJo+jMd577z0BiKFDhzYocyk3vr6+zd4MWqrcNGaZEsL5puqqU/9m7XA4pDfQ5qYc6iuQp0tTyk1NTY3YtWuXGDFihJty1lKqq6ul/U5WCOr3+c033zTbzvlWblrzGvnwww8b3ddmswmtVisAsXTp0maPszFc7Tf3iYqKElOmTJEsCKeL6/gefvhht+3vv/++pDw1p6TWxzUmarW6UYXdxbZt2ySlrX7bycnJAhB33313k/s+++yzZ6zcCCHEihUrJIvcyR+NRiOuvfZasWbNmgb71dTUSNM+u3fvbrL94uJiqb38/Hy3sqZ+y6770bhx45qV/frrrxeAeOWVV6Rt9e+RJ1vCTkVLlBvXORkxYkSTdVz3WqVSKcrKyhrt4+SXg/r89ttvApxT8adSMM8HskNxGyI9PV1yvrryyiubrHfVVVcBcPz4cdLT0xut09QS3ODgYOn/Sy+9tNk6paWlTcrgcixujAEDBkiOf9u2bWtQvnv3bh577DG6deuGt7c3SqVScmB77LHHAMjOzm6y70svvbRVlnw2tcooLCxM+r++M1xaWpoUeG7QoEFNtlvfMfbvUN9hUK/X0717d7766isAkpOTpf9dVFRU8NprrzFo0CCCgoLQarXS/p6enlK95sa2X79+rSL72aI1r5Gmzr8rYCLwt5whX3zxRYTzBRIhBHa7nYKCAr788kuEEEyZMoWrr766SefedevWMWrUKDp16oTBYHBzHn311VeBhufyiiuuwMPDg507dzJgwAA++uijJo/fxYYNGwCnc3NiYiIhISGNfoYNGwZAVVUVx48fB8BqtbJ3714ALr/88ib7aK6sJVxxxRXs37+f1atX8+yzz3L55Zfj5+cHOJ3ply5dyqBBg3jhhRfc9tu+fbs0vldffXWTx9a5c2dpH5fT/KlwjdtHH33UZLshISGsWLGiQbsbN24EnCsge/bseYaj0jhWq5U9e/YALbtGHA4HO3bsaLROc/eDXr16ERAQQF5eHr179+add97h4MGDTS5cONfIS8FbCX9/f+n/kpIStwdkSyksLJT+by4+S/1VWIWFhW4rUFwYjcZG962/2uBUdZpaMXUq+Tw8PPD396egoMDtmADeeecdnnzySRwOB+D0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ZWVN0KjOHXfddRevvPIKGzduJDc3d6KHM6F27dpFV1cX8+bNU45Fo1E2btzIT37yE4LBIGq1egJHODGys7MTPm8Apk+fzp/+9KcJGtG5TwQ3R8nIyCAjI+N9z5s/fz56vZ5Dhw5x8cUXAxAOh2lqaqKgoOBMD/OsG+99+fGPf8z//M//KN+7XC6uuOIKfv/737N48eIzOcSzbrz3BOIzNpdddpkyw6dSXVgTpjqdjvnz5/PWW28p5RJisRhvvfUWd91118QObgLJsszdd9/NX/7yF959912KioomekgT7vLLL2f//v0Jx2699VbKysr42te+dkEGNgDLli0bVSagtrZ2Un7enC4iuDkFSUlJ3HHHHTz00EPk5eVRUFDA448/DsANN9wwwaObOPn5+QnfWywWAEpKSi7Y30idTifLly+noKCAH/zgB3R3dyuPXUizFvfeey8333wzCxYsYNGiRTz11FP4/X5uvfXWiR7ahFm1ahW//e1v+dvf/obValXyj5KTkzEajRM8uolhtVpH5RyZzWbS0tIu6Fyk1atXs3TpUr773e9y4403sn37dn72s59dcLPAJ0MEN6fo8ccfR6PRcNNNNxEIBFi8eDFvv/22qDsgJHjzzTepq6ujrq5uVIAny/IEjers+8QnPkF3dzcPPvggHR0dVFRUsH79+lFJxheSZ555BoDly5cnHF+3bt37LnkKF5aFCxfyl7/8hW984xs8+uijFBUV8dRTT/GZz3xmood2zpLkC+lfWEEQBEEQJr0La/FfEARBEIRJTwQ3giAIgiBMKiK4EQRBEARhUhHBjSAIgiAIk4oIbgRBEARBmFREcCMIgiAIwqQightBEARBECYVEdwIgiAIgjCpiOBGEIQTampqet8O6AMDA2d8HO+++y6SJPHwww+f8dc63dauXcutt97K7Nmz0Wg0SJLEu+++O9HDEoRJS7RfEARhXEpKSvjsZz875mMGg+Esj+b88uUvfxmId3fOyMhQ+kgJgnBmiOBGEIRxmTJlynk5a3IueOWVV5g/fz5ZWVnccccdPPvssxM9JEGY1MSylCAIp9W+ffv45Cc/SXZ2NjqdjoKCAu6++256e3tHnfvLX/6Sa6+9lsLCQgwGA6mpqVxxxRW88847Cec9/PDDXHbZZQA88sgjCUtiTU1NQLwBpSRJY47plltuSTgX4Pnnn0eS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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "# select data using grid partitioning methods\n", - "# -------------------------------------------\n", - "size = 50\n", - "\n", - "selector = Medoid()\n", - "selected_medoid = selector.select(X, size=size, labels=labels)\n", - "\n", - "selector = GridPartition(5, \"equisized_independent\")\n", - "selected_p1 = selector.select(X, size=size, labels=labels)\n", - "\n", - "selector = GridPartition(5, \"equisized_dependent\")\n", - "selected_p2 = selector.select(X, size=size, labels=labels)\n", - "\n", - "selector = GridPartition(5, \"equifrequent_independent\")\n", - "selected_p3 = selector.select(X, size=size, labels=labels)\n", - "\n", - "selector = GridPartition(5, \"equifrequent_dependent\")\n", - "selected_p4 = selector.select(X, size=size, labels=labels)\n", - "\n", - "\n", - "graph_data(\n", - " X,\n", - " indices=[selected_medoid, selected_p1, selected_p2, selected_p3, selected_p4],\n", - " labels=[\n", - " \"Medoid\",\n", - " \"equis_independent\",\n", - " \"equis_dependent\",\n", - " \"equif_independent\",\n", - " \"equif_dependent\",\n", - " ],\n", - " title=\"Comparing Partition Based Selectors\",\n", - " xlabel=\"Feature 1\",\n", - " ylabel=\"Feature 2\",\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Compute the diversity of the selected data points" - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "metadata": {}, - "outputs": [ - { - "data": { - "text/markdown": [ - "**Diversity of Selected Sets**\n", - "\n", - "| | logdet | wdud |\n", - "|-------------------|--------------------|---------------------|\n", - "| equis_independent | 118.897 | 0.081 |\n", - "| equis_dependent | 117.838 | 0.079 |\n", - "| equif_independent | 111.146 | 0.104 |\n", - "| equif_dependent | 109.174 | 0.112 |\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "div_measure = [\"logdet\", \"wdud\"]\n", - "set_labels = [\n", - " # \"Medoid\",\n", - " \"equis_independent\",\n", - " \"equis_dependent\",\n", - " \"equif_independent\",\n", - " \"equif_dependent\",\n", - "]\n", - "set_indices = [selected_p1, selected_p2, selected_p3, selected_p4]\n", - "seleced_sets = zip(set_labels, set_indices)\n", - "\n", - "# compute the diversity of the selected sets and render the results in a table\n", - "table_data = [[\"\"] + div_measure]\n", - "for i in seleced_sets:\n", - " # print([i[0]] + [compute_diversity(X_dist[i[1]], div_type=m) for m in div_measure])\n", - " table_data.append([i[0]] + [compute_diversity(X_dist[i[1]], div_type=m) for m in div_measure])\n", - "\n", - "render_table(table_data, caption=\"Diversity of Selected Sets\")" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.5" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Tutorial Partition-Based Selectors\n", + "\n", + "This tutorial demonstrates using partition-based selectors in `selector` package. To easily visualize the data and sampled points, we will use a 2D dataset in this tutorial. However, the same functionality can be applied to higher dimensional datasets.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import sys\n", + "\n", + "# uncomment the following line to run the code for your own project directory\n", + "# sys.path.append(\"/Users/Someone/Documents/projects/Selector\")" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.pylab as plt\n", + "import numpy as np\n", + "from sklearn.datasets import make_blobs\n", + "from sklearn.metrics.pairwise import pairwise_distances\n", + "from IPython.display import Markdown\n", + "\n", + "from selector.measures.diversity import compute_diversity\n", + "from selector.methods.partition import Medoid, GridPartition" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Utility Function for Plotting Data\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "# define a function to make visualization easier\n", + "\n", + "\n", + "def graph_data(\n", + " data,\n", + " indices=None,\n", + " labels=None,\n", + " reference=False,\n", + " title=\"\",\n", + " xlabel=\"\",\n", + " ylabel=\"\",\n", + " number=False,\n", + " fname=None,\n", + "):\n", + " \"\"\"Graphs the data in a scatter plot.\n", + "\n", + " Parameters\n", + " ----------\n", + " data : numpy.ndarray of shape (n_samples, 2)\n", + " The original data points to be graphed.\n", + " indices : list of numpy.ndarray, optional\n", + " List of indices array of the data points selected.\n", + " labels : list of str, optional\n", + " List of labels denoting method for selected indices.\n", + " reference : bool, optional\n", + " Whether to highlight the first data point.\n", + " title : str, optional\n", + " The title of the plot.\n", + " xlabel : str, optional\n", + " The label of the x-axis.\n", + " ylabel : str, optional\n", + " The label of the y-axis.\n", + " number : bool, optional\n", + " Whether to label the selected data points with numbers representing the order of selection.\n", + " fname : str, optional\n", + " Filename for saving the figure. If None, figure is shown.\n", + " \"\"\"\n", + " if data.ndim != 2 or data.shape[1] != 2:\n", + " raise ValueError(f\"Expect data to be a 2D array with 2 columns, got {data.shape}.\")\n", + "\n", + " if labels is not None and len(indices) != len(labels):\n", + " raise ValueError(\n", + " f\"Expect indices and labels to have the same length, got {len(indices)} and {len(labels)}.\"\n", + " )\n", + "\n", + " # Add a title and axis labels\n", + " plt.figure(dpi=100)\n", + " plt.title(title, fontsize=18)\n", + " plt.xlabel(xlabel, fontsize=14)\n", + " plt.ylabel(ylabel, fontsize=14)\n", + "\n", + " # plot original data\n", + " plt.scatter(data[:, 0], data[:, 1], marker=\"o\", facecolors=\"none\", edgecolors=\"0.75\")\n", + "\n", + " colors = [\"skyblue\", \"r\", \"b\", \"k\", \"g\", \"orange\", \"navy\", \"indigo\", \"pink\", \"purple\", \"yellow\"]\n", + " markers = [\"o\", \"x\", \"*\", \"_\", \"|\", \"s\", \"p\", \">\", \"<\", \"^\", \"v\"]\n", + " text_location = [(0.1, 0.1), (-0.1, 0.1)]\n", + " colors_numbers = [\"black\", \"red\", \"blue\", \"k\", \"k\", \"k\", \"k\", \"k\", \"k\", \"k\", \"k\"]\n", + "\n", + " if indices:\n", + " for index, selected_index in enumerate(indices):\n", + " plt.scatter(\n", + " data[selected_index, 0],\n", + " data[selected_index, 1],\n", + " c=colors[index],\n", + " label=labels[index] if labels is not None else None,\n", + " marker=markers[index],\n", + " )\n", + " if number:\n", + " shift_x, shift_y = text_location[index]\n", + " for i, mol_id in enumerate(selected_index):\n", + " plt.text(\n", + " data[mol_id, 0] + shift_x,\n", + " data[mol_id, 1] + shift_y,\n", + " str(i + 1),\n", + " c=colors_numbers[index],\n", + " )\n", + " if reference:\n", + " plt.scatter(data[0, 0], data[0, 1], c=\"black\")\n", + " if labels is not None:\n", + " # plt.legend(loc=\"upper left\", frameon=False)\n", + " plt.legend(loc=\"best\", frameon=False)\n", + " if fname is not None:\n", + " plt.savefig(fname, dpi=500)\n", + " else:\n", + " plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "# define function to render tables easier\n", + "\n", + "\n", + "def render_table(data, caption=None, decimals=3):\n", + " \"\"\"Renders a list of lists in ta markdown table for easy visualization.\n", + "\n", + " Parameters\n", + " ----------\n", + " data : list of lists\n", + " The data to be rendered in a table, each inner list represents a row with the first row\n", + " being the header.\n", + " caption : str, optional\n", + " The caption of the table.\n", + " decimals : int, optional\n", + " The number of decimal places to round the data to.\n", + " \"\"\"\n", + "\n", + " # check all rows have the same number of columns\n", + " if not all(len(row) == len(data[0]) for row in data):\n", + " raise ValueError(\"Expect all rows to have the same number of columns.\")\n", + "\n", + " if caption is not None:\n", + " # check if caption is a string\n", + " if not isinstance(caption, str):\n", + " raise ValueError(\"Expect caption to be a string.\")\n", + " tmp_output = f\"**{caption}**\\n\\n\"\n", + "\n", + " # get the width of each column (transpose the data list and get the max length of each new row)\n", + " colwidths = [max(len(str(s)) for s in col) + 2 for col in zip(*data)]\n", + "\n", + " # construct the header row\n", + " header = f\"| {' | '.join(f'{str(s):^{w}}' for s, w in zip(data[0], colwidths))} |\"\n", + " tmp_output += header + \"\\n\"\n", + "\n", + " # construct a separator row\n", + " separator = f\"|{'|'.join(['-' * w for w in colwidths])}|\"\n", + " tmp_output += separator + \"\\n\"\n", + "\n", + " # construct the data rows\n", + " for row in data[1:]:\n", + " # round the data to the specified number of decimal places\n", + " row = [round(s, decimals) if isinstance(s, float) else s for s in row]\n", + " row_str = f\"| {' | '.join(f'{str(s):^{w}}' for s, w in zip(row, colwidths))} |\"\n", + " tmp_output += row_str + \"\\n\"\n", + "\n", + " return display(Markdown(tmp_output))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Generating Data\n", + "\n", + "The data should be provided as:\n", + "\n", + "- either an array `X` of shape `(n_samples, n_features)` encoding `n_samples` samples (rows) each in `n_features`-dimensional (columns) feature space,\n", + "- or an array `X_dist` of shape `(n_samples, n_samples)` encoding the distance (i.e., dissimilarity) between each pair of `n_samples` sample points.\n", + "\n", + "This data can be loaded from various file formats (e.g., csv, npz, txt, etc.) or generated using various libraries on the fly. In this tutorial, we use [`sklearn.datasets.make_blobs`](https://scikit-learn.org/stable/modules/generated/sklearn.datasets.make_blobs.html) to generate cluster(s) of `n_samples` points in 2-dimensions (`n-features=2`), so that it can be easily visualized. However, the same functionality can be applied to higher dimensional datasets.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Selecting from One Cluster\n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Shape of data = (500, 2)\n", + "Shape of labels = (500,)\n", + "Unique labels = [0]\n", + "Cluster size = 500\n", + "Shape of the distance array = (500, 500)\n" + ] + } + ], + "source": [ + "# generate n_sample data in 2D feature space forming 1 cluster\n", + "X, labels = make_blobs(\n", + " n_samples=500,\n", + " n_features=2,\n", + " centers=np.array([[0.0, 0.0]]),\n", + " random_state=42,\n", + ")\n", + "\n", + "# compute the (n_sample, n_sample) pairwise distance matrix\n", + "X_dist = pairwise_distances(X, metric=\"euclidean\")\n", + "\n", + "print(\"Shape of data = \", X.shape)\n", + "print(\"Shape of labels = \", labels.shape)\n", + "print(\"Unique labels = \", np.unique(labels))\n", + "print(\"Cluster size = \", np.count_nonzero(labels == 0))\n", + "print(\"Shape of the distance array = \", X_dist.shape)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Selecting from One Cluster\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Check Documentation: **[Medoid](https://selector.qcdevs.org/api_methods_partition.html#selector.methods.partition.Medoid) | [GridParition](https://selector.qcdevs.org/api_methods_partition.html#selector.methods.partition.GridPartition)**\n" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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WCxYu3Yt4uLioFKpml3XaWlpeOihhxAWFgaJRAKRSISAgABcc801+L//+7/es8r28tTZgKS0tJT1v1m0aNEV9bV//36iUqlc5qKlUqmL78bff//drF1T/4cff/yR7UOhUBAul8uWTZo0iZjNZvLLL78QiURCABClUkkYhmHrzJ49u0XZnPPDK1asIJMmTSIACI/Hc5EXbcwfL1iwgK3D4/GIu7s74fF47DahUEi2bt3aZtv58+eTO+64gwAgHA6HuLm5EQ6Hw879t+UH0tQH5q+//iIymYwAIHK53EUOjUbTqn/Ptm3bCJ/PZ+vKZDIiEokIAOLr60s2b9582f4CTeXbt29fi3VSUlLYOm+88Uazds5zLpfLXbbdddddxGaztbnPrVu3ssemUCiISCQikydPJu+88w7x8fFhf+MKhcLF/8THx8elz5aO4fbbbyeenp5smaenp0v722+/vUWZWqIrrpFffvmFeHt7EwBEIpEQoVDoMn6JiYntna4WcV4jkydPbrXO//73P3ZfSUlJzcpfeeUVtpzL5RI3NzcX+RiGIRs2bGix74SEBJdrWSgUNvNlaclPJi8vj0RFRbnsQ6lUurR75JFHWtxnVVUVGTFihMu17Tw/DMOQjz/++LJ9dG666SYCgPj7+xO73d6ptk3lu/baa12O5dJju/XWW1v0l2zPJ+att95y8b2USCREIBCw3319fcmZM2dabHv69GkSEBDA1uVwOMTd3d3lXK9bt44QQsi3335LfHx82OtTKpU2uwYLCgrYvmtra0l8fLzL70ilUrn8NpYtW9aiXM5jXr58ORk/fjx7Tt3c3AjDMOx1/dtvv7nIyufzO/ws6G6ootMNfPPNNy430MuloKCA/aFERkaSQ4cOsWUHDx4kQ4cOJQCIu7t7swdx05u4SqUiU6dOJSkpKYQQQhobG8n777/PKjwvvvgiUSqVZPbs2SQvL48QQkh9fT154YUX2D5+//33ZvI5LwClUkmEQiHZuHEjMRgMrOx33nkn2/6nn35q1n7VqlXknXfeIefPnycWi4UQQojNZiPJycnk3nvvZS/goqKiZm2dio5MJiM8Ho+8++67RKfTsbIXFxc3G4e2FB03Nzdy6623kgsXLhBCCDGZTOS7775jFYR58+Y1kyE7O5tVDkeOHElOnTpFCCHEbreT33//nQQFBRE3N7duVXR2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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# select data using grid partitioning methods\n", + "# -------------------------------------------\n", + "size = 50\n", + "\n", + "# selector = Medoid()\n", + "# selected_medoid = selector.select(X, size=size)\n", + "\n", + "selector = GridPartition(nbins_axis=6, bin_method=\"equisized_independent\")\n", + "selected_p1 = selector.select(X, size=size)\n", + "\n", + "selector = GridPartition(nbins_axis=6, bin_method=\"equisized_dependent\")\n", + "selected_p2 = selector.select(X, size=size)\n", + "\n", + "selector = GridPartition(nbins_axis=6, bin_method=\"equifrequent_independent\")\n", + "selected_p3 = selector.select(X, size=size)\n", + "\n", + "selector = GridPartition(nbins_axis=6, bin_method=\"equifrequent_dependent\")\n", + "selected_p4 = selector.select(X, size=size)\n", + "\n", + "\n", + "graph_data(\n", + " X,\n", + " indices=[selected_p1, selected_p2, selected_p3, selected_p4],\n", + " labels=[\n", + " # \"Medoid\",\n", + " \"equis_independent\",\n", + " \"equis_dependent\",\n", + " \"equif_independent\",\n", + " \"equif_dependent\",\n", + " ],\n", + " title=\"Comparing Partition-Based Selectors\",\n", + " xlabel=\"Feature 1\",\n", + " ylabel=\"Feature 2\",\n", + " fname=\"quick_start_compare_partition_methods\",\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Compute diversity of selected points" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "**Diversity of Selected Sets**\n", + "\n", + "| | logdet | wdud |\n", + "|-------------------|-------------------|---------------------|\n", + "| equis_independent | 90.84 | 0.072 |\n", + "| equis_dependent | 90.513 | 0.063 |\n", + "| equif_independent | 75.536 | 0.085 |\n", + "| equif_dependent | 78.987 | 0.09 |\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "div_measure = [\"logdet\", \"wdud\"]\n", + "set_labels = [\n", + " # \"Medoid\",\n", + " \"equis_independent\",\n", + " \"equis_dependent\",\n", + " \"equif_independent\",\n", + " \"equif_dependent\",\n", + "]\n", + "set_indices = [selected_p1, selected_p2, selected_p3, selected_p4]\n", + "seleced_sets = zip(set_labels, set_indices)\n", + "\n", + "# compute the diversity of the selected sets and render the results in a table\n", + "table_data = [[\"\"] + div_measure]\n", + "for i in seleced_sets:\n", + " # print([i[0]] + [compute_diversity(X_dist[i[1]], div_type=m) for m in div_measure])\n", + " table_data.append([i[0]] + [compute_diversity(X_dist[i[1]], div_type=m) for m in div_measure])\n", + "\n", + "render_table(table_data, caption=\"Diversity of Selected Sets\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Comparing Multiple Selection Methods (Multiple Clusters)\n", + "\n", + "Each cluster is treated independently, and if possible, equal number of samples are selected from each cluster. However, if a cluster is underpopulated, then all points from that cluster are selected. This is to ensure that the selected subset is representative of the entire dataset.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Shape of data = (500, 2)\n", + "Shape of labels = (500,)\n", + "Unique labels = [0 1]\n", + "Cluster sizes = 250 250\n", + "Shape of the distance array = (500, 500)\n" + ] + } + ], + "source": [ + "# generate n_sample data in 2D feature space forming 3 clusters\n", + "X, labels = make_blobs(n_samples=500, n_features=2, centers=2, random_state=42)\n", + "\n", + "# compute the (n_sample, n_sample) pairwise distance matrix\n", + "X_dist = pairwise_distances(X, metric=\"euclidean\")\n", + "\n", + "print(\"Shape of data = \", X.shape)\n", + "print(\"Shape of labels = \", labels.shape)\n", + "print(\"Unique labels = \", np.unique(labels))\n", + "size_0, size_1 = np.count_nonzero(labels == 0), np.count_nonzero(labels == 1)\n", + "print(\"Cluster sizes = \", size_0, size_1)\n", + "print(\"Shape of the distance array = \", X_dist.shape)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To select from multiple clusters provide the `labels` argument to the `select` method.\n", + "Check Documentation: **[Medoid](https://selector.qcdevs.org/api_methods_partition.html#selector.methods.partition.Medoid) | [GridParition](https://selector.qcdevs.org/api_methods_partition.html#selector.methods.partition.GridPartition)**\n" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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KVP967ewsJDx48cTFxeHp6dng2vyt99+Y/jw4URERKDVavH29iY2Nparr76a119/nZKSktMYyVbkfM+LXSzk5+dL/jQPPPDA32pr9erVwsfHx23u3svLy80XY926dQ32qz+v/e2330pteHt7C5VKJZUNGDBAWK1W8fPPPwtPT08BCJPJJBQKhVTnjjvuaFS2QYMGCUA8++yzYsCAAQIQarXaTV5AvPjii43uP3LkSKmOWq0Wfn5+bnPpOp1OLF68uNl977vvPnHLLbcIQCiVSuHr6yuUSqXkB9Lc/H59n5Y//vhD8oMwGo1ucoSFhTXpr7NkyRKh0WikugaDQXh4eAhAhIaGik8++UQqO13qy9fUnPq+ffukOtOnT2+wn+ucG41Gt2233XabsNvtzfa5ePFi6di8vb2Fh4eHGDRokHjttddEcHCw9Bv39vZ28ycJDg52a7OxY7j55ptFQECAVBYQEOC2/80339yoTI3RGtfIzz//LIKCggQgPD09hU6ncxu/Xbt2nep0NcqprgEhhBgzZowkZ2O4rjNAaLVa4e/v7+avZzKZGj0+IYS4//773c67wWCQrvOmrgshhFi+fLnbmGo0Grcx1Wq14tNPP220z+3btwtfX1+prl6vl64tb29v8fXXX5+xz41L9rvuuuu09qvPzp07RUREhCSDSqVyuz4UCoWYMWNGo/s2dz1WV1eLW2+9tcG1V/9e2qdPH1FSUtJo25999pl076h/ruvfi3bu3CmEEGLs2LEiODjY7Tde//rp2bOnW9spKSlux+zh4eF2zM3da111PvzwQ6nP+vu7eOmll9yO3dPTs4Fv2fnyDZKVm1biq6++crtpnimZmZnSDSYxMVGsX79eKlu7dq2Ij48XgPDz82vw8K1/4/bx8RFXXHGF2LdvnxDCeRG+9dZbkpLzn//8R5hMJnHHHXeIjIwMIYQQFRUV4rnnnpPaWL58eQP5XDddk8kkdDqdmD9/vqipqZFkr3+h//DDDw32nzZtmnjttdfE3r17hc1mE0IIYbfbRUpKirj77rulB1VOTk6DfV3KjcFgEGq1Wrz++uvCbDZLsufm5jYYh+aUG19fX/Gvf/1LHDhwQAghhMViEV9//bV0Ad97770NZEhNTZVutj169BDbtm0TQgjhcDjE8uXLRbt27dxu8qdLS5SbX375Raozb948IYTTAffhhx8Wy5cvl8ZECCGOHz8u5s6dKzkkz507t9k+DQaDuPbaa6UxEUKIw4cPS/+31KG4qWNoqWNpc8pNa10jvr6+ol+/fmLr1q1CCCFsNptYvny5CA0NFeB8CTgTmlNujh8/LmbNmiUpKk09UJ988knx7rvvisOHD0sKqc1mE5s3bxbDhg0T4FTAq6ur3fZbt26dAKfSP2vWLHH8+HGprLi4WPz2229i5MiRDa6vPXv2SM65Dz74oNi/f7+oq6sTQghx7Ngx8dhjjwlwvpC4xstFeXm5iIqKEoCIiooSv//+u3A4HEIIITZu3Cg6d+7spjSdrnIzePBgqe8vvviiUQW9OXJzcyUldvjw4WLbtm3CarUKIYQoKCgQzz//vKRMfPfddw32b+56vOeeewQgYmNjxRdffCFdezU1NeKHH34QsbGxAhA33XRTg31//vlnSQnq16+fWLdunXRsFotFrFu3Tjz44IPSPbwl8rgoLy8XMTExAhDh4eHil19+kdretWuX6NOnj6TgNKbE178fxMfHi5UrV0r7Hzp0SAghREZGhvQ7Hj9+vNtvqqysTKxbt0489thj0j3yXCMrN63Ef/7zH+kH0diDuaU88sgj0o03Ly+vQXlWVpb0oPr3v//tVlb/xt25c2dRW1vbYP97771XqnPVVVdJN6H6uCwyjVmg6r9RfvTRRw3K7Xa7GDhwoCTD6XLdddcJQEybNq1BWX2rz1tvvdVkGy1VboYMGdLojfKtt96S3j5dCpiLBx54QAAiKCjI7cHh4uDBg24WgNOlJcqNa4zqv9Wdim+++UaAc5VVc3326tVLeqg1RltQblrrGunUqVMD5UAIIX788UepTlZWVrPH2RiufU9eLVX/rTk5OVm8//77p922EELU1dWJbt26CUB8/vnnbmWzZs0SgLj66qtPq83LL79cgNMi2xRjx44VgLjxxhsb7VOr1Yr9+/c32C8vL89N4T9d5Wb16tVuloyQkBBx++23i1dffVX88ccforKystn9R48eLaB5y88bb7whAJGUlNSgrKnf8tq1a6V7QWZmZqPtZmVlSdav+teqzWaTlI/+/fuf1orZlig3r7zyigCn9W3v3r0NysvLy0V0dLQAxHXXXddkH97e3k1eAy5rXFxcXItlP5fIyk0r8eijj0o/CJcl43RxOBzCz8/vlDeZSZMmCUD4+/u7ba9/416wYEGj+/73v/+V6qxcubLROi+//LIAxKWXXtqgzKXcREZGNqoYCSHE77//LvWxZ8+eJo+jMd577z0BiKFDhzYocyk3vr6+zd4MWqrcNGaZEsL5puqqU/9m7XA4pDfQ5qYc6iuQp0tTyk1NTY3YtWuXGDFihJty1lKqq6ul/U5WCOr3+c033zTbzvlWblrzGvnwww8b3ddmswmtVisAsXTp0maPszFc7Tf3iYqKElOmTJEsCKeL6/gefvhht+3vv/++pDw1p6TWxzUmarW6UYXdxbZt2ySlrX7bycnJAhB33313k/s+++yzZ6zcCCHEihUrJIvcyR+NRiOuvfZasWbNmgb71dTUSNM+u3fvbrL94uJiqb38/Hy3sqZ+y6770bhx45qV/frrrxeAeOWVV6Rt9e+RJ1vCTkVLlBvXORkxYkSTdVz3WqVSKcrKyhrt4+SXg/r89ttvApxT8adSMM8HskNxGyI9PV1yvrryyiubrHfVVVcBcPz4cdLT0xut09QS3ODgYOn/Sy+9tNk6paWlTcrgcixujAEDBkiOf9u2bWtQvnv3bh577DG6deuGt7c3SqVScmB77LHHAMjOzm6y70svvbRVlnw2tcooLCxM+r++M1xaWpoUeG7QoEFNtlvfMfbvUN9hUK/X0717d7766isAkpOTpf9dVFRU8NprrzFo0CCCgoLQarXS/p6enlK95sa2X79+rSL72aI1r5Gmzr8rYCLwt5whX3zxRYTzBRIhBHa7nYKCAr788kuEEEyZMoWrr766SefedevWMWrUKDp16oTBYHBzHn311VeBhufyiiuuwMPDg507dzJgwAA++uijJo/fxYYNGwCnc3NiYiIhISGNfoYNGwZAVVUVx48fB8BqtbJ3714ALr/88ib7aK6sJVxxxRXs37+f1atX8+yzz3L55Zfj5+cHOJ3ply5dyqBBg3jhhRfc9tu+fbs0vldffXWTx9a5c2dpH5fT/KlwjdtHH33UZLshISGsWLGiQbsbN24EnCsge/bseYaj0jhWq5U9e/YALbtGHA4HO3bsaLROc/eDXr16ERAQQF5eHr179+add97h4MGDTS5cONfIS8FbCX9/f+n/kpIStwdkSyksLJT+by4+S/1VWIWFhW4rUFwYjcZG962/2uBUdZpaMXUq+Tw8PPD396egoMDtmADeeecdnnzySRwOB+D0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ZWVN0KjOHXfddRevvPIKGzduJDc3d6KHM6F27dpFV1cX8+bNU45Fo1E2btzIT37yE4LBIGq1egJHODGys7MTPm8Apk+fzp/+9KcJGtG5TwQ3R8nIyCAjI+N9z5s/fz56vZ5Dhw5x8cUXAxAOh2lqaqKgoOBMD/OsG+99+fGPf8z//M//KN+7XC6uuOIKfv/737N48eIzOcSzbrz3BOIzNpdddpkyw6dSXVgTpjqdjvnz5/PWW28p5RJisRhvvfUWd91118QObgLJsszdd9/NX/7yF959912KioomekgT7vLLL2f//v0Jx2699VbKysr42te+dkEGNgDLli0bVSagtrZ2Un7enC4iuDkFSUlJ3HHHHTz00EPk5eVRUFDA448/DsANN9wwwaObOPn5+QnfWywWAEpKSi7Y30idTifLly+noKCAH/zgB3R3dyuPXUizFvfeey8333wzCxYsYNGiRTz11FP4/X5uvfXWiR7ahFm1ahW//e1v+dvf/obValXyj5KTkzEajRM8uolhtVpH5RyZzWbS0tIu6Fyk1atXs3TpUr773e9y4403sn37dn72s59dcLPAJ0MEN6fo8ccfR6PRcNNNNxEIBFi8eDFvv/22qDsgJHjzzTepq6ujrq5uVIAny/IEjers+8QnPkF3dzcPPvggHR0dVFRUsH79+lFJxheSZ555BoDly5cnHF+3bt37LnkKF5aFCxfyl7/8hW984xs8+uijFBUV8dRTT/GZz3xmood2zpLkC+lfWEEQBEEQJr0La/FfEARBEIRJTwQ3giAIgiBMKiK4EQRBEARhUhHBjSAIgiAIk4oIbgRBEARBmFREcCMIgiAIwqQightBEARBECYVEdwIgiAIgjCpiOBGEIQTampqet8O6AMDA2d8HO+++y6SJPHwww+f8dc63dauXcutt97K7Nmz0Wg0SJLEu+++O9HDEoRJS7RfEARhXEpKSvjsZz875mMGg+Esj+b88uUvfxmId3fOyMhQ+kgJgnBmiOBGEIRxmTJlynk5a3IueOWVV5g/fz5ZWVnccccdPPvssxM9JEGY1MSylCAIp9W+ffv45Cc/SXZ2NjqdjoKCAu6++256e3tHnfvLX/6Sa6+9lsLCQgwGA6mpqVxxxRW88847Cec9/PDDXHbZZQA88sgjCUtiTU1NQLwBpSRJY47plltuSTgX4Pnnn0eS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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# select data using grid partitioning methods\n", + "# -------------------------------------------\n", + "size = 50\n", + "\n", + "selector = Medoid()\n", + "selected_medoid = selector.select(X, size=size, labels=labels)\n", + "\n", + "selector = GridPartition(5, \"equisized_independent\")\n", + "selected_p1 = selector.select(X, size=size, labels=labels)\n", + "\n", + "selector = GridPartition(5, \"equisized_dependent\")\n", + "selected_p2 = selector.select(X, size=size, labels=labels)\n", + "\n", + "selector = GridPartition(5, \"equifrequent_independent\")\n", + "selected_p3 = selector.select(X, size=size, labels=labels)\n", + "\n", + "selector = GridPartition(5, \"equifrequent_dependent\")\n", + "selected_p4 = selector.select(X, size=size, labels=labels)\n", + "\n", + "\n", + "graph_data(\n", + " X,\n", + " indices=[selected_medoid, selected_p1, selected_p2, selected_p3, selected_p4],\n", + " labels=[\n", + " \"Medoid\",\n", + " \"equis_independent\",\n", + " \"equis_dependent\",\n", + " \"equif_independent\",\n", + " \"equif_dependent\",\n", + " ],\n", + " title=\"Comparing Partition Based Selectors\",\n", + " xlabel=\"Feature 1\",\n", + " ylabel=\"Feature 2\",\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Compute the diversity of the selected data points" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "**Diversity of Selected Sets**\n", + "\n", + "| | logdet | wdud |\n", + "|-------------------|--------------------|---------------------|\n", + "| equis_independent | 118.897 | 0.081 |\n", + "| equis_dependent | 117.838 | 0.079 |\n", + "| equif_independent | 111.146 | 0.104 |\n", + "| equif_dependent | 109.174 | 0.112 |\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "div_measure = [\"logdet\", \"wdud\"]\n", + "set_labels = [\n", + " # \"Medoid\",\n", + " \"equis_independent\",\n", + " \"equis_dependent\",\n", + " \"equif_independent\",\n", + " \"equif_dependent\",\n", + "]\n", + "set_indices = [selected_p1, selected_p2, selected_p3, selected_p4]\n", + "seleced_sets = zip(set_labels, set_indices)\n", + "\n", + "# compute the diversity of the selected sets and render the results in a table\n", + "table_data = [[\"\"] + div_measure]\n", + "for i in seleced_sets:\n", + " # print([i[0]] + [compute_diversity(X_dist[i[1]], div_type=m) for m in div_measure])\n", + " table_data.append([i[0]] + [compute_diversity(X_dist[i[1]], div_type=m) for m in div_measure])\n", + "\n", + "render_table(table_data, caption=\"Diversity of Selected Sets\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.5" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/notebooks/tutorial_similarity_based.ipynb b/notebooks/tutorial_similarity_based.ipynb index 0b2c0872..dffe43f1 100644 --- a/notebooks/tutorial_similarity_based.ipynb +++ b/notebooks/tutorial_similarity_based.ipynb @@ -1,512 +1,512 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Tutorial Similarity Based Selectors\n", - "\n", - "This tutorial demonstrates using distance-based selectors in `selector` package. To easily visualize the data and sampled points, we will use a 2D dataset in this tutorial. However, the same functionality can be applied to higher dimensional datasets.\n" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import sys\n", - "\n", - "# uncomment the following line to run the code for your own project directory\n", - "# sys.path.append(\"/Users/Someone/Documents/projects/Selector\")" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "import matplotlib.pylab as plt\n", - "import numpy as np\n", - "from sklearn.datasets import make_blobs\n", - "from sklearn.metrics.pairwise import pairwise_distances\n", - "from IPython.display import Markdown\n", - "from selector.measures.diversity import compute_diversity\n", - "\n", - "from selector.methods.similarity import SimilarityIndex, NSimilarity" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Utility Function for Plotting Data\n" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "# define a function to make visualization easier\n", - "\n", - "\n", - "def graph_data(\n", - " data,\n", - " figsize=(6, 4),\n", - " indices=None,\n", - " labels=None,\n", - " reference=False,\n", - " title=\"\",\n", - " xlabel=\"\",\n", - " ylabel=\"\",\n", - " number=False,\n", - " fname=None,\n", - "):\n", - " \"\"\"Graphs the data in a scatter plot.\n", - "\n", - " Parameters\n", - " ----------\n", - " data : numpy.ndarray of shape (n_samples, 2)\n", - " The original data points to be graphed.\n", - " indices : list of numpy.ndarray, optional\n", - " List of indices array of the data points selected.\n", - " labels : list of str, optional\n", - " List of labels denoting method for selected indices.\n", - " reference : bool, optional\n", - " Whether to highlight the first data point.\n", - " title : str, optional\n", - " The title of the plot.\n", - " xlabel : str, optional\n", - " The label of the x-axis.\n", - " ylabel : str, optional\n", - " The label of the y-axis.\n", - " number : bool, optional\n", - " Whether to label the selected data points with numbers representing the order of selection.\n", - " fname : str, optional\n", - " Filename for saving the figure. If None, figure is shown.\n", - "\n", - " \"\"\"\n", - " if data.ndim != 2 or data.shape[1] != 2:\n", - " raise ValueError(f\"Expect data to be a 2D array with 2 columns, got {data.shape}.\")\n", - "\n", - " if labels is not None and len(indices) != len(labels):\n", - " raise ValueError(\n", - " f\"Expect indices and labels to have the same length, got {len(indices)} and {len(labels)}.\"\n", - " )\n", - "\n", - " # Add a title and axis labels\n", - " plt.figure(figsize=figsize)\n", - " plt.title(title, fontsize=18)\n", - " plt.xlabel(xlabel, fontsize=14)\n", - " plt.ylabel(ylabel, fontsize=14)\n", - "\n", - " # plot original data\n", - " plt.scatter(data[:, 0], data[:, 1], marker=\"o\", facecolors=\"none\", edgecolors=\"0.75\")\n", - "\n", - " colors = [\"skyblue\", \"r\", \"b\", \"k\", \"g\", \"orange\", \"navy\", \"indigo\", \"pink\", \"purple\", \"yellow\"]\n", - " markers = [\"o\", \"x\", \"*\", \"_\", \"|\", \"s\", \"p\", \">\", \"<\", \"^\", \"v\"]\n", - " text_location = [(0.1, 0.1), (-0.1, 0.1)]\n", - " colors_numbers = [\"black\", \"red\", \"blue\", \"k\", \"k\", \"k\", \"k\", \"k\", \"k\", \"k\", \"k\"]\n", - "\n", - " if indices:\n", - " for index, selected_index in enumerate(indices):\n", - " plt.scatter(\n", - " data[selected_index, 0],\n", - " data[selected_index, 1],\n", - " c=colors[index],\n", - " label=labels[index] if labels is not None else None,\n", - " marker=markers[index],\n", - " )\n", - " if number:\n", - " shift_x, shift_y = text_location[index]\n", - " for i, mol_id in enumerate(selected_index):\n", - " plt.text(\n", - " data[mol_id, 0] + shift_x,\n", - " data[mol_id, 1] + shift_y,\n", - " str(i + 1),\n", - " c=colors_numbers[index],\n", - " )\n", - " if reference:\n", - " plt.scatter(data[0, 0], data[0, 1], c=\"black\")\n", - " if labels is not None:\n", - " # plt.legend(loc=\"upper left\", frameon=False)\n", - " plt.legend(loc=\"best\", frameon=False)\n", - " if fname is not None:\n", - " plt.savefig(fname, dpi=600)\n", - " else:\n", - " plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], - "source": [ - "# define function to render tables easier\n", - "\n", - "\n", - "def render_table(data, caption=None, decimals=3):\n", - " \"\"\"Renders a list of lists in ta markdown table for easy visualization.\n", - "\n", - " Parameters\n", - " ----------\n", - " data : list of lists\n", - " The data to be rendered in a table, each inner list represents a row with the first row\n", - " being the header.\n", - " caption : str, optional\n", - " The caption of the table.\n", - " decimals : int, optional\n", - " The number of decimal places to round the data to.\n", - "\n", - " \"\"\"\n", - "\n", - " # check all rows have the same number of columns\n", - " if not all(len(row) == len(data[0]) for row in data):\n", - " raise ValueError(\"Expect all rows to have the same number of columns.\")\n", - "\n", - " if caption is not None:\n", - " # check if caption is a string\n", - " if not isinstance(caption, str):\n", - " raise ValueError(\"Expect caption to be a string.\")\n", - " tmp_output = f\"**{caption}**\\n\\n\"\n", - "\n", - " # get the width of each column (transpose the data list and get the max length of each new row)\n", - " colwidths = [max(len(str(s)) for s in col) + 2 for col in zip(*data)]\n", - "\n", - " # construct the header row\n", - " header = f\"| {' | '.join(f'{str(s):^{w}}' for s, w in zip(data[0], colwidths))} |\"\n", - " tmp_output += header + \"\\n\"\n", - "\n", - " # construct a separator row\n", - " separator = f\"|{'|'.join(['-' * w for w in colwidths])}|\"\n", - " tmp_output += separator + \"\\n\"\n", - "\n", - " # construct the data rows\n", - " for row in data[1:]:\n", - " # round the data to the specified number of decimal places\n", - " row = [round(s, decimals) if isinstance(s, float) else s for s in row]\n", - " row_str = f\"| {' | '.join(f'{str(s):^{w}}' for s, w in zip(row, colwidths))} |\"\n", - " tmp_output += row_str + \"\\n\"\n", - "\n", - " return display(Markdown(tmp_output))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Generating Data\n", - "\n", - "The data should be provided as:\n", - "\n", - "- either an array `X` of shape `(n_samples, n_features)` encoding `n_samples` samples (rows) each in `n_features`-dimensional (columns) feature space,\n", - "- or an array `X_dist` of shape `(n_samples, n_samples)` encoding the distance (i.e., dissimilarity) between each pair of `n_samples` sample points.\n", - "\n", - "This data can be loaded from various file formats (e.g., csv, npz, txt, etc.) or generated using various libraries on the fly. In this tutorial, we use [`sklearn.datasets.make_blobs`](https://scikit-learn.org/stable/modules/generated/sklearn.datasets.make_blobs.html) to generate cluster(s) of `n_samples` points in 2-dimensions (`n-features=2`), so that it can be easily visualized. However, the same functionality can be applied to higher dimensional datasets.\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Selecting from One Cluster\n" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Shape of data = (500, 2)\n", - "Shape of labels = (500,)\n", - "Unique labels = [0]\n", - "Cluster size = 500\n", - "Shape of the distance array = (500, 500)\n" - ] - } - ], - "source": [ - "# generate n_sample data in 2D feature space forming 1 cluster\n", - "X, labels = make_blobs(\n", - " n_samples=500,\n", - " n_features=2,\n", - " centers=np.array([[0.0, 0.0]]),\n", - " random_state=42,\n", - ")\n", - "\n", - "# compute the (n_sample, n_sample) pairwise distance matrix\n", - "X_dist = pairwise_distances(X, metric=\"euclidean\")\n", - "\n", - "print(\"Shape of data = \", X.shape)\n", - "print(\"Shape of labels = \", labels.shape)\n", - "print(\"Unique labels = \", np.unique(labels))\n", - "print(\"Cluster size = \", np.count_nonzero(labels == 0))\n", - "print(\"Shape of the distance array = \", X_dist.shape)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### NSimilarity based methods\n", - "\n", - "Check Documentation: **[NSimilarity](https://selector.qcdevs.org/api_methods_similarity.html#selector.methods.similarity.NSimilarity)**\n" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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ADoex6uvvhoA8N///hdLlizBl19+edYA2kOHDgFolQEICQnp9PPEE08AAMrLy9llT5w4AbfbDQC47LLLOt1GV/O6Q2+vJc++mUwmhIWFdbpvt99+e4d96wqdTse2XbVqVafrDQ0NZQOR2677999/B9D6zBGJRH04Mh05ceIEK1zYnefdqVOnOg2Q7+panDdvHhiGwddff425c+di+/btZw1u7w68Pq9hiPH392f/r6ur83rwdRfPjRJAl/oibbOSDAYDYmNjO7SRy+U+l/UYE91p09kJcrb+iUQi+Pv7o7q62mufgNab1D333MPeQBiGgVKphFAoBNCaUdDY2OiV4dSeoKCgTuf1hO4co7bHoK2KZVe/70Bow9x888149tlnkZWVhUceeaTLzAoAuP7669kbTlsiIyNx9OjRDtPFYjFuuOEG3HDDDQBao+0zMjLw1ltv4b333kNLSwtuuukmFBUVISQkpEd97+w4A38d657+Fn3BYDBg1qxZyM7OZqeJRCIEBASAy+UCaP2t3W73oJyHXXHppZciNTUVZ86cwbvvvssaD0VFRdi7dy8A4O9//7vXMj397dvD4/EQGxuLhx56CBKJBHfffTeeeeYZzJ0718tYb2lpwdVXX832A2g1sNVqNfh8PoDWe6HD4ehwHG+++WZkZGTglVdewY4dO7Bjxw4AQEJCAmbPno3bbrsNEydO9FrG86CxWq2wWq1n3Y+2+le9ubf2lt5cS559czgcnWaHtsVisXSrL20fzmczCj20PW5VVVUAgOjo6G4t2xN6+ps4nU7U1dV5vch46OpavPjii/HMM8/gsccew+7du7F79252vbNmzcLy5cu9sp26y7D3tIwePZr9/+TJk0PYk3OX3Nxc3HvvvXC73Vi0aBEyMjJgtVpRX1/PClt5RKw8FrgvPA+WoWSwxaEYhmFFyr744gscOXKky/Z1dXWorq7u8OmufDiPx8OFF16Ibdu24fHHHwcANDc3sw+X4cw//vEPZGdnw9/fH//73/+g1+thsVhQU1PDnoceo/RcOA893pZ33nmH7Y/n/zFjxmDatGle7fv627dl1apV7Lm+fft2r3lPP/009u7dC7FYjBdffBHl5eWwWq0wGo3scfR4M30dx5deegn5+fnYtGkT5s6dC5VKhaKiIrz22muYNGkS7r33Xq/2LpcLALB48WIvz1Bn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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "# select data using n-similarity methods\n", - "# -------------------------------------------\n", - "size = 50\n", - "\n", - "# Baroni-Urbani-Buser\n", - "# selector = NSimilarity(similarity_index=\"BUB\", preprocess_data=True)\n", - "# selected_bub = selector.select(X, size=size)\n", - "\n", - "# Jaccard-Tanimoto\n", - "selector = NSimilarity(similarity_index=\"JT\", preprocess_data=True)\n", - "selected_jt = selector.select(X, size=size)\n", - "\n", - "# Austin-Colwell\n", - "selector = NSimilarity(similarity_index=\"AC\", preprocess_data=True)\n", - "selected_ac = selector.select(X, size=size)\n", - "\n", - "# Russel-Rao\n", - "selector = NSimilarity(similarity_index=\"RR\", preprocess_data=True)\n", - "selected_rr = selector.select(X, size=size)\n", - "\n", - "# Faith\n", - "selector = NSimilarity(similarity_index=\"Fai\", preprocess_data=True)\n", - "selected_fai = selector.select(X, size=size)\n", - "\n", - "\n", - "graph_data(\n", - " X,\n", - " figsize=(6, 4),\n", - " indices=[selected_jt, selected_ac, selected_rr, selected_fai],\n", - " labels=[\n", - " \"Jaccard-Tanimoto\",\n", - " \"Austin-Colwell\",\n", - " \"Russel-Rao\",\n", - " \"Faith\",\n", - " ],\n", - " title=\"Comparing N-Similarity-Based Selectors\",\n", - " xlabel=\"Feature 1\",\n", - " ylabel=\"Feature 2\",\n", - " fname=\"quick_start_compare_partition_methods.png\",\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Compute diversity of selected points\n", - "\n", - "The similarity of a set of points can be computed using the `SimilarityIndex` class and an appropriate similarity index (Check Documentation: **[SimilarityIndex](https://selector.qcdevs.org/api_methods_similarity.html#selector.methods.similarity.SimilarityIndex)**). The diversity of the set can then be computed as `1 - similarity_index`." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": {}, - "outputs": [ - { - "data": { - "text/markdown": [ - "**Diversity of Selected Sets: row = selected set, column = 1 - similarity index**\n", - "\n", - "| | JT | AC | RR | Fai |\n", - "|------------------|---------------------|--------------------|---------------------|---------------------|\n", - "| Jaccard-Tanimoto | 0.442 | 0.463 | 0.442 | 0.442 |\n", - "| Austin-Colwell | 0.442 | 0.463 | 0.442 | 0.442 |\n", - "| Russel-Rao | 0.442 | 0.463 | 0.442 | 0.442 |\n", - "| Faith | 0.442 | 0.463 | 0.442 | 0.442 |\n" - ], - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The selected sets coincide for all similarity indices.\n", - "This is due to the fact that the data has low dimensionality\n", - "\n" - ] - } - ], - "source": [ - "set_indices = [selected_jt, selected_ac, selected_rr, selected_fai]\n", - "sim_idx_list = [\"JT\", \"AC\", \"RR\", \"Fai\"]\n", - "set_labels = [\"Jaccard-Tanimoto\", \"Austin-Colwell\", \"Russel-Rao\", \"Faith\"]\n", - "selected_sets = zip(set_labels, sim_idx_list, set_indices)\n", - "\n", - "scaled_data = NSimilarity()._scale_data(X)\n", - "\n", - "# The similarity of a set of data points\n", - "table_data = [[\"\"] + sim_idx_list]\n", - "for i in selected_sets:\n", - " table_data.append(\n", - " [i[0]]\n", - " + [\n", - " 1 - SimilarityIndex(method=\"esim\", sim_index=si)(scaled_data[i[2]])\n", - " for si in sim_idx_list\n", - " ]\n", - " )\n", - "\n", - "caption = \"Diversity of Selected Sets: row = selected set, column = 1 - similarity index\"\n", - "render_table(table_data, caption=caption)\n", - "\n", - "print(\n", - " \"The selected sets coincide for all similarity indices.\\n\"\n", - " \"This is due to the fact that the data has low dimensionality\\n\"\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Comparing NSimilarity based Selection Methods (Multiple Clusters)\n", - "\n", - "Each cluster is treated independently, and if possible, equal number of samples are selected from each cluster. However, if a cluster is underpopulated, then all points from that cluster are selected. This is to ensure that the selected subset is representative of the entire dataset.\n" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Shape of data = (500, 2)\n", - "Shape of labels = (500,)\n", - "Unique labels = [0 1]\n", - "Cluster sizes = 250 250\n", - "Shape of the distance array = (500, 500)\n" - ] - } - ], - "source": [ - "# generate n_sample data in 2D feature space forming 3 clusters\n", - "X, labels = make_blobs(n_samples=500, n_features=2, centers=2, random_state=42)\n", - "\n", - "# compute the (n_sample, n_sample) pairwise distance matrix\n", - "X_dist = pairwise_distances(X, metric=\"euclidean\")\n", - "\n", - "print(\"Shape of data = \", X.shape)\n", - "print(\"Shape of labels = \", labels.shape)\n", - "print(\"Unique labels = \", np.unique(labels))\n", - "size_0, size_1 = np.count_nonzero(labels == 0), np.count_nonzero(labels == 1)\n", - "print(\"Cluster sizes = \", size_0, size_1)\n", - "print(\"Shape of the distance array = \", X_dist.shape)" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAiUAAAGTCAYAAAD3FmIeAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8hTgPZAAAACXBIWXMAAA9hAAAPYQGoP6dpAAEAAElEQVR4nOydd3Qc1dmHn23aol3tqvdmq1guko0LHRswYFowxfRiIBAgQAKhB0INvZgWSPiIHUiC6TVAKAEDxr3Isi3JstV7XWm1klZb7veHmIvWKpaNi2zPc84eyzszd+7Mzsx95y2/qxFCCFRUVFRUVFRU9jHafd0BFRUVFRUVFRVQjRIVFRUVFRWVUYJqlKioqKioqKiMClSjREVFRUVFRWVUoBolKioqKioqKqMC1ShRUVFRUVFRGRWoRomKioqKiorKqEA1SlRUVFRUVFRGBapRoqKioqKiojIqUI0Sld1OeXk5Go0GjUZDeXn5vu7OfsusWbPQaDTcd999e33fixYtQqPRkJaWtlPL9hb78tyo7Br33XcfGo2GWbNm7euu7BSj4Xo/mDhgjRK/389bb73FpZdeSlZWFg6Hg5CQEGJiYjjqqKO488472bhx477upsoo49tvv5UGlUaj4YMPPhh2/bS0tGEHRyEEb7/9NmeeeSapqamYzWasVitjx47lqKOO4uabb+b999+no6Nj9x/MQcqCBQu47777WL9+/T7ZvzKIDfYxm82kpaVx7rnn8tlnn+2T/u2vqPdSH+vXr+e+++5jwYIF+7orewT9vu7AnmD58uVcdtllbNmyRX5nMBiw2Wy0tLSwdOlSli5dyqOPPspZZ53FG2+8QUhIyD7s8YGFwWAgOztb/r0/c9ddd3H66aej0+l2elun08ncuXNZsmSJ/E6v12OxWKisrKS0tJSlS5fyzDPPsHDhQubPnx+0fUpKCtnZ2URFRf3Sw9hp7HY72dnZJCYm7vV9j4Thzs2CBQuoqKggLS2NyZMn7/3O9SMqKkpeO0IIWltbqaiooKKigrfffpvLL7+cv//97/u0j/sDv/ReOpBYv349999/P6mpqfz+97/f193Z7RxwnpKPP/6YWbNmsWXLFiIjI3nkkUfYsmULvb29tLS00Nvby6pVq7jjjjsICwvjvffeo6ura193+4AiMTGRoqIiioqKRu2gNlIKCwv5xz/+sUvbXnrppSxZsgSdTscf/vAHtmzZgsfjoaWlhe7ubvLz83nsscfIy8sbdPvXXnuNoqIirr/++l9yCLvEmWeeSVFREV9//fVe3/dI2JfnZmdYtWoV9fX11NfX09DQgMfjYf369ZxwwgkALFy4kDfeeGMf93L080vvJZX9hwPKU1JSUsLFF1+Mx+Nh/Pjx/Pe//yUpKSloHZ1Ox7Rp05g2bRq33norV1xxxT7qrcpo57TTTuOTTz7h3nvv5cILL8RkMo1425KSEj7++GMAHnroIe64446g5Xq9ntzcXHJzc7ntttvo7u7erX1XGZ1otVry8vJ4//33SUxMpL29nQ8++IALLrhgX3dt1KLeSwcXB5Sn5O6776ajowOTycT7778/wCDZnoiICD744APsdvuAZfX19dx6661MmDCB0NBQQkNDmTBhArfddhsNDQ2Dtrd9gmdFRQVXXXUVKSkpmEwmxo4dy913343b7ZbbbNy4kYsvvpjk5GRMJhOZmZk89NBDeL3eQffRP8Gvt7eXRx99lNzcXEJDQwkPD+eEE04YNlZdX1/P888/zxlnnEFOTg52ux2z2UxGRga//vWv2bRp05Dbzp8/H41Gw/z58xFC8H//938cddRRREZGotFoWLRo0aDnoT/9czYAtm7dyhVXXEFycjJGo5GkpCSuuuoqampqhuwHQEFBAeeddx5xcXGYTCbGjBnDDTfcQGNj44B97Cr33HMPVquV6upqnn/++Z3atn8+wxlnnLHD9c1m84DvhkvmVHJZFi1aRFdXF/fddx85OTlYLBYSEhK45JJLKCsrk+s3Nzdz++23k5WVhdlsJi4ujl//+tdDXsu7mtzn9Xr56KOPuPrqq5k2bRrx8fEyl+ukk07ijTfeQAgx6Lbb/27r1q3joosuIikpCYPBEJQgOdi5URIpKyoqALj88ssH5HQAvPzyy2g0GiIiIujp6RnyWAKBwA5zhnaV0NBQMjIyAOjs7Bx0319//TU33ngjhx12GElJSYSEhBAZGcnMmTN5+eWXh3xGALS1tfGnP/2JQw45hLCwMEJCQoiLiyM3N5drrrlmWA/Y0qVLufjii0lNTcVkMmG325kxYwaPPfbYoH3tz2effcYJJ5yAw+HAarWSl5fH448/Pmxfd8TuuJcUNm7cyNVXX01mZiYWiwWr1Upubi5//OMfaW5u3uU+ulwuHn30UQ4//HAiIiIwGo0kJydz/vnns2zZsh1u/8UXX3D++efLXJmIiAhyc3O54YYbgrbXaDRcfvnlAFRUVAy4vge7TtetW8ell14qf8/w8HCOOOIIFixYgMfjGbQ/29//33zzDXPnziU+Ph6dThcUHuvu7ubJJ5/k8MMPJzw8HIPBQHR0NOPHj+eyyy7j3XffHfmJBBAHCPX19UKr1QpAXHnllb+orW+//VY4HA4BCECEhoaK0NBQ+f/w8HDx/fffD9iurKxMrvPuu+/KNsLCwoROp5PLjj76aNHb2ys++eQTYbFYBCDsdrvQaDRynfPOO2/Qvs2cOVMA4s477xRHH320AIRerw/qLyDuvffeQbe/7LLL5Dp6vV5EREQIvV4vvzMajeKdd94ZdttLL71UnH322QIQWq1WhIeHC61WKxYuXDjgPJSVlQW18c0338hl//vf/4TVahWAsNlsQf1ISEgQ1dXVg/bjvffeEwaDQa5rtVqFyWQSgIiPjxcLFy6Uy3aW/v0rKysT9957r/zN29raBqyfmpo66Pl+6623ZDtffPHFTvdDiJ9/68F+S2W/CxYsEJMmTRKAMJlMwmw2y/3Gx8eLsrIysW3bNpGeni4AYbFYREhIiFwnMzNTtLe3D2hfOYepqak7taz/+VOufZvNFvTdvHnzhN/vH3bbd955R/7GYWFhwmQyiZkzZw57bp544gkRGxsrnwNhYWEiNjY26COEEB0dHfK6e/3114c8/5999pkAhE6nE5WVlUOuN9T5Gez6V3C73cJutwtA3HTTTQOW97+HlGtcWb//c6Srq2vAtlVVVSIlJUWup9yj/Z9B/c+lgt/vFzfeeOOA/fbfLjs7W5SXlw96TMq9onwcDoe8p4855hhx5513Drnv4dgd95IQQjz22GPy2hjsXoiPjxdr164dsN1w17sQQqxbt04kJSXJdnQ6XdA1r9FoxMMPPzzotm63W8ybNy/ovNlstqDfOi8vT64fGxsrwsLC5O+6/fX9xBNPBLX/9NNPB40rdrs96NmZm5sramtrhz3mBQsWyDaU7S+77DIhRN+9lJeXF3Ss/X/34c7bUBwwRskbb7whT8Inn3yyy+1UVlbKAX78+PHihx9+kMu+++47kZ2dLQARERExYNDs/yBxOBzi+OOPF5s2bRJCCNHV1SWee+45eYPffffdwm63i/POO0/e5C6XS/zxj3+UbXz55ZcD+qc8jO12uzAajeLll18W3d3dsu/nnHOO3P7DDz8csP2DDz4onnjiCVFQUCC8Xq8Qou9htHHjRnHRRRdJI6ympmbAtopRYrVahV6vF08++aQc0Fwul7y4R2qUhIeHi1/96leisLBQCCGEx+MRb775pryhL7nkkgF92LZtmzTkDjnkELF69WohhBCBQEB8+eWXIjU1VYSHh+82o6Sjo0NER0cLQNx+++0D1h/KKCkrK5M38qRJk0RxcfFO92UkRonD4RBpaWniiy++EH6/X/h8PvHFF1/IPp977rlixowZYvLkyWLZsmVCCCF6e3vFm2++Kc/jH//4xwHt76pRsmLFCvGb3/xGfPnll0HGTktLi3j22WflA/XZZ58dsG3/c2+1WsUpp5wirw0hhNiyZctOnRvFSB6Ma665Rg6WQ3HWWWcJQJx22mlDrjMYwxklgUBAbNiwQcyZM0cAwmw2i61btw5oo6qqSlx00UXio48+Ei0tLfJ7l8slFi5cKBISEoY0aK688koBiLS0NPHVV18Jn88nhBDC5/OJ8vJy8dJLLw16Ld99990CEDExMeLFF1+U++3t7RXffPONmDJlirzvtjcqP/zwwyCjUzHiurq6xIsvvihCQkLkc3VnjZLdcS/93//9n7yu/vznP4u6ujp5TlavXi2OO+44AYikpCThcrmCth3ueq+trRUxMTECEGeddZZYvXq16O3tFUII0dDQIO655x45QL///vsDtj/33HOlgXH77beLqqoquaypqUn861//Etdcc82I+9Ofjz/+WP4mZ5xxhigtLRVC9D1nX3vtNfmcPeKII+Q1sv0+TCaT0Ol0Yv78+fI39fl88pp98MEH5Xj47rvvip6eHiFE35hSU1MjXnvtNXHVVVcN28/tOWCMEuWGAgYdUEeK8rAKDw+XF25/qqqq5IP1t7/9bdCy/oPxhAkT5A/Un0suuUSuc8IJJ4hAIDBgHcUDMpjHR3kYA+LVV18dsNzv94tjjjlG9mFnOfXUUwUgHnzwwQHL+ntZnnvuuSHbGKlRcuyxxw76xvzcc8/JB7ZiOCkoD9yYmJigh7VCUVGRMBqNu80oEUKIZ599VvZn+2trKKNECCGuuuqqoDeIKVOmiOuuu068+uqroqCgYNDfvj8jGXjNZrMoKSkZsPzVV1+V+46NjRXNzc0D1rnnnnsEIMaOHTtg2a4aJTvi7bffHnKf/c/9jBkzBjwo+/NLjZL169fLfRUVFQ1YXl9fL98oP/rooxEdm0J/oyQqKiroTVZp02Qyiblz54r8/Pydalth1apV8gVCeSlRyMnJEYD497//PeL2ysrKhE6nE2azWaxfv37QdTo6OqRHYPsBdvz48dLgGOyefvnll+U52VmjRIhfdi91dHRIg+jzzz8fdB2v1yumTp0qAPHMM88ELRvuer/iiisEIC688MIh9//0008LCPZ4CCHEV199JY/pL3/5y5Dbb89I7z/lOjj66KMHvZc++ugjuf+333570H0oxtZQnHzyyQIY0hO0KxwwOSUtLS3y74iIiF1qQwjBW2+9BcA111xDXFzcgHWSkpK45pprAFi8ePGQbd10000YjcYB35900kny7zvuuGPQvAdlnQ0bNgzZfnJysowt9ker1XL33XcDsGnTJgoKCoZsYzBOPfVUAH744Ych1wkPD+c3v/nNTrU7GHfddRda7cBLUIkbd3d3U1JSIr8XQsj45LXXXjvo75ydnc255577i/vWn2uuuYb09HS6u7t3KrfgL3/5C/fccw+hoaEIIVi3bh1/+ctfuPLKK5k0aRJxcXHcfPPNQ+Z1jISzzz5b5ib0p/91dvXVVxMZGTnkOtu2bQvKc9qTKNfXtm3bqK+vH3K9W2+9dZfKsEdKXl4ehx9+OAB/+9vfBixfuHAhXq+XpKQkTjnllF3eT3NzMw0NDfKj5FZ4PB6cTie1tbW71O60adOIiYnB7XYP0GNxOBwA1NXVjbi9RYsW4ff7mTNnzpAVLDabjblz5wLw3//+V36/YcMGNm/eDPTl9Q12T1911VW/qBLvl9xL7777Lk6nkylTpgTdF/3R6/Uy2bj/sQ1HT08P//73vwG4/fbbh1zv0ksvBSA/Pz+of0op+MSJE7n22mtHtM+RsmHDBgoLC4G+32Swe+n0009nxowZAMNWgN15551DLtuVa21HHDBGye6grKyM1tZWAGbPnj3keko5X0tLS1AyYX+UH3t7YmNj5d/Tp08fdp22trYh+6Ak+g3G0UcfjV7fV1i1evXqAcvz8/O57rrryM3NJSwsDK1WKxOlrrvuOgCqq6uH3Pf06dN3i67LoYceOuj3CQkJ8m/l9wAoLS3F6XQCMHPmzCHb3d2KkSEhITz44INA34OkuLh4RNvp9XoeeOABampqeP311/n1r39NXl6ePHeNjY0888wzTJw4kZUrV+5S33bHdQbI87o7cLlcPPHEE8ycOZOYmBhCQkLk9WWxWOR6w11jRx555G7rz1AoLxevvfYavb298nvxUxI3wJVXXvmLjKOysjJEn0caIQQej4fCwkJuvfVWvvvuO0499VT+8pe/DLptb28vL7/8MieeeCIJCQkYjcagpMbGxkZg4Hk87bTTgL6XnquvvprPP/98h4JiS5cuBfoSLuPi4ob8LFy4EEAmE8PPzxi9Xs/RRx89aPtarfYX3Ze/5F5Sjq2wsHDYY3vggQcGHNtwrFmzRiZKn3jiiUO2O2HCBLlN/7Z//PFH4Offa3fS/zcZ7lmpjGWDjRPQlzR8yCGHDLm90vcXXniBCy64gA8++OAXJQzDAVQS3P9NsLW1NWhgGynKTQ4Ma9X3r+ppbGwkPT19wDo2m23QbRVjYSTrDJexPlz/TCYTkZGRNDQ0BB0T9F08v/vd7wgEAkBfNrfdbpdene7ubjo6OoZ9c46JiRly2c4wknPU/xw0NTXJv4f7ffeENsqFF17IE088QX5+PnfddddOZZTb7XYuvvhiLr74YqDvDeuHH37gueee4+OPP6a5uZmzzz6bkpKSnSo7ht1zncHw19rOsGXLFo4//viggdJiseBwOOQbtPK2uDeuseE499xzuemmm2hubua9997j/PPPB+B///sf27ZtQ6fT8etf/zpom+nTp1NVVTWgrSOOOIL33ntvh/sMCQlh3LhxPPbYY/h8Pp5++ml+97vfcdJJJzF27Fi5XmNjI7Nnzw7ydJpMpiAxtqamJgKBwIDzeOutt5Kfn89bb73FK6+8wiuvvIJGo2HChAnMmTOHX//611LcUEHx2Ljd7hF5zfprOynPmKioqEG9wwo7qoYcCbtyLynH1tPTM2y1lcJIdav6e7lG6u3s37biKUxNTR3RtjvDzv4m248TCpGRkYN6vhQuvPBCVq5cyfPPP8/ixYtl9CAjI4MTTzyRK664gqlTp+5U3w8YT0l/a3TdunX7sCejl8LCQn7/+98TCASYN28eK1eupKenh7a2Ninw9PTTTwMMWbYJ7FG3+kj5peW+u7K/Rx55BID33nuPFStW7HJbJpOJ2bNn89FHH3HZZZcBfW+7n3/++W7p677k8ssvp7q6mrS0NN5++21aWlpwu900NjZSX18fVOq9r68xk8kkSxv7h3BeeeUVAE4++eQBA2lTU1NQOEb59PfojRTF4PH5fLz99ttBy2666SYKCgqIjIzk73//O3V1dXR3d9PU1CTvVcUw3/48GgwG3nzzTdavX8+f/vQnjjvuOCwWCxs3buTJJ59kwoQJPPXUU0Hb+P1+oC8M0d+zM9Tn22+/3enj3ROM5F5Sju28884b0bGNdL4upV3oe5kbSdv9vUV7+xm2K4zkPlywYAHFxcU8/PDDnHzyyTgcDrZu3cpf/vIXpk2bttOqsweMUXLsscdKi+7999/fpTb6v50N51ruv2xvvNENxnA6HorSIQT375133sHv95OTk8PixYsHDcMMF+ff10RHR8u/h4vF70jjZFc5+eST5UNlewGnXeXqq6+Wf480LDRaqaqqki7pN954g3POOWdA3s9ou75+85vfoNFo+Pbbb9m6dSvNzc3y+TFY3lR5efluG6T7vyH3DwN7vV7pdXnhhRe4/PLLB+S3+f3+HbrJ8/LyuP/++/n6669xOp189dVXHHPMMfj9fulNUVDaH2nooj/KM6a5uTkoDLY9e+q+VBjqXvolxzYc/X+TXWl7T/ULgn+TobRI4Oex7JeOYxkZGdx55518+umntLS0sGzZMpl/9Oyzz/LRRx+NuK0DxiiJjY3l7LPPBuDf//530Lw3O0J500hPT5cP0eHEhb766iugz7U1WOhmb7BkyZIh3zS///57fD4f0JcQp6C4nfPy8oZ0ySnHNhoZM2aMTKwabhDYk29xjz76qNzH7phQzWq1yr+Hc7PuD/QPa0yZMmXQdfbG9aVc28N5YhSysrI47rjjEELwyiuvyPyS5ORkTj755D3az/4vN6GhofLvpqYmGWYY6jz+8MMPIwpFKOj1eo4//nj+85//YDQaEUIE/RZKDs9XX321U+3Cz88Yn8/H999/P+g6gUBgj3tXhrqXlGNbs2bNbk3I7P9SpyjO7gxHHHHELm07kuu7/2/Sf76g7VGugaHyznYFrVbLYYcdxjvvvENKSgoAX3755ci33209GQU89NBDWK1Wuru7Oeuss3Zombe1tXH22WfT3t4O9LnTzjvvPAD++te/DvpWV1tby1//+leAfSoNXVlZOeicLIFAgIcffhiA8ePHM2nSJLlMUa4tKCgY9IL+7LPPRo1bdjA0Gg1nnXUW0KfKOVgicElJiayg2hMceuihsg933nnnkA+GsrKyERnG/X/D4RLK9gf6KyP3fwtXcLlcPPTQQ3u8H2FhYcDIk3eVhNdFixbJMM4VV1yxx0NISuUGBL88hIWFSdf+YOfR5/Pxxz/+cch2h3szNhqN8rj6v5hcccUV6PV6mpubuffee4ftd29vb5Cya25uLjk5OQD8+c9/lvlq/fn73/8+rPd5OH7pvTRv3jwcDgder5ebb7552ME8EAiM+LoJDQ3lwgsvBOCxxx6jsrJy2PW3D/FdeeWVQF+V5EsvvTSifcLIru/c3FzGjx8P9I2L/UNNCp9++qkMQ+/qWDbctabT6aTRNlxeygB2W3HxKOH999+XKn1RUVHi0UcfDdJx8Pl8Yu3ateKee+6Rtev9lTqrqqrk9xMmTBBLly6Vy3744QdZ+70j8bShlBz7azEMxXB16P3F00wmk/jb3/4WJJ6miPEA4r333gvatn9d/LXXXit1Pjo7O8XLL78sLBaLiIyMHHLfik6JouY3FCPVKRkOZZ1vvvkm6PuSkhKpWjpt2jSpwBgIBMTXX38t0tPTd6t42mAUFRUFqVwyiF7Gxx9/LLRarTjllFPEP/7xj6C2ent7xdq1a8X8+fODdDm213f4pVocQ51DheF+p13RKfH7/VJJdMKECVLYTgghfvzxR3HIIYfI62uwfo302hBi+HOjiAAeccQRorW1dYdteb1eERcXJ/et0+mCRKx2lh0pura2topnnnlGapakpaUN0Bo56qijBCASExPF119/La+NgoICccIJJwij0ShVpre/BmJjY8Udd9whli1bFqSVVFJSItVDtVqtFHZUuP/++2W/L7nkElFQUBB0jtatWyfuv/9+kZycPEDR+r333pPbnnfeefL8dXd3i5deekkYjcZdFk/bHffSokWL5PKTTz5ZLF++XK7j9/vF5s2bxZNPPinGjRs3QOV3R+JpipBdQkKCeO2110RHR4dc3tjYKN555x0xd+5cceKJJw7Y/vzzz5e/xx133DFAPO2VV14RV1xxRdA2JSUl8ljefPPNYc+bst7cuXOleFpvb6/45z//KfW2hhNP25EWSl5enrjhhhvEN998Izo7O+X3NTU14vrrr5f7H0ofZjAOOKNEiD7jISMjI2jQCAkJEREREUEywxqNRlxwwQVSgU/h22+/DZL53V5m3uFw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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "# select data using n-similarity methods\n", - "# -------------------------------------------\n", - "size = 50\n", - "\n", - "# Jaccard-Tanimoto\n", - "selector = NSimilarity(similarity_index=\"JT\", preprocess_data=True)\n", - "selected_jt = selector.select(X, size=size, labels=labels)\n", - "\n", - "# Austin-Colwell\n", - "selector = NSimilarity(similarity_index=\"AC\", preprocess_data=True)\n", - "selected_ac = selector.select(X, size=size, labels=labels)\n", - "\n", - "# Russel-Rao\n", - "selector = NSimilarity(similarity_index=\"RR\", preprocess_data=True)\n", - "selected_rr = selector.select(X, size=size, labels=labels)\n", - "\n", - "# Faith\n", - "selector = NSimilarity(similarity_index=\"Fai\", preprocess_data=True)\n", - "selected_fai = selector.select(X, size=size, labels=labels)\n", - "\n", - "\n", - "graph_data(\n", - " X,\n", - " figsize=(6, 4),\n", - " indices=[selected_jt, selected_ac, selected_rr, selected_fai],\n", - " labels=[\n", - " \"Jaccard-Tanimoto\",\n", - " \"Austin-Colwell\",\n", - " \"Russel-Rao\",\n", - " \"Faith\",\n", - " ],\n", - " title=\"Comparing NSimilarity-Based Selectors\",\n", - " xlabel=\"Feature 1\",\n", - " ylabel=\"Feature 2\",\n", - " fname=\"quick_start_compare_nsim_methods_cluster.png\",\n", - ")" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.5" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Tutorial Similarity Based Selectors\n", + "\n", + "This tutorial demonstrates using distance-based selectors in `selector` package. To easily visualize the data and sampled points, we will use a 2D dataset in this tutorial. However, the same functionality can be applied to higher dimensional datasets.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import sys\n", + "\n", + "# uncomment the following line to run the code for your own project directory\n", + "# sys.path.append(\"/Users/Someone/Documents/projects/Selector\")" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.pylab as plt\n", + "import numpy as np\n", + "from sklearn.datasets import make_blobs\n", + "from sklearn.metrics.pairwise import pairwise_distances\n", + "from IPython.display import Markdown\n", + "from selector.measures.diversity import compute_diversity\n", + "\n", + "from selector.methods.similarity import SimilarityIndex, NSimilarity" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Utility Function for Plotting Data\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "# define a function to make visualization easier\n", + "\n", + "\n", + "def graph_data(\n", + " data,\n", + " figsize=(6, 4),\n", + " indices=None,\n", + " labels=None,\n", + " reference=False,\n", + " title=\"\",\n", + " xlabel=\"\",\n", + " ylabel=\"\",\n", + " number=False,\n", + " fname=None,\n", + "):\n", + " \"\"\"Graphs the data in a scatter plot.\n", + "\n", + " Parameters\n", + " ----------\n", + " data : numpy.ndarray of shape (n_samples, 2)\n", + " The original data points to be graphed.\n", + " indices : list of numpy.ndarray, optional\n", + " List of indices array of the data points selected.\n", + " labels : list of str, optional\n", + " List of labels denoting method for selected indices.\n", + " reference : bool, optional\n", + " Whether to highlight the first data point.\n", + " title : str, optional\n", + " The title of the plot.\n", + " xlabel : str, optional\n", + " The label of the x-axis.\n", + " ylabel : str, optional\n", + " The label of the y-axis.\n", + " number : bool, optional\n", + " Whether to label the selected data points with numbers representing the order of selection.\n", + " fname : str, optional\n", + " Filename for saving the figure. If None, figure is shown.\n", + "\n", + " \"\"\"\n", + " if data.ndim != 2 or data.shape[1] != 2:\n", + " raise ValueError(f\"Expect data to be a 2D array with 2 columns, got {data.shape}.\")\n", + "\n", + " if labels is not None and len(indices) != len(labels):\n", + " raise ValueError(\n", + " f\"Expect indices and labels to have the same length, got {len(indices)} and {len(labels)}.\"\n", + " )\n", + "\n", + " # Add a title and axis labels\n", + " plt.figure(figsize=figsize)\n", + " plt.title(title, fontsize=18)\n", + " plt.xlabel(xlabel, fontsize=14)\n", + " plt.ylabel(ylabel, fontsize=14)\n", + "\n", + " # plot original data\n", + " plt.scatter(data[:, 0], data[:, 1], marker=\"o\", facecolors=\"none\", edgecolors=\"0.75\")\n", + "\n", + " colors = [\"skyblue\", \"r\", \"b\", \"k\", \"g\", \"orange\", \"navy\", \"indigo\", \"pink\", \"purple\", \"yellow\"]\n", + " markers = [\"o\", \"x\", \"*\", \"_\", \"|\", \"s\", \"p\", \">\", \"<\", \"^\", \"v\"]\n", + " text_location = [(0.1, 0.1), (-0.1, 0.1)]\n", + " colors_numbers = [\"black\", \"red\", \"blue\", \"k\", \"k\", \"k\", \"k\", \"k\", \"k\", \"k\", \"k\"]\n", + "\n", + " if indices:\n", + " for index, selected_index in enumerate(indices):\n", + " plt.scatter(\n", + " data[selected_index, 0],\n", + " data[selected_index, 1],\n", + " c=colors[index],\n", + " label=labels[index] if labels is not None else None,\n", + " marker=markers[index],\n", + " )\n", + " if number:\n", + " shift_x, shift_y = text_location[index]\n", + " for i, mol_id in enumerate(selected_index):\n", + " plt.text(\n", + " data[mol_id, 0] + shift_x,\n", + " data[mol_id, 1] + shift_y,\n", + " str(i + 1),\n", + " c=colors_numbers[index],\n", + " )\n", + " if reference:\n", + " plt.scatter(data[0, 0], data[0, 1], c=\"black\")\n", + " if labels is not None:\n", + " # plt.legend(loc=\"upper left\", frameon=False)\n", + " plt.legend(loc=\"best\", frameon=False)\n", + " if fname is not None:\n", + " plt.savefig(fname, dpi=600)\n", + " else:\n", + " plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "# define function to render tables easier\n", + "\n", + "\n", + "def render_table(data, caption=None, decimals=3):\n", + " \"\"\"Renders a list of lists in ta markdown table for easy visualization.\n", + "\n", + " Parameters\n", + " ----------\n", + " data : list of lists\n", + " The data to be rendered in a table, each inner list represents a row with the first row\n", + " being the header.\n", + " caption : str, optional\n", + " The caption of the table.\n", + " decimals : int, optional\n", + " The number of decimal places to round the data to.\n", + "\n", + " \"\"\"\n", + "\n", + " # check all rows have the same number of columns\n", + " if not all(len(row) == len(data[0]) for row in data):\n", + " raise ValueError(\"Expect all rows to have the same number of columns.\")\n", + "\n", + " if caption is not None:\n", + " # check if caption is a string\n", + " if not isinstance(caption, str):\n", + " raise ValueError(\"Expect caption to be a string.\")\n", + " tmp_output = f\"**{caption}**\\n\\n\"\n", + "\n", + " # get the width of each column (transpose the data list and get the max length of each new row)\n", + " colwidths = [max(len(str(s)) for s in col) + 2 for col in zip(*data)]\n", + "\n", + " # construct the header row\n", + " header = f\"| {' | '.join(f'{str(s):^{w}}' for s, w in zip(data[0], colwidths))} |\"\n", + " tmp_output += header + \"\\n\"\n", + "\n", + " # construct a separator row\n", + " separator = f\"|{'|'.join(['-' * w for w in colwidths])}|\"\n", + " tmp_output += separator + \"\\n\"\n", + "\n", + " # construct the data rows\n", + " for row in data[1:]:\n", + " # round the data to the specified number of decimal places\n", + " row = [round(s, decimals) if isinstance(s, float) else s for s in row]\n", + " row_str = f\"| {' | '.join(f'{str(s):^{w}}' for s, w in zip(row, colwidths))} |\"\n", + " tmp_output += row_str + \"\\n\"\n", + "\n", + " return display(Markdown(tmp_output))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Generating Data\n", + "\n", + "The data should be provided as:\n", + "\n", + "- either an array `X` of shape `(n_samples, n_features)` encoding `n_samples` samples (rows) each in `n_features`-dimensional (columns) feature space,\n", + "- or an array `X_dist` of shape `(n_samples, n_samples)` encoding the distance (i.e., dissimilarity) between each pair of `n_samples` sample points.\n", + "\n", + "This data can be loaded from various file formats (e.g., csv, npz, txt, etc.) or generated using various libraries on the fly. In this tutorial, we use [`sklearn.datasets.make_blobs`](https://scikit-learn.org/stable/modules/generated/sklearn.datasets.make_blobs.html) to generate cluster(s) of `n_samples` points in 2-dimensions (`n-features=2`), so that it can be easily visualized. However, the same functionality can be applied to higher dimensional datasets.\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Selecting from One Cluster\n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Shape of data = (500, 2)\n", + "Shape of labels = (500,)\n", + "Unique labels = [0]\n", + "Cluster size = 500\n", + "Shape of the distance array = (500, 500)\n" + ] + } + ], + "source": [ + "# generate n_sample data in 2D feature space forming 1 cluster\n", + "X, labels = make_blobs(\n", + " n_samples=500,\n", + " n_features=2,\n", + " centers=np.array([[0.0, 0.0]]),\n", + " random_state=42,\n", + ")\n", + "\n", + "# compute the (n_sample, n_sample) pairwise distance matrix\n", + "X_dist = pairwise_distances(X, metric=\"euclidean\")\n", + "\n", + "print(\"Shape of data = \", X.shape)\n", + "print(\"Shape of labels = \", labels.shape)\n", + "print(\"Unique labels = \", np.unique(labels))\n", + "print(\"Cluster size = \", np.count_nonzero(labels == 0))\n", + "print(\"Shape of the distance array = \", X_dist.shape)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### NSimilarity based methods\n", + "\n", + "Check Documentation: **[NSimilarity](https://selector.qcdevs.org/api_methods_similarity.html#selector.methods.similarity.NSimilarity)**\n" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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ADoex6uvvhoA8N///hdLlizBl19+edYA2kOHDgFolQEICQnp9PPEE08AAMrLy9llT5w4AbfbDQC47LLLOt1GV/O6Q2+vJc++mUwmhIWFdbpvt99+e4d96wqdTse2XbVqVafrDQ0NZQOR2677999/B9D6zBGJRH04Mh05ceIEK1zYnefdqVOnOg2Q7+panDdvHhiGwddff425c+di+/btZw1u7w68Pq9hiPH392f/r6ur83rwdRfPjRJAl/oibbOSDAYDYmNjO7SRy+U+l/UYE91p09kJcrb+iUQi+Pv7o7q62mufgNab1D333MPeQBiGgVKphFAoBNCaUdDY2OiV4dSeoKCgTuf1hO4co7bHoK2KZVe/70Bow9x888149tlnkZWVhUceeaTLzAoAuP7669kbTlsiIyNx9OjRDtPFYjFuuOEG3HDDDQBao+0zMjLw1ltv4b333kNLSwtuuukmFBUVISQkpEd97+w4A38d657+Fn3BYDBg1qxZyM7OZqeJRCIEBASAy+UCaP2t3W73oJyHXXHppZciNTUVZ86cwbvvvssaD0VFRdi7dy8A4O9//7vXMj397dvD4/EQGxuLhx56CBKJBHfffTeeeeYZzJ0718tYb2lpwdVXX832A2g1sNVqNfh8PoDWe6HD4ehwHG+++WZkZGTglVdewY4dO7Bjxw4AQEJCAmbPno3bbrsNEydO9FrG86CxWq2wWq1n3Y+2+le9ubf2lt5cS559czgcnWaHtsVisXSrL20fzmczCj20PW5VVVUAgOjo6G4t2xN6+ps4nU7U1dV5vch46OpavPjii/HMM8/gsccew+7du7F79252vbNmzcLy5cu9sp26y7D3tIwePZr9/+TJk0PYk3OX3Nxc3HvvvXC73Vi0aBEyMjJgtVpRX1/PClt5RKw8FrgvPA+WoWSwxaEYhmFFyr744gscOXKky/Z1dXWorq7u8OmufDiPx8OFF16Ibdu24fHHHwcANDc3sw+X4cw//vEPZGdnw9/fH//73/+g1+thsVhQU1PDnoceo/RcOA893pZ33nmH7Y/n/zFjxmDatGle7fv627dl1apV7Lm+fft2r3lPP/009u7dC7FYjBdffBHl5eWwWq0wGo3scfR4M30dx5deegn5+fnYtGkT5s6dC5VKhaKiIrz22muYNGkS7r33Xq/2LpcLALB48WIvz1Bn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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# select data using n-similarity methods\n", + "# -------------------------------------------\n", + "size = 50\n", + "\n", + "# Baroni-Urbani-Buser\n", + "# selector = NSimilarity(similarity_index=\"BUB\", preprocess_data=True)\n", + "# selected_bub = selector.select(X, size=size)\n", + "\n", + "# Jaccard-Tanimoto\n", + "selector = NSimilarity(similarity_index=\"JT\", preprocess_data=True)\n", + "selected_jt = selector.select(X, size=size)\n", + "\n", + "# Austin-Colwell\n", + "selector = NSimilarity(similarity_index=\"AC\", preprocess_data=True)\n", + "selected_ac = selector.select(X, size=size)\n", + "\n", + "# Russel-Rao\n", + "selector = NSimilarity(similarity_index=\"RR\", preprocess_data=True)\n", + "selected_rr = selector.select(X, size=size)\n", + "\n", + "# Faith\n", + "selector = NSimilarity(similarity_index=\"Fai\", preprocess_data=True)\n", + "selected_fai = selector.select(X, size=size)\n", + "\n", + "\n", + "graph_data(\n", + " X,\n", + " figsize=(6, 4),\n", + " indices=[selected_jt, selected_ac, selected_rr, selected_fai],\n", + " labels=[\n", + " \"Jaccard-Tanimoto\",\n", + " \"Austin-Colwell\",\n", + " \"Russel-Rao\",\n", + " \"Faith\",\n", + " ],\n", + " title=\"Comparing N-Similarity-Based Selectors\",\n", + " xlabel=\"Feature 1\",\n", + " ylabel=\"Feature 2\",\n", + " fname=\"quick_start_compare_partition_methods.png\",\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Compute diversity of selected points\n", + "\n", + "The similarity of a set of points can be computed using the `SimilarityIndex` class and an appropriate similarity index (Check Documentation: **[SimilarityIndex](https://selector.qcdevs.org/api_methods_similarity.html#selector.methods.similarity.SimilarityIndex)**). The diversity of the set can then be computed as `1 - similarity_index`." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "**Diversity of Selected Sets: row = selected set, column = 1 - similarity index**\n", + "\n", + "| | JT | AC | RR | Fai |\n", + "|------------------|---------------------|--------------------|---------------------|---------------------|\n", + "| Jaccard-Tanimoto | 0.442 | 0.463 | 0.442 | 0.442 |\n", + "| Austin-Colwell | 0.442 | 0.463 | 0.442 | 0.442 |\n", + "| Russel-Rao | 0.442 | 0.463 | 0.442 | 0.442 |\n", + "| Faith | 0.442 | 0.463 | 0.442 | 0.442 |\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The selected sets coincide for all similarity indices.\n", + "This is due to the fact that the data has low dimensionality\n", + "\n" + ] + } + ], + "source": [ + "set_indices = [selected_jt, selected_ac, selected_rr, selected_fai]\n", + "sim_idx_list = [\"JT\", \"AC\", \"RR\", \"Fai\"]\n", + "set_labels = [\"Jaccard-Tanimoto\", \"Austin-Colwell\", \"Russel-Rao\", \"Faith\"]\n", + "selected_sets = zip(set_labels, sim_idx_list, set_indices)\n", + "\n", + "scaled_data = NSimilarity()._scale_data(X)\n", + "\n", + "# The similarity of a set of data points\n", + "table_data = [[\"\"] + sim_idx_list]\n", + "for i in selected_sets:\n", + " table_data.append(\n", + " [i[0]]\n", + " + [\n", + " 1 - SimilarityIndex(method=\"esim\", sim_index=si)(scaled_data[i[2]])\n", + " for si in sim_idx_list\n", + " ]\n", + " )\n", + "\n", + "caption = \"Diversity of Selected Sets: row = selected set, column = 1 - similarity index\"\n", + "render_table(table_data, caption=caption)\n", + "\n", + "print(\n", + " \"The selected sets coincide for all similarity indices.\\n\"\n", + " \"This is due to the fact that the data has low dimensionality\\n\"\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Comparing NSimilarity based Selection Methods (Multiple Clusters)\n", + "\n", + "Each cluster is treated independently, and if possible, equal number of samples are selected from each cluster. However, if a cluster is underpopulated, then all points from that cluster are selected. This is to ensure that the selected subset is representative of the entire dataset.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Shape of data = (500, 2)\n", + "Shape of labels = (500,)\n", + "Unique labels = [0 1]\n", + "Cluster sizes = 250 250\n", + "Shape of the distance array = (500, 500)\n" + ] + } + ], + "source": [ + "# generate n_sample data in 2D feature space forming 3 clusters\n", + "X, labels = make_blobs(n_samples=500, n_features=2, centers=2, random_state=42)\n", + "\n", + "# compute the (n_sample, n_sample) pairwise distance matrix\n", + "X_dist = pairwise_distances(X, metric=\"euclidean\")\n", + "\n", + "print(\"Shape of data = \", X.shape)\n", + "print(\"Shape of labels = \", labels.shape)\n", + "print(\"Unique labels = \", np.unique(labels))\n", + "size_0, size_1 = np.count_nonzero(labels == 0), np.count_nonzero(labels == 1)\n", + "print(\"Cluster sizes = \", size_0, size_1)\n", + "print(\"Shape of the distance array = \", X_dist.shape)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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0KfKOVgicElJiayg2hMceuihsg933nnnkA+GsrKyERnG/X/D4RLK9gf6KyP3fwtXcLlcPPTQQ3u8H2FhYcDIk3eVhNdFixbJMM4VV1yxx0NISuUGBL88hIWFSdf+YOfR5/Pxxz/+cch2h3szNhqN8rj6v5hcccUV6PV6mpubuffee4ftd29vb5Cya25uLjk5OQD8+c9/lvlq/fn73/8+rPd5OH7pvTRv3jwcDgder5ebb7552ME8EAiM+LoJDQ3lwgsvBOCxxx6jsrJy2PW3D/FdeeWVQF+V5EsvvTSifcLIru/c3FzGjx8P9I2L/UNNCp9++qkMQ+/qWDbctabT6aTRNlxeygB2W3HxKOH999+XKn1RUVHi0UcfDdJx8Pl8Yu3ateKee+6Rtev9lTqrqqrk9xMmTBBLly6Vy3744QdZ+70j8bShlBz7azEMxXB16P3F00wmk/jb3/4WJJ6miPEA4r333gvatn9d/LXXXit1Pjo7O8XLL78sLBaLiIyMHHLfik6JouY3FCPVKRkOZZ1vvvkm6PuSkhKpWjpt2jSpwBgIBMTXX38t0tPTd6t42mAUFRUFqVwyiF7Gxx9/LLRarTjllFPEP/7xj6C2ent7xdq1a8X8+fODdDm213f4pVocQ51DheF+p13RKfH7/VJJdMKECVLYTgghfvzxR3HIIYfI62uwfo302hBi+HOjiAAeccQRorW1dYdteb1eERcXJ/et0+mCRKx2lh0pura2topnnnlGapakpaUN0Bo56qijBCASExPF119/La+NgoICccIJJwij0ShVpre/BmJjY8Udd9whli1bFqSVVFJSItVDtVqtFHZUuP/++2W/L7nkElFQUBB0jtatWyfuv/9+kZycPEDR+r333pPbnnfeefL8dXd3i5deekkYjcZdFk/bHffSokWL5PKTTz5ZLF++XK7j9/vF5s2bxZNPPinGjRs3QOV3R+JpipBdQkKCeO2110RHR4dc3tjYKN555x0xd+5cceKJJw7Y/vzzz5e/xx133DFAPO2VV14RV1xxRdA2JSUl8ljefPPNYc+bst7cuXOleFpvb6/45z//KfW2hhNP25EWSl5enrjhhhvEN998Izo7O+X3NTU14vrrr5f7H0ofZjAOOKNEiD7jISMjI2jQCAkJEREREUEywxqNRlxwwQVSgU/h22+/DZL53V5m3uFwiO+++27AfvemUXLnnXfKB5fBYAgaiKFPMXYwlJug/7EoA+zUqVPF888/P6qNEiH6BLj6yxjbbDapTpqYmCjPn9FoHHYfgzESo0SIYDGnwQbHzz//PGh5/2uwv+wz9ClkDib4t78ZJUL0PQj7/zYWi0X+NqGhoUGG8Z4ySpYsWSLPsU6nE/Hx8SI1NXXYB2x/8cWdVXDdnuHE07b//VNSUsTGjRsHtLF69eqgZ47RaJQKnHq9Xrz22mtDXgP9ry1FYl6ZhkF57m0vECZEn2F/zz33BPXPbDaLyMjIAUZ4f6Vrhf5q1NAnQKlcC0cfffQuy8zvjntJCCFeeumlIFl5o9EoIiMjg2TXAfHPf/4zaLsdDdCbN28WWVlZQec8IiIi6PcDxOzZswds63a7pXKw8gkLCxtSZl7h+OOPD3r+Kdf39r/r9jLzDocj6BxMmjRp0PM1UqNEuQaV68rhcAw47sFUh4fjgArfKBx55JEUFRXxxhtvcNFFF5GRkYHJZMLlchEREcFRRx3FH//4RwoLC/n3v/+NwWAI2n7mzJkUFhbyhz/8gZycHAKBAEIIcnJyuOWWWygsLByyHn9vERISwtdff83DDz9MdnY2Ho8Hu90u48aKrsb2/Otf/2LBggXk5uZiNBrx+/1MmjSJRx55hKVLlwbFZUcr55xzDqtXr2bevHlER0fj8XiIjY3ld7/7HevWrZNhBCX/ZE9w3333DTvx10knnURJSQnPPvss8+bNIycnB6PRiNPpxGKxkJmZybnnnsvixYtZtWrVLpWwj0ZOO+00qb/hcDjw+XxERUVx+eWXs2bNGo4//vg93odjjjmG//znP8yePRuHw0FDQwMVFRXDJhTOmzdP/r07hAEVthdP6+joIDIyklmzZvH000+zadOmoMpBhalTp7Jy5UrOPfdcoqKiCAQC2Gw2zj33XH788UcuueSSIff5xRdfcOedd3L00UeTnJwsZ83NyMjg8ssvZ9WqVYNWRGg0Gh544AE2bNjAddddR05ODjqdjvb2djmJ26233sqPP/44qI7MQw89xCeffMJxxx1HWFgYHo+HnJwcHn30Ub7++utd1jbaXffSNddcQ3FxMbfccgt5eXmyDavVyrRp07jhhhv48ssvdzqUkZOTw4YNG/jrX//KiSeeSFRUFB0dHQghyMjIYN68efztb38bNKxssVh49913+eSTTzjzzDNJSEigp6dHznx84403Diru984773DTTTeRlZWF1+uV1/f2IZ2bbrqJ1atXy0lfu7q6MJvNHHbYYTzzzDO/+NmzePFi7r//fo4//njS09Pp7e3F6/WSmprKeeedx9dffy0rOkeKRogRZIOpjBpmzZrFkiVLuPfee3f7zKUHCn/84x95+OGHOe6444ZNWFZRUXjqqae45ZZbSE5OpqysbFSUvauoHIwckJ4SlYOXpqYmqcY5Z86cfdwblf0Bv98vEw2vuuoq1SBRUdmHqEaJyn7Hc889x6OPPsrWrVtl6bPH4+HTTz/lmGOOobGxkejoaK644op93FOV0U4gEODee+9l27ZthIaGykocFRWVfcMBIzOvcvBQWlrKs88+y5133olOp8Nut9PR0SENFLvdzltvvTXoJHQqKtAXk7/llltobW3F5XIBcP/99wcJ9KmoqOx9VKNEZb/jsssuQ6fT8d1331FTU0NLSwtms5n09HROOukkfve73+2R+W9UDhw6OzupqKjAYDAwbtw4rr/+en7729/u626pqBz0qImuKioqKioqKqMCNadERUVFRUVFZVRwUIZvAoEAtbW12Gy2/WKmRhUVFRUVldGCEAKXy0VCQsLOSciPgIPSKKmtrSU5OXlfd0NFRUVFRWW/paqqiqSkpN3a5kFplNhsNqDvhCqTG6moqKioqKjsmI6ODpKTk+VYujs5KI0SJWQTFhamGiUqKioqKiq7wJ5If1ATXVVUVFRUVFRGBapRoqKioqKiojIqUI0SFRUVFRUVlVGBapSoqKioqKiojApUo0RFRUVFRUVlVKAaJSoqO4HP56O7u1tO/qeioqKisvs4KEuCVVR2lq66OqoLC6nV6XBqLOTnO5g5UzB1TAI2pxNsNrDb93U3VVRUVPZrVE+JisoOcNfW4jvhBBIvvYzSnjA+3JDFfTdm8o/vYnljSRGeo46GOXOgvX1fd1VFRUVlv0Y1SlRUdkDZhg3onO2E1lRz5q/PovjjvtBN8cc+5v3mHIwV5fTWN4DLtY97qqKiorJ/o4ZvVFSGwe120xBi4qFTviZl8TuYq9soqPYCbjZ+0csC5tFtc1B36mUsjE9UbygVFRWVX4BGCCH2dSf2Nh0dHdjtdtrb21WZeZVhaWpq4uu1lVwwZ9qw65nD/Kwq9DEhIWQv9UxFRWVnmTVrFpMnT2bBggV7fd/z58/H6XTywQcf7PV972725Biqhm9UVIZBp9Oht+74NrlxsRON6aCz71UOUubPn8/cuXP3dTd2G/fddx8ajWbYzy/l2WefZdGiRb+8sztg1qxZ/P73v9/j+9lTqEaJisow2O12zFrB/UvLeezNZZhpBDrlx0wDj7+1DEdcgFDD7p+cSkVlRwSEoMLVy+ZWDxWuXgIHn/M7CCHETpfs33LLLdTV1clPUlISDzzwQNB3vxS73Y7D4fjF7RzoqEaJisow6HQ6JiZGE9fWyKTrn6SbaCBUfrqJYeJvnyC+pY5kq2Ef91blYKPY6eGlTW28sbWDjypcvLG1g5c2tVHs9Oy1Pnz++eccddRROBwOIiMjOe2009i2bVvQOtXV1VxwwQVEREQQGhrKtGnTWLFihVz+8ccfM336dEwmE1FRUZx55ply2euvv860adOw2WzExcVx4YUX0tjYKJd/++23aDQaPvvsM6ZOnYrRaOSHH37A7XZz6aWXYrVaiY+P56mnnhryGKxWK3FxcfKj0+nk/uLi4vj3v//NpEmTCA0NJTk5meuuu47Ozk65/aJFi3A4HPz3v/8lJycHq9XKnDlzgoyZ7b1Ls2bN4oYbbuD3v/894eHhxMbG8sorr+B2u7n88sux2WxkZGTw2WefBfV1yZIlzJgxA6PRSHx8PHfccYc0wubPn8+SJUt49tlnpYenvLx8h9uNJlSjREVlB6Ro4JJrz+HbpukA5B7u5JYPW8k9zAnAt00zuOCqM9DW1OzDXqocbBQ7Pbxf5sLlDQR97/IGeL/MtdcME7fbzc0338zq1av5+uuv0Wq1nHnmmQQCff3q7Oxk5syZ1NTU8NFHH5Gfn89tt90ml//nP//hzDPP5JRTTmHdunV8/fXXzJgxQ7bv9Xp58MEHyc/P54MPPqC8vJz58+cP6Mcdd9zBo48+SmFhIbm5udx6660sWbKEDz/8kC+++IJvv/2WtWvX7tIxarVannvuOTZt2sQ//vEP/ve//3HbbbcFrdPV1cWTTz7J66+/znfffUdlZSW33HLLsO3+4x//ICoqipUrV3LDDTdw7bXXMm/ePI444gjWrl3LiSeeyCWXXEJXVxcANTU1nHLKKUyfPp38/HxeeuklXn31VR566CGgL0R0+OGHc9VVV0kPT3Jy8g63G1WIg5D29nYBiPb29n3dFZX9AadTiMMOE9/EniOuur1MPLymSTyytkk8vKZJ/ObOCvFN3DlCHHZY33oqKnsBfyAgXihoEY+sbRry80JBi/AHAntk/5dddpk444wzBl3W1NQkAFFQUCCEEOKvf/2rsNlsoqWlZdD1Dz/8cHHRRReNeN+rVq0SgHC5XEIIIb755hsBiA8++ECu43K5REhIiHjrrbfkdy0tLcJsNovf/e53O9xHamqqeOaZZ4Zc/vbbb4vIyEj5/4ULFwpAbN26VX734osvitjYWPn/7c/ZzJkzxVFHHSX/7/P5RGhoqLjkkkvkd3V1dQIQy5YtE0IIcdddd4ns7GwR6Pe7vvjii8JqtQq/3y/b3f4YR7LdzrAnx1DVU6KisiPsdvj8c2atfoaXH0nlwswwfpVq48LMMP7y52RmrXoGPv9cVXRV2WtUdXoHeEi2x+UNUNXp3eN9KSkp4YILLmDMmDGEhYWRlpYGQGVlJQDr169nypQpREREDLr9+vXrOf7444dsf82aNZx++umkpKRgs9mYOXNmUPsK06b9XCG3bds2ent7OfTQQ+V3ERERZGdny/8//PDDWK1W+dm+vf589dVXHH/88SQmJmKz2bjkkktoaWmRHgwAi8XC2LFj5f/j4+ODwkyDkZubK//W6XRERkYyadIk+V1sbCyAbKewsJDDDz88KPH2yCOPpLOzk+rq6iH3s6vb7QtUo0RFZSTY7ZCUhFajIdUWwvgII6m2ELQaDSQlqQaJyl7F7R1ZMutI1/slnH766bS2tvLKK6+wYsUKmSvS29sLgNlsHnb74Za73W5OOukkwsLC+Ne//sWqVat4//33g9pXCA0N3al+X3PNNaxfv15+EhISBl2vvLyc0047jdzcXN59913WrFnDiy++OKAPBkNwTplGo0HsIOl4sG36f6cYEUqo62BANUpUVFRU9jNGWum1pyvCWlpaKC4u5u677+b4448nJyeHtra2oHVyc3NZv349ra2tg7aRm5vL119/PeiyoqIiWlpaePTRRzn66KMZN27cDr0PAGPHjsVgMAQl07a1tbFlyxb5/4iICDIyMuRHrx9c+nDNmjUEAgGeeuopDjvsMLKysqitrd1hH/YEOTk5LFu2LMjYWbp0KTabjaSkJABCQkLw+/07vd1oQTVKVFRUVPYzkq0GbIbhH982g3aPV4SFh4cTGRnJ3/72N7Zu3cr//vc/br755qB1LrjgAuLi4pg7dy5Lly6ltLSUd999l2XLlgFw77338sYbb3DvvfdSWFhIQUEBjz32GAApKSmEhITw/PPPU1paykcffcSDDz64w35ZrVauvPJKbr31Vv73v/+xceNG5s+fj1a780NeRkYGXq9X9uH111/n5Zdf3ul2dgfXXXcdVVVV3HDDDRQVFfHhhx9y7733cvPNN8tjS0tLY8WKFZSXl9Pc3EwgEBjRdqOF0dUbFRUVFZUdotVomJ00fLhidlJoX3hxDxAIBNDr9Wi1WhYvXsyaNWuYOHEiN910E0888UTQuiEhIXzxxRfExMRwyimnMGnSJB599FF0Oh3QVxr79ttv89FHHzF58mSOO+44Vq5cCUB0dDSLFi3i7bffZvz48Tz66KM8+eSTI+rjE088wdFHH83pp5/O7NmzOeqoo5g6depOH2teXh5PP/00jz32GBMnTuRf//oXjzzyyE63sztITEzk008/ZeXKleTl5XHNNddw5ZVXcvfdd8t1brnlFnQ6HePHjyc6OprKysoRbTdaUGXmVZl5FRWV/ZRip4evqt1BSa82g5bZSaFkO4x7bL9z5swhIyODF154YY/tQ2X0sifHUHX+MBUVFZX9lGyHkUx7CFWdXtxeQahBQ7LVsMc8JG1tbSxdupRvv/2Wa665Zo/sQ+XgRjVKVFRUVPZjlIqwvcEVV1zBqlWr+MMf/sAZZ5yxV/apcnChGiUqKioqKiNCKcdVUdlTjLpE1++++47TTz+dhIQENBpN0DTPXq+X22+/Xc5BkJCQwKWXXrrPyrNUVFRUVFRUdh+jzihxu93k5eVJcZr+dHV1sXbtWu655x7Wrl3Le++9R3FxMb/61a/2QU9VVFRUVFRUdiejuvpGo9Hw/vvvB82suD2rVq1ixowZVFRUkJKSMqJ21eobFRUVFRWVXUOtvhmG9vZ2NBoNDodjyHU8Hg8ez88zZnZ0dOyFnqmoqKioqKjsDKMufLMz9PT0cPvtt3PBBRcMa6098sgj2O12+UlOTt6LvVTZG/h8PlpaWmhubg4yQFVUVFRU9h/2W0+J1+vl3HPPRQjBSy+9NOy6d955Z5D0cUdHh2qYHCAE2tqo2LiRSiFow0x+voO8vDIyIixkWcyEREaqk+WpqKio7Cfsl54SxSCpqKjgyy+/3GFMy2g0EhYWFvRR2f8RTic9s2YRff4FbO2y8eGGLO67MZMPN2TxY0U33mNmIk46Cdrb93VXVVRUdgNpaWksWLBgX3cD6Js9WKPRsH79+j3S/qJFi4LSEu677z4mT568R/Y1mtjvjBLFICkpKeGrr74iMjJyX3dJZR/RXl1NoLkFa20NZ111FsUf+wAo/tjHvGvmEVpTTU9tPbhc+7inKioHJsuWLUOn03Hqqafu1na3H5AVVq1axdVXX/2L2xdC8Le//Y1DDz0Uq9WKw+Fg2rRpLFiwgK6url/cvsquM+rCN52dnWzdulX+v6ysjPXr1xMREUF8fDznnHMOa9eu5ZNPPsHv91NfXw/0TUMdErJ3VA1VRgdVQsuDp3xF2pvvYa5uo6DaC7jZ+EUvCziHbpuD6tMu4bX4xNF3oauo/FLa2/sM7sGmnq+uBpttj4cuX331VW644QZeffVVamtrSUhI2KP7i46O3i3tXHLJJbz33nvcfffdvPDCC0RHR5Ofn8+CBQtIS0sbtuJTZQ8jRhnffPONAAZ8LrvsMlFWVjboMkB88803I95He3u7AER7e/ueOxCVPc5H3xcNeT0oH3OYX2ys8ezrrqqo7F6cTiEOO0yIMWOEqKwMXlZZ2ff9YYf1rbeHcLlcwmq1iqKiInHeeeeJP//5z3LZwoULhd1uD1r//fffF/2HnPXr14tZs2YJq9UqbDabOOSQQ8SqVasGHQPuvfdeIYQQqamp4plnnpFtAOKVV14Rc+fOFWazWWRkZIgPP/xw2H6/+eabAhAffPDBgGWBQEA4fzpnfr9f3H///SIxMVGEhISIvLw88dlnn8l1lfFo3bp1Qgghpk6dKp544gm5/IwzzhB6vV64XC4hhBBVVVUCECUlJUIIIXp6esQf/vAHkZCQICwWi5gxY0bQOLb9Obz33ntFXl7esMe2t9iTY+ioC9/MmjULIcSAz6JFi0hLSxt0mRCCWbNm7euuq+xljGE79n/cuNiJxtQnxRMIBKivr2fdunUsXbqUFStWUFpaqlbrqOx/uFzQ2AilpTBrFlRV9X1fVdX3/9LSvuV7MHT51ltvMW7cOLKzs7n44ov5+9//jtgJ2auLLrqIpKQkVq1axZo1a7jjjjswGAwcccQRLFiwgLCwMOrq6qirq+OWW24Zsp3777+fc889lw0bNnDKKadw0UUX0draOuT6//rXv8jOzh507h6NRoP9J+/Ss88+y1NPPcWTTz7Jhg0bOOmkk/jVr35FSUnJoO3OnDmTb7/9FugLD33//fc4HA5++OEHAJYsWUJiYiIZGRkAXH/99SxbtozFixezYcMG5s2bx5w5c4Zs/2Bh1BklKiojJT7Szv1Ly3nszWWYaQQ65cdMA4+/tQxHXIBQg4ZAIMCmTZsoKipCq9WSmJhIeHg4NTU1rFq1Cpead6KyP5GUBN9+C2PG/GyY/PjjzwbJmDF9ywcL7ewmXn31VS6++GIA5syZQ3t7O0uWLBnx9pWVlcyePZtx48aRmZnJvHnzyMvLIyQkBLvdjkajIS4ujri4OKxW65DtzJ8/nwsuuICMjAwefvhhOjs7Wbly5ZDrl5SUkJ2dvcP+Pfnkk9x+++2cf/75ZGdn89hjjzF58uQhE21nzZrFDz/8gN/vZ8OGDYSEhHDRRRdJQ+Xbb79l5syZ8tgXLlzI22+/zdFHH83YsWO55ZZbOOqoo1i4cOEO+3YgoxolKvst4+MjSGhvZtJvn6SbaCBUfrqJYeJ1TxDfUkuy1UBlZSWtra1MmjSJvLw80tLSyMrK4rDDDsNkMrFp06adestTUdnnJCcHGyZHHhlskOxB2YPi4mJWrlzJBRdcAIBer+e8887j1VdfHXEbN998M7/+9a+ZPXs2jz76KNu2bdulvuTm5sq/Q0NDCQsLo7GxEYAJEyZgtVqxWq2cfPLJACO6zzs6OqitreXII48M+v7II4+ksLBw0G2OPvpoXC4X69atY8mSJcycOZNZs2ZJo2TJkiXSo19QUIDf7ycrK0v2z2q1smTJkl0+DwcKav6fyn6LrraWS6+bxz3NvwEg93AnJ94R4ItHtGxY7uDb5hk8eNVcWPIttbW1xMfHD6jWMhgMZGdns2bNGlpaWoiKitoHR6KisoskJ8Prr/cZJAqvv75HDRLo85L4fL6gxFYhBEajkRdeeAGtVjtg8Pd6vUH/v++++7jwwgv5z3/+w2effca9997L4sWLOfPMM3eqLwaDIej/Gk2fZxTg008/lfs1m80AZGVlUVRUtFP7GAkOh4O8vDy+/fZbli1bxgknnMAxxxzDeeedx5YtWygpKZGeks7OTnQ6HWvWrEGn0wW1M5xX6GBA9ZSo7L/YbITExXJy3GquvqOS81/wEZkc4PwXffzmzkpOjltNSFwsPQYDvb29QxocNpsNo9FIu6pnorK/UVUFl1wS/N0ll/ycY7IH8Pl8vPbaazz11FOsX79efvLz80lISOCNN94gOjoal8uF2+2W2w2m55GVlcVNN93EF198wVlnnSVDFyEhIfj9/l/c19TUVDIyMsjIyCAxMRGACy+8kC1btvDhhx8OWF8IIedzSUhIYOnSpUHLly5dyvjx44fc38yZM/nmm2/47rvvmDVrFhEREeTk5PDnP/+Z+Ph4srKyAJgyZQp+v5/GxkbZP+UTFxf3i497f0b1lKjsv9jt8PnnzHK5OCYxkapOL26vINSgIfnPkWivewZsNjQ/lYoP5bZVkqU1Gs2Id+33++np6UGj0WA2m3dqWxWV3UL/pNYxY/o8JJdc8nOOyR4K4XzyySe0tbVx5ZVXyqRQhbPPPptXX32V//73v1gsFu666y5uvPFGVqxYwaJFi+R63d3d3HrrrZxzzjmkp6dTXV3NqlWrOPvss4E+kbTOzk6+/vpr8vLysFgsWCyW3dL/c889l/fff58LLriAu+++mxNPPJHo6GgKCgp45plnuOGGG5g7dy633nor9957L2PHjmXy5MksXLiQ9evX869//WvItmfNmsXzzz9PdHQ048aNk9+98MILzJs3T66XlZXFRRddxKWXXspTTz3FlClTaGpq4uuvvyY3N3e3677sT6ieEpX9G7sdkpLQajSk2kIYH2Ek1RaCVqPpS/Kz2zGZTJhMJhoaGgZtwul00tvbS3h4+A535/f72bp1K8uWLWPVqlWsXLmSlStXUltbq+akqOw9qqsHJrUeccTA5Nfq6t2+61dffZXZs2cPMEigzyhZvXo11dXV/POf/+TTTz9l0qRJvPHGG9x3331yPZ1OR0tLC5deeilZWVmce+65nHzyydx///0AHHHEEVxzzTWcd955REdH8/jjj++2/ms0Gv7973/z9NNP88EHHzBz5kxyc3O57777OOOMMzjppJMAuPHGG7n55pv5wx/+wKRJk/j888/56KOPyMzMHLLto48+mkAgIMM00GeU+P3+ARWiCxcu5NJLL+UPf/gD2dnZzJ07l1WrVo14tvsDFY04CJ+ke3LaZZWdQwiB1+tFCEFISMge8zjU1NRQUlJCZmYmCQkJcj9dXV1s2LABvV7P1KlTh92/3+8nPz+fzs5OEhMTiYyMxO/309DQQGNjI8nJyYwdO3aP9F9FJYj2dpgzp6/sd3uPiOJBiYmBzz9X535S2e3syTFUDd+o7BOE00njtm2U+/3U9WjIz3cwfXoXExIiSNGAJixstz5MExIScLvdlJSUUF1djd1ux+Px0NbWhtlsZuLEiTs0iGpra3G5XEyZMiXoRoyMjMRqtVJaWkpsbOxBn6imshf4KXQ5qKJrcjIsWbJXFF1VVHY3avhGZe/T3o7n2GMJ/dUZFLTo5UR6b69O478F9XQfcSRizpzdOpGeRqMhKytLGhRKAl5WVhbTpk3DZDLtsI26ujqio6MHfTNISkoiJCSEurq63dZnFZVh+Sl0OSg/hS5VVPY3VE+Jyl6no6YGbWMT1toazr76bP4+fjXQN5He05vnYamuokerxeRy7fYHq91uHzQWPhK6u7tlBv/2aLVawsLC6O7u/iXdU1FRUTmoUY0Slb1OZUDDA0NOpDePbpuDmlMv4R+jbCI9vV5PT0/PkMs9Ho/UQgBkRY/X66WzsxONRoPNZhugS6CioqKi0oea6Komuu51PvxuM3NnThh2HXOYn1WFPsbF6hBCoNPp9lrZrd/vp7m5mY6ODrRaLRERETgcDkpKSmhqauLQQw9Frw82l9rb21m3bh3Z2dl0d3dTX1+Pv7UVQ08P3VFRtGtDyc93cMghHeTEOhgTYkBrt6sudhUVlf0ONdFVZfTR3o6nuZlanZ4ql5fVa6yceGIIOXEOdLW1wybZGWw79hTcuNhJRUMTTVv6cjTMZjOJiYkkJibuUePE6XSyadMmvF4vZrOZQCBAVVUVVquVzMxMGhoa2LBhA5mZmdhsNoQQNDc3s2XLFkJDQ6moqMDr9RJnNhN3xx1o2pz8+28fsKwsk0U32pn/fDuHp5eQcM1ZmJMS0ajVESoqKioS1ShR2Xna2/Ecdxze+ga+VAbcG/oG3CPHruPS6+YREhc7ZDlijN3G/UvLMVXXcd95Y+nmZ1EkM27uf6sUf1wAI36ys7PRarU0NzezdetW2tvbGT9+/B4xTJTy4LCwMLKysrBYLAghcDqdFBUVUVxczKRJkygsLGTNmjWEhIQQCATw+Xw4HA40Gg1ut5tp06bh3LgRTZsTa20N866Zx6KgvJlzsFRX4dHqMO6BvJmREggE0Gg0qvCbiorKqEE1SlR2muayMkz1DYMPuJvOJqSmgl4gZIgBNzc5mrVF+ST/9km6eSdoWTehTLzuWmpf/yOzTpyMTttXIBYbG0tTUxObNm2ioaFhj0gxV1VVodfrmTRpksz70Gg0hIeHM3HiRNasWYPH4+HQQw+ltbUVl8uFRqMhMjISg8HA8uXLycrKwmw2s0FoePqUr0gdZXkzwumkqbSUSiGodgfIz3dw5JE+8lKiie7pUctIVVRU9imqUaKyUwgh2Orx8swOBty60y5j4RADbkhDA5ddN48/NV8DDDGR3rXnoPv+u6CSx+joaMLDw6mtrd0jRklTUxMJCQmDJqLabDbCwsJoamoiNjaWqKiooLl0mpubAeSEf5Udet76v5x+LTwJgAt44Kc/zP+6k7vu9jIhIWS3H8tgCKeTnlmzsDQ1s/7/PmLptiwZUiqt28Il187DnBivCm6pqKjsM1SjRGWn6Onpodyp3fGA+9qd3HHnEAOuzYYxPo6TPatxXlZB2rmhaDRw/osBZiwu5cRFK/rCPzbbgE0jIiIoKyvbE4eG3+8nJGRoA2G4ScK0P3l0fD4fRqMRo90w6Hr9uXGxE40pdNc6uwu0VlRgbGoeshTbXF2BR6vZpyElFZVfyrfffsuxxx5LW1sbDodjX3dHZSdRxdNUdopAIIDeuuPLpm/AHaKwS5lIb9UzvPRIChdmhvGrVBsXZoZxw8Vu4l7/zZBv616vd5dLagOBwLDz01gsFpxO55Dbtre3DzkpmN1uR6fTUV9fD0BceBj3Ly3nsTeXYaYR6JQfMw08/tYyHHEBQg17L5+jwg9XnPIVt9n+zILqcyj4op+Hq3oet9ke4opTl+CLH1yLRWX0IkSf2vzeqqWcP3++zEcyGAykp6dz2223DVsyP5pYtGiR7L9WqyU+Pp7zzjuPysrKfd21gx7VU6KyU5hMJkyawIgSVQcbcLu6uqirq8PtdqPT6YgyGEiOjpaehrroKIpbW+gyGNh++FfmmekfNtkRXq+Xqqoq6urqpEETGxtLSkrKABXXhIQESkpKaGtrw2az0dzcTG9vLyEhIXR1deH1egkLC6OhoQG9Xo/D4ZAGkk6nIzExkcrKSiwWC7nJMeRvKSBpmLyZxjfuJXly5IiP5ZeyrVXw9o48XP+8k7v+uPdCSiq7h88/h1NOgc8+65sSZ28wZ84cFi5ciNfrZc2aNVx22WVoNBoee+yxvdOBX0hYWBjFxcUIISgrK+O6665j3rx5rFixYl937aBG9ZSo7BQ6nY6sqDDi2pqYdP1TdBMNhMpPNzFMvO4J4ltqSbYGhzAqKytZuXIldXV1aDQaPB4PhYWFrF69Wr5hxcTEYDKZKCgowOVyyW17enpkqW7SUNLa2+HxeFi7di01NTXExMSQnp5OZGQkjY2NrFmzRkrNK8THxxMeHs6GDRv44YcfKCoqory8nKKiIiorK9HpdBQWFlJYWEhBQQHLli2jqqpKel/S0tKIjY2luLiYTZ9/zkW/OYtvm6cDfXkzt3zYSu5hTgC+bZ7BBVfNRVtTs/M/wi4SMsJS7CE9XCqjlnfeCf53b2A0GomLiyM5OZm5c+cye/ZsvvzyS6DvXliwYEHQ+pMnT5YzBQshuO+++0hJScFoNJKQkMCNN94o1/3LX/5CZmYmJpOJ2NhYzjnnHLksEAjwyCOPkJ6ejtlsJi8vj3d24cA1Gg1xcXHEx8dzxBFHcOWVV7Jy5Uo6OjrkOrfffrusxBszZgz33HMPXq83qJ2XXnqJsWPHEhISQnZ2Nq+//vpO90XlZ1RPicpOk27Qk/ibM3mg6XpgiETVq+ai7Zeo2tTURGlpKSkpKaSmpkoPQ2dnJwUFBRQUFDBt2jR0Oh25ubkUFBSwZs0aLBYLOp0Ol8uFTqdj4sSJhIaOLA+jpKQEv99PZmYm1dXVdHZ2ymUajYaNGzcyY8YMWRKrKLD2D/EEAgH0ej0+nw+/309CQgJjxozB4/FQXV3Ntm3bCAQCpKamotVqycnJITExkcaSEogI5yTPStquKCf9XKvMmzn8nUpOXrh6yLyZPUVUWOgue7hURheBALz0EijRxv5GSXp6398OB1x7LWj3wqvnxo0b+fHHH0lNTR3R+u+++y7PPPMMixcvZsKECdTX15Ofnw/A6tWrufHGG3n99dc54ogjaG1t5fvvv5fbPvLII/zzn//k5ZdfJjMzk++++46LL76Y6OhoZs6cuUv9b2xs5P3330en0wWFh202G4sWLSIhIYGCggKuuuoqbDYbt912GwDvv/8+v/vd71iwYAGzZ8/mk08+4fLLLycpKYljjz12l/pysKMaJSo7jSEiAn1SIid5V9JyaSljLwiTA+5hb1dw8qKBA25VVRUOh4P09PQgXQyr1UpOTg7r16+nra2NiIgILBYL06dPp6WlhdbWVoQQxMXFERsbO0BJdSg8Hg/Nzc0kJiZSVFQk96kYNG63m+7uboqLixk3bhyBQICCggKcTidms5mxY8fKNtra2jAYDERERNDU1ERGRgahoaFkZ2ej1+spLy8nPj5eJsmGhYURNnUqfPcdx7lczEpMpKrTi9srCDVoSP5zJNrrntnr5bd5KbFsKi0k+frRE1JS2TXcbvjTn6C1FTSanw2Pzk64556+3JKICLj00j1n937yySdYrVZ8Ph8ejwetVssLL7wwom0rKyuJi4tj9uzZGAwGUlJSmDFjhlwWGhrKaaedhs1mIzU1lSlTpgB99/XDDz/MV199xeGHHw7AmDFj+OGHH/jrX/+6U0ZJe3s7VqsVIQRdXV0A3HjjjUEvPXfffbf8Oy0tjVtuuYXFixdLo+TJJ59k/vz5XHfddQDcfPPNLF++nCeffFI1SnYR1ShRgfZ2/E4n9YYQypzdrFxl4YTZBsZbtAQKC6m1hVHUA6tWh3LE4R4mJEQS8+qrHKfRMHNcGhXtHroCYAvRkfxwJNrfBg+4Xq+Xjo4Oxo0bN6hQl91ux2Qy0dLSQkREBNBXzRIdHU10dPQuHZISmmlqakKr1WI0GoO8LD09PSxfvpz6+nri4uLo7OyUSa7jx4/H9tOTPDo6mh9//BGv10t0dDQNDQ3SeGppacHlciGEYNWqVcTFxZGQkEBXVxfNzc0EAgFCQ0OJ83pJtW2XozHCENTuxNrW1leK3TRMKfZ2Hi6V0YnNBuvWwQUXwLJloBSF+f19RsoRR8DixXvWEXfsscfy0ksv4Xa7eeaZZ9Dr9Zx99tkj2nbevHksWLCAMWPGMGfOHE455RROP/109Ho9J5xwAqmpqXLZnDlzOPPMM7FYLGzdupWuri5OOOGEoPZ6e3ul4bI9VqtV/n3xxRfz8ssvA31ekLVr1+L1evnss8/417/+xZ///Oegbd98802ee+45tm3bRmdnJz6fL0hWvbCwkKuvvjpomyOPPJJnn312ROdBZSCqUXKw096Ob/ZsPLX1/Odv77GsLItFN9i56vE6Hvz7SUSXbMaYMZ53r/gvr9we/5NM+hYuvuZszEmJ6D7/nDHh273tbzegKeGQoapmNBoNOp1u2MqYnUUxfnp7ewEGhH36e1zKy8vp7u7GYDDg9Xqlt0Sv18vtdTodra2tss3i4mLq6+sJCwtDp9NhNBqpra2lqqoK6JPFNxgMNDU1UVZWRnZ29h7RVtkpbDaMCXGc3LuatstGR0hJZddJSYFvvunziPRPj7JY+ipxDDuuSv9FhIaGkpGRAcDf//538vLyePXVV7nyyivRarUD7uf+uRjJyckUFxfz1Vdf8eWXX3LdddfxxBNPsGTJEmksfPvtt3zxxRf86U9/4r777mPVqlUyBPuf//xnwIzdRqNx0H6uX79e/t3foNBqtbL/OTk5bNu2jWuvvVbmhCxbtoyLLrqI+++/n5NOOgm73c7ixYt56qmndvGMqYwE1Sg5yOlqaCBQW4+1tpp515wr1VmL/uMnqqQQrd9P9NZCiv7T9yqmaFpYqqvo1mgwj0DTwmAwYDQaaWlpGdTz0d3djdvtHnEC60gICwtDq9VKb8X2pbxKsq0iIw8/Gyrbtm2jvLw8yGNiNptl4q3b7aa+vp5x48YRERHBsmXLiIuLo76+XlYVTZ06Fb1ej9frZdu2bRQVFWE0GgkPD99tx7jTKKXYLhfHjJKQksovY+XKYIME+v6/ciUceeTe64dWq+Wuu+7i5ptv5sILLyQ6Opq6ujq5vKOjY4C+kNls5vTTT+f000/nt7/9LePGjaOgoIBDDjkEvV7P7NmzmT17Nvfeey8Oh4P//e9/nHDCCRiNRiorK0ccqlEMjx1xxx13MHbsWG666SYOOeQQmSPzxz/+Ua5TUVERtE1OTg5Lly7lsssuk98tXbqU8ePHj2ifKgNRjZKDnDJvgPtO+YL0N98PUmddt0THHF7Fg5lQv2Ddd3q2V22tPvViFsXGs6PiUY1GQ0JCAuXl5cTExMgQDfSV+ZaUlKDX64mJidktxySEoLa2Vv7f7XazbNkykpOTSUxMpLm5mbKyMsLDw6X3Q6vVEhcXR1tbGxqNhpCQEDZu3MjUqVOJiIjA6XSi1WoxmUy0trYSFRVFXFwc27ZtA/qE1To7Oxk3bhxFRUU0NTURHx+PwWAgOzsbt9tNZWXlvjVKoM/gsNvRwqgIKan8Mj7+uO/fuXPhySfhD3+ADz+Ejz7au0YJ9IVkbr31Vl588UWOO+44Fi1axOmnn47D4eBPf/pTkKd00aJF+P1+Dj30UCwWC//85z8xm82kpqbyySefUFpayjHHHEN4eDiffvopgUCA7OxsbDYbt9xyCzfddBOBQICjjjqK9vZ2li5dSlhYWJBxsLMkJydz5pln8qc//YlPPvmEzMxMKisrWbx4MdOnT+c///kP77//ftA2t956K+eeey5Tpkxh9uzZfPzxx7z33nt89dVXu9yPgx3VKDnI2VTbwzv/1z8W26dd0QkMdlsFaVr8+04KbutkavqOp65OTk6mvb2dDRs2EBUVRXh4OL29vdTX1+P1epk4ceIui6L1RwhBYWEhjY2NxMTE0NjYCCA9FuXl5fj9fiIjI/F4PEDfG5vD4aCxsZHs7Gw2btwI9HlOysrKMJlMBAIBAoEAiYmJVFRUEBcXR3FxMXV1daSnp8uQT2xsLNXV1bS3txMfHw/8XHqoVAPtjuNUUQH41a8gL68vt0SjgfffhzfegBEWwexW9Ho9119/PY8//jglJSWUlZVx2mmnYbfbefDBB4M8JQ6Hg0cffZSbb74Zv9/PpEmT+Pjjj4mMjMThcPDee+9x33330dPTQ2ZmJm+88QYTJkwA4MEHHyQ6OppHHnmE0tJSHA4HhxxyCHfdddcvPoabbrqJww8/nJUrV/KrX/2Km266ieuvvx6Px8Opp57KPffcI8uaAebOncuzzz7Lk08+ye9+9zvS09NZuHAhs2bN+sV9OVjRiN0ZyN9P6OjowG63097eHhRjPBh5d+k6zjnqkF3a9vZPWzhvip4pcSM7h4FAgLq6Ompra+nq6pLJrElJSUHJaMMhhEAIIcXWtqe+vp6ioiLGjBlDcnIyFRUVlJeXo9frpQhacnIyvb29NDQ0AJCdnY3dbmfNmjVYrVbi4+Opq6ujvb1dtqvRaDAajQMUK/V6PcnJybKaZ+rUqaxatYqwsDCys7Pleo2NjWzevJkjjzwSw54O9o922tsJtLfTEGKkpMnFilVmZh0DuSnRGBsb1RCSisooZ0+Ooaqn5CDHZtQPqV1hopEHnljFvbceO6SmRbhl8OSywdBqtSQmJg5IUBsJbrebqqoqGhsbCQQCGAwGEhISSE5ORq/X43a7KS0tpaWlBYDS0lIaGxtJTU2VHhOfzwcgk1GhL+wSFxeHRqNh0qRJbN68maKiIkwmk8xJsVgs5OXl0dPTQ35+vtx/amoqLpeL8vJyQkJC8Hg8tLW14Xa7B+g1tLa2YjQaZd6Kz+eTOSpWq/XgMVTa2/GfeCI9NbV8/NefE6v7Eqg3cOl152BKUCcFVFE5WFGNkoOcnLgIyvNrSb7+Kbp5O2hZD+mYb3uKbs4N+l7RtKh57S5SJu+al2VnaG9vJz8/X3pJoC8cU1FRQV1dHRMmTKCgoACDwSD1RKKjo6mpqWHTpk2MGTMGm80mE1Ghr3LAaDTS3t5OIBBAp9PhcDg47LDDaG5upqOjg5aWFoQQTJ/ep8q6bt066UkpLi4mEAgwbtw4kpKSZIb/pk2bMJlMQVL4TqeThoYG0tLSEEKwbds26urq5OR+Wq2W2NhYxo4dO2Idlt1wUnHX11MloMLVy9q1YcycKchLiSG0tXWPeSv8Tic9NbWE1gQnVvclUJ+DqboCj0adFFBF5WBFNUoOchIDfi6+5mzub/ot8LN2xdf3e1m3NpbXxcUAHDK1geP+ZAjStHjg2nPQ/vD9Hk2QDAQCbNq0SVbRpKen43A46O3tpby8nMbGRjZs2IDBYCAuLk4qt6alpZGYmIjL5aK0tFS2p9frMRgMjB07ltbWVlpbWykuLiYnJ0dOzhUaGkpTUxPd3d04HA7cbjcej4eenh7Gjx9PWFgY3d3dlJaWUltbS3h4OCEhIXR3d+Pz+TAYDNTW1mIwGGhra6OhoYGwsDASExPZtGkTra2tpKSkEBMTg0ajobm5mYqKCtxuN3l5eYPmnPh8Pil/bbVah53NeIe0t9N73HGI+ga++9sHLCvL7Oet2Myl183DlBC3R7wVtboQbp7zBelvBSdW90+grjnlEv4Rn6g+nFRUDkJGXU7Jd999xxNPPMGaNWuoq6vj/fffZ+7cuXK5EIJ7772XV155BafTyZFHHslLL71EZmbmiPeh5pT0o70dMWcO35Qm8O/LnmDs+X3qrCEdHZgv+CuivhNNnI3uN66mNywMIWDbGx1csOgWjsuoQ/P55wRsNtra2qTWR2Rk5G57429ubmbjxo2EhIQwY8aMAe2uXbtWDtaK3okSpgGkRPxg6PV6/H4/Qgj0ej0pKSk4nU5ZkaPX69FoNHi9XkJDQ/F4PBx11FFy+46ODmpra3G73Qgh6OzsZOzYsTidThlGUub1SEpKorW1lU2bNuFwONBqtZjNZuLj47FarXR0dLB27VqysrJISEiQ+/D7/ZSWllJXV0cgEJDHGRsbS0ZGxi6dZ1dhIZrZJ2CtraEtKY1Tx69m2ReRHH5iC//ZPJXw6gp6U9MJ+WH3i6h9uqyEU4/IGnYdc5ifVYU+dVJAFZVRykGVU6K8LV5xxRWcddZZA5Y//vjjPPfcc/zjH/8gPT2de+65h5NOOonNmzcPmPVVZQTY7Wg+/5zjXC5mJiRQ5uymyw92UxiBzy6iddmP9Kan43F46fQ14e/qZPZ5GnKveQJNVBTNXi9bli+nt7dX6n7odDpSUlJISUkZVMF1JAQCAYQQMtk0JSUFvV6PEILe3l6EEISEhGA2m+no6MBkMnHIIYeg0WhYtWqVFD0LBAJoNBoiIyPp6OiQ35tMJg499FA5Q2h1dbX0qOh0OpKTk0lJSQH6kme3bNkC9BlJQghCQ0P75OR/uiFbW1vZsGEDERERJCcny2odnU4nDZvi4mKgL/RkMploamqipqaG5ORkxowZQ2RkJPX19dIoEUKwadMmnE4nycnJxMbGotFoaGpqorKyErfbzeTJk/H5fEEzL0dHRxMRETHkuS/3CR485SvS3nxvaG/FqZfuEW+F1rzjdfomBRzZ/EYqKioHFqPOU9IfjUYT5CkRQpCQkMAf/vAHbrnlFqAv3yA2NpZFixZx/vnnj6jdUespaW8Hl4ve2Fg21bbyww8Gjp0FOfEOdLW1+6Qqwe12U1dXR1dXF3q9nujoaCIjI9FqtXIgjoyMJC0tDZvNRk9PD9XV1VRXV5OWlkZaWtpO7a+trY3Kykra2tqCvldyPrq7u+U8FQaDAb/fTyAQwG63S5npqqoqqR/SH8WosVgsuFwupk2bJqt+nE4n69evJzQ0lMjISHQ6HVFRUYSGhiKEYM2aNUET+gGEh4eTlZWF2Wxm8+bNdHR0cOihh8oZkHt6etDr9VgsFgoKCmhtbSUiIoLc3Fygz2BSjKHMzEx6e3upq6vjiCOOAH72Ek2aNInIyOD5aFwuF2vWrCEmJoampiY0Gg1hYWH09vbS1dWF1WolNzd30DDPO1/nM2/25GF/hz3lrVi+pYIvmhl+UsCMDC7ICBuoo6KiojIqOKg8JcNRVlZGfX09s2fPlt/Z7XYOPfRQli1bNqRR4vF4pCYFEDQ19ajhpzBKT00tr7/0blCc/4gx67j0unMwxu+ZOP9w9JeS3p6ysjLsdjsTJ06Ub+Umk4mMjAw0Gg2VlZUkJiZK+faGhgba29vRaDQ4HA5iY2OD8idqa2vZsmULoaGh0uDQ6XR4vV4CgQAtLS1SGtpsNtPQ0CB1SLq6uuT6SgJpf52SnJwcSktLiYqKIioqivz8fBoaGqRRohhBbrebnp4e6UGJjo5Go9FIg0Sj0ZCTk0MgEKC8vJx169YRGxtLY2MjmZmZdHd3s23bNhm+gT4dlO7ubkJDQ2UIRmnLYrFgNBrZunUrBoNBynNrNBrq6+ux2WwDDBLldzGbzTQ2NhIXFydDOYp3afPmzWzcuJEpU6YM8JjorTueNnZPeSsmJUWzoWTTsJMC1v3zHpIn5+32fauoqIx+9sKk1ruP+vp6AGJjY4O+j42NlcsG45FHHsFut8tPcnLyHu3nLuFy0VNTi7mqknnXnEPxx315EMUf+zjnN2djrCjHU1cPP5WR7mu6urpwuVwkJSUNGiZISkoiEAjQ3NxMa2sry5cvZ9u2bfT29tLT08OWLVtYsWKFLItVvktISMBoNKLVapkxYwZHHnmknBfHYrFgMBhobm7G4XAEza3h9Xr5/vvvWb9+vfSkKNjtdmJjY/H5fJhMJmm0KHNxtLa2BslHh4SEEAgE0Gq1NDU1ScMG+rx1mzdvZuvWrXg8Hnp7e6mqqpJz5axbtw63201WVhbTp09n0qRJctuwsDCcTicdHR34/X7Wrl3Lxo0b8Xg8MizV09PDhg0b8Pv99PT0DNBvEUJQXV3N8uXL6e7uBn7WZunp6ZEG37hx4+jo6JAS+v0Jtxi5f2k5j725DDON9Enl9X3MNPD4W8twxAUINexa6G04QltbufTaeXzb1FfRlHu4k1s+bCX3sL5+fts8g4uvOQttTc1u37eKisroZ78ySnaVO++8k/b2dvnpr1MxWugMj+TSEz/nNttDLKieR8EX/eL81fO4zfYQV5yyBF/8zmt87AmUAd1sNuN2u3G5XEEJpYomh9vtZuPGjYSFhTFp0iTCw8Ox2+2kp6cTEhLChg0b8Hq91NXVodPppIx7dHS0DD0o5bWKN8TpdLJ06VKampoG9MvpdEojQvlXmVPHZDLR3t5OdXW1/L/P52Pz5s1ye8XzduihhwYlkSq6I2PGjEGj0cgqG5PJhEajQaPRUFhYCMDUqVNJSEiQoSAlF0TxzGzYsIFVq1bhcrkICQnB4XAAP08i6HQ62bp1qxR76095eTlbt27F/pO3zGAwkJmZicvlYt26dTJnJjw8XM43tD25yTHEtTUy6fon6SYaCJWfbmKYeN0TxDXXkmzdA9opNhumxHjmxK7i17eWcf4LPiKTA5z/oo+rbi/n5Dh1UkAVlYOZ/Sp8o8yy2tDQICW8lf9Pnjx5yO2MRuOQM0iOFlZvbeWdV/tP4tQn9x4k6/6vO7ntjm7yUiyDtLB3UQyG/Px8aaAoc8b4/X45cHd0dKDVatFqtWzYsEGW5HZ3d8tQS21tLU1NTbLSBKC6ulqGRPx+P0ajEY/HIw0fJQyiCJxB3wAdGhpKe3t7kBdFESaLiooK8ogoaq/K8fT29tLd3Y3H48Hr9QYl79bW1mKz2WTirE6nIzw8HIPBQHV1NZmZmeTn5+Pz+aThpAivKZ4eIQRerxedTieVYXt7e6UhMW3aNOrr66mqqqK+vp6MjAxKSkro6OiQZcgVFRWkpaURHh5OU1MTkZGRJCYmEhkZyerVq6moqCAzMxONRoNerw8KFymEd3ZyybXzuK/pWuDnMvD+5d4PXj0X7fe7v/pGmRTwWJeLmYmJVLp66fQGsIXoSH4kEu316qSABzKLFi3i97///aAevP5sn0+ocvCwXxkl6enpxMXF8fXXX0sjpKOjgxUrVnDttdfu2879QoTRv8N1blzsJBAyOn4yRaI9EAgwYcIEmpubaWhowOPxYDAY5Ay5HR0dGAwGnE4nOTk5REdHo9Vqpc6HUoHS29uLXq/H4XDQ3NwM9HljNm3aFGQMaLVaGX5R9q+QkJCAw+Ggvr5e9g/6pi4frDTYZDLR29uL3++nt7dX5nOsXr0ao9GITqdDr9dLYyg7O5sNGzYQExOD2+0O2kd+fj7QF15Zvnz5kOdNp9NJ74cyYV91dTXx8fGEhoYyZswYGhoa5Pmw2Wxs2LCBMWPG0NPTg06nw2g0smnTpgHHkpCQQE1NDWPHjqW3txe32z24eq7NhjkxnpM8K2m5tJSxF/SVgZ//YoDpb2zjpNdWYtiT3op+kwKmhW33sqBOCrhfMH/+fP7xj38M+L6kpGTYWXnPO+88TjnlFPn/++67jw8++ECKD6qojI4Rrh+dnZ1s3bpV/r+srIz169cTERFBSkoKv//973nooYfIzMyUJcEJCQn7vUVtCxla7r2/rLvduG/lyDs6OqioqJBhAb/fz5YtW/B6vaSmpmIymSguLsbr9ZKVlUVJSQler5fMzMygXCCz2UxOTg5tbW309vbicDiC9D0iIiIIDQ2lurpa5p3Az9oiyt+KoWEwGKisrBwwtbjCYFolSk4G/KxxYrVaMRqNMkdJ2ZfJZEKn09Hb20tnZ6dUhlWqa/onTxsMBoxGo0yOVTwWgUAAj8cjvS/19fUIIbDZbKSnp8t+REREUF9fj0ajITc3l+LiYlmSDFBcXIzZbCYiIoLGxkbi4+Ox2+3YbDb8fj9er5etW7ei0+kGn3nZbqftjTcwr1rFjdlujPFR+HVGjBo/XOuiccb5lGdmkq56K1SGYc6cOSxcuDDou+jo6GG3MZvNmM0jqAtXOWgZdTklq1evZsqUKbK88+abb2bKlCn86U9/AuC2227jhhtu4Oqrr2b69Ol0dnby+eef7/caJRMTI4lraxo2zh9VX0maY98dZ0NDA2vXrqW9vR2tVktaWhpWq1WGbyoqKiguLpYeBsUTAH35HUVFReTn57Nx40ZKSkqorKwMMiqgL4wSExNDW1sbVqtVDtYKyqAOfYaG8ndCQgKTJ09Gq9XK5NCIiAj5ANRoNHIfBoMBu90edM0IIQgEArS1tUnxNEDmlXR3d7N6dZ8k+valwS6XK+hhbDabmTZtmty3Uo0EfSEkJbQkhCAyMpLJkycH5a8oxlJYWBgGg4GJEycyY8aMoP729vbS2tqKEIL169fLmZGhzzPU0tJCTk4OWq1WeoP6U9baiikjg0mTJpIdHcb4CCNjwy2MHZNO/PTpVLa3y7CSispgGI1G4uLigj7PPvsskyZNIjQ0lOTkZK677rqg+2XRokUyh2rRokXcf//95Ofny7ysRYsWyXWbm5s588wzsVgsZGZm8tFHH+3lI1TZF4w6T8msWbMYTjpFo9HwwAMP8MADD+zFXu15TE1NXHLtOcPG+R+49uw9Lus+FD09PRQVFREbG0sgEMDr9UodkiVLliCEICUlhejoaNxuN0VFRaxdu1YObEqS8VA0NzeTkJBAW1sbjY2N6HQ6mTi6Pf2vD+XvlpYWurq6MBqN2Gw2PB4PgUBADvY2m016M3w+n+yL1WqVD01l4A4EAqSnp1NWVobP58Nut9PZ2Rk0sPc3LLRarawYCgQCdHZ20tnZSXd3N0ajkfLycrltdna2DNloNBopsKbgcrlob2/HZDIFGSGNjY0yDyUjI4OkpCTcbjdlZWWywkkxDq1WKxkZGbS0tFBYWChzfKKjo0lNTUWr1dLR0cGECRMGrZxKTEykoqKCpqamXZo8UWXvoHjrhiI0dO8L0Gm1Wp577jnS09MpLS3luuuu47bbbuMvf/nLgHXPO+88Nm7cyOeff85XX30FIBO4Ae6//34ef/xxnnjiCZ5//nkuuugiKioqiIiI2GvHo7L3GXVGyUGLEufv/SnOf/7Pcf4Zi0uZ89qqPp2SfVSVUFdXh1arJTMzk9LSUlwul9TT0Gq16PV62tvbGTNmjKyKcblcQYmog6EsF0JgMBiYPn06LS0tNDc309LSEhR2iY2NJT4+nvr6+gEl4EpIJTw8nLq6Omw2G06nE622zxm4vTZNXl4ebrebrVu3EhYWFrTc5/NRVlYm/694Z6Kjo+WxKbMKFxQUoNfr6erqknL1Pp9PelUUfRyLxUJXVxdr1qyRg4UQgra2NgoLC7FYLHR2dsr2x4//OenZ6/VSWVlJSkoKPT09bNu2DSEE8fHxjB8/XpYhazQaMjMzcTqdMuckPj5eis7V1taydu1aGfMfyrvYPydIZfSyfbn49uxpXcxPPvkkqA8nn3wyb7/986SeaWlpPPTQQ1xzzTWDGiVmsxmr1Yper5dFDP2ZP38+F1xwAQAPP/wwzz33HCtXrmTOnDl74GhURguqUTJa+Kkq4TiXi2Pi4ylubKfTGyDcYiTjsXS0Ny7Yp1UJLpcLh8OBXq8nJiaG2tpaWlpaiIqKIiIiAqfTicvlkoqsCopB0l/UDPpcv0qlikJdXR1paWlER0djsVhoaGgIyhuxWCw4HA4cDgcWiyVooj3oewgroRclD2UwgygsLIzw8HACgQAGg2FQMT2tVkt8fDwajUaWEPc3SAA2btwoJeSV/TocDrq6ukhLS6O0tBSv14vf75fJrTabLSg8BH1eIsUwU8TZ+qskKssVITqdTkdpaSnbtm0LMvrMZjNbtmyRCbvQJ0hnNptJSUkhISGB/Px8+fu4XC5sgxi53d3dUgpfRWUojj32WF566SX5/9DQUL766iseeeQRioqK6OjowOfz0dPTQ1dXFxbLzlUNKsrHStthYWFBmkEqByajLqfkoMZuh6Qk9DodE+IjODQliqwoG1qNpi9ksw8TD5VQQ1837YSHh1NYWEhdXR0JCQlSdVWpQgGCyrYV40N5MHm9XjlwKgNjb28vNTU19PT0UPOTeFZ/T0n/BDklgXN7Ib2R0N7eTklJCQUFBbLN7WfmVUJUSt8mTJggPQyKkJvJZJKeGCWnpKWlhbi4OGJiYkhMTByQywEwceJEOeBHRUVhs9mw2+2kpaVx2GGHDUhO9fl8supGq9WSnZ3NYYcdRlZWFmPGjGHcuHHy/GVnZxMIBMjMzOTII48kMTGRrVu30tTUhF6vZ8yYMXR3dxMWFkZVVdUAb4gQgvLycjmHjsroRQkTDvXZ0yhqz8rH4/Fw2mmnkZuby7vvvsuaNWt48cUXAXYpP0nJAVPo/wxSOXBRPSUqIyIiIoKSkhJ6enowmUxMmDCBoqIiiouL5cDcH51OR11d3YDvFY9BIBCQMvCBQIDw8HDa2trYunVrUPVVfHw8dXV1aDQatm7dKqtTlIeTUj68I5TwiUJNTU2Ql6G/8aBU4jQ1NUmPi1arlZom8HM8Xzl2pR9CCHp6eqitrR10/h0l9KTMEhwIBIbV2AGkCq3b7ZahH2X2YUCGmsaMGSP1eMLDw9Hr9YwdOxa3201FRQVRUVE4HA40Gg3h4eHU1NSwdu1aUlJSsNvtct6i1tZWsrOzBxhqKqOLfZEzMhxr1qwhEAjw1FNPyfvirbfeGnYbRddIRUVB9ZQcBAgh8Pv9OxVj9vl8NDY2UlNTQ1tbGzExMRgMBjZt2iQnmpswYQI5OTlBwnSK5yIQCMgse6vVKsMR/ZMrlfJft9s9YAI+BcUgsVgsctbc77//npUrV8r9aDSaoCqb/n1R+ra9MqrSLyV5FJDrCiGkh0aphNm4caP8bsyYMVJlVjFqlHNrNBrlHD4KoaGhhIeHExISIh/WBoOB+Ph42tradvi7REZGYjAYKC8vH7Cuz+ejtrYWjUZDQkKCNCT6C9rFx8fT2dlJb28vPp8PIQRms5kpU6ZgNpspLi5m5cqVbNiwgZ6eHiZMmBDk5VJRGQkZGRl4vV6ef/55SktLef3113n55ZeH3SYtLU3KPjQ3NwfNUaZycKJ6Sg5gfD4f1dXV1NbWSnXSqKgoUlJSBs0lgL7BdevWrdTW1gYNgHq9ntTUVCorK1m+fDlWq5Xu7u6gtxydTkdiYiI9PT20t7fLAd/tdpOamkpHRwdlZWUyd0LZNioqaliPhxBCJnKGhYXh9XqlsaD0UdlXeHi4VFPtL26m0D+ptX8uiVKFo8jGd3d3Yzab6enpkfke0CdZn5KSAvRVxCgS9REREbS2tuL3+wck93Z1daHVahkzZgyRkZEsX758wCSRw6EkGG/evJn8/HySk5MxmUy4XC5ZVm0wGNBoNNhsNkJCQqitrcVisVBfXy89ViUlJYSEhEhvU0hICLm5ufT09EhDMzQ0dNCKHBWVHZGXl8fTTz/NY489xp133skxxxzDI488wqWXXjrkNmeffTbvvfcexx57LE6nk4ULFzJ//vy912mVUYdG7OkU7VHInpx2ebTg8/nIz8/H7XYTGxuLw+HA4/FQV1eHx+Nh4sSJg5bWFRYW0tDQgE6nIy4uDovFQnNzs/RkTJgwgZaWFurr69Hr9URERJCQkEB5ebkc5LOzs2U5r81mCxI/Gynh4eH09PQECZxtnyw7mEprdHQ0zc3NWK1WsrKy0Gg0shJmqG2UWYxDQkKYNm0a7e3tbNq0adBSYIvFgs1mkxMS2u12XC6XNEJsNhudnZ1BBl16ejrt7e20trYSExODXq+ntrZWlv3uKHyj0NLSQmlpaVApqMViISoqisrKSmbMmIHFYqG6ulqKp/n9fkwmkzQ6fD4fVquVqVOnqsaHiorKLrEnx1A1fHOAUl5eTldXF1OmTCE7O5vY2FhSUlKYNm0adrtd6lf0p6enh4aGBoxGI0cccQQZGRmEhoZitVpl0uOWLVtobW0lKiqKI488kvHjx+NwOEhMTCQQCMjwRVZWFsBOGSQmk4lp06ZhMBhoa2sLEhQDBhgH22fz22w23G639KxYLJYB++9vkOh0uqDkuenTp2MwGKipqcFqtZKXlyfn+FEwm81Sf2TixImkpKQQCARk+Cg2NjYolAN9ibUTJkxg/PjxQXojPT09JCYmSg/Stm3baGhoGDLGbjKZZF8VMbiuri6qq6vRarVs3bqVQCBAfHy8NEi0Wi09PT1otVppkHR2dqpVDCoqKqMSNXxzAOL3+6mvrychIWFAmEan05GZmcnKlStpbm4Oql5REjnHjx+P3+8nPz+fjo4OQkJCBuQqpKWlBb1pR0ZGYrFYZGglMzNTyq0rE9z193SEhobKN35Fdr2npwePx0NERAQdHR2DGjSKZ0IJiSQkJFBbWwv0VeRUVFTI8MmyZcv6Klc6O9F3d9MTHU27NpT8fAd5eU7sfjfRPT20+Xxow8Koq6uTya2TJk2iubmZ7u5u2T/oCzX1z7dQ5uxQwln9PTtWqxWPx0NbWxvLly8nJiYGs9ksS4JjY2OpqanB6XSi0+nQ6XRUVVVJD5TBYMBisRAbG0ttba0sgVaMMaXMMjQ0lKamJlpbW1m1ahVhYWH4/X4ZylImD1TKM3U6nZxpWC37VVFRGU2oRskBiDKB3PbhGSEE7e3ttLS0oNPpaGhoICoqShocSjJoWFgYa9asobe3l0mTJhEREYFGo6G8vDyoAqU/Wq2W3Nxc1q9fLyfS0+l0sjQxOzubyspKwsLCaG9vx+v1Bg320OeFqK+vD5KS779OYmIimZmZuN1uVq1ahdlsDqrw2bZtG3FxcfT09OB0OqVBknv77eic7bzxygf8WJrJohvtzH++ncPTtzD96otJdtjZ8NhjQbonJSUleDweKaPv8Xiw2+2Ul5cTHh4uvRbKbKcul4uwsDB6e3ulN6KlpYWQkBBsNhsmk4nm5mZZGqmIpSmGmd/vlwabkmRsMpmora1l69at8hxkZmZKlVUlzNTT04Pdbsfn80l9F+jL5UlOTpbJsKGhoURHR9PR0UF7ezurVq0iNzc3SEVTRUVFZV+ihm8OQJQKD6/XKwXNXC4X69atY/369dTX1+P3+2ltbWX58uW0trbS2dkpwwrfffcdnZ2dxMfHS4MEgrUGBjNOTCYTmZmZwM9qjcqbeEtLCz09PXR0dNDT00Nvb69UQFXmvdBoNHR1ddHR0UEgEMBkMgUZLcnJyUCflyUiIgKdTidl3hXq6+txOp2yPX13NzpnO9baGs65+hyKP+4L3xR/7GPeb+Zhra1B52xH38/DAX2hFSEEnZ2dMiG1/af5YFauXMnmzZvZsGEDgEzaHTdunNxv0k9TAfT29tLS0oLT6QzSZomLi8PtdmM2m5k0aRJHHXUU4eHh8lzr9XrCwsI47LDDpNGoCLop2O12srOzpbCd2+0mIyND5gIdfvjhWCwWamtryczMZNq0aYwdO1YaNaGhoWzcuFEtyVRRURk1qJ6SAxCj0YjRaKSoqCioCkSj0ZCVlYVer2fz5s1MmDCB2tpaCgoKgJ8nn1PCHxUVFfT09DBu3Dj8fj8NDQ1y0GxubpZVNApCCKqrq7FYLEyaNEkO1lVVVTQ0NCCEkPkYitha/xwPxVNjtVpl+Wp/3G43RqMRjUaDyWSSCqsGgwGPx0NmZib19fVSAh+gOyqGK075irQ338Vc46Sgxgu42fhFLwuYR7fNQc0Zl3B9cj30dMnz1N8Y6v9/IQRCiKCcDKPRyOTJkzGZTERGRlJYWEh2djYmk0lqrrjdbjlRodVqpaamBo1Gw9SpU9Hr9XR2dtLW1sa4ceNwu91UV1fT1NTE2LFj8fl8cnbk7TVhlCoaJWzk8/lwOBzU19fT3d1NTU0NERERQXPYNDU1YbFYyMnJYcWKFXKmYRUVFZV9jWqUHIDU1tbKt/vo6GhsNhulpaUYDAYp6BUeHi6XLV++HKPRyKGHHsqqVavo7u5Gr9fLidk0Gg0tLS34/X7S0tJwu900NTWxdetWWZ7qdrspLy+nra2NiRMnIoSgsrKSmpqaAWqOubm5aDQa1q5dO8DwgIGz8CpGUkFBASaTiZCQEGl4KGEUZf6MxMREurq68Hq9VFVVsbHGw9v/l9OvtScBcAEP/PSH+V93cubZbRw+LpHKysoBpbpCCOmBWLVqlVSa7OzsJDk5maqqKjo6OjCZTERHR1NWVkZBQUGQYq1GowkqRVY8QYoh2NzcLCX8fT4fVVVVwM/JvTabjba2Ntrb24PCLRqNBr1eT3d3t5wY0GQysW3bNoqKinC5XGRnZ8v1GxoaaGpqIjMzE7PZLOcIUo0SFRWV0YBqlBxgeL1etm3bRkJCAiaTidLSUpqbm9FqtXIae4PBICd8U7wNio7JlClTWLFiBT6fj4qKCgA5+V18fDxpaWls3rwZvV5PfX19kDKq0m5ERASbNm2itbWV0NDQAR6R1atXk5SUNKimx/YYjUaZIOvxeKSmBvR5VJRqm5SUFDQajSzHtVqtREZGom+vH7JthRsXO0nPSaWnu0UaJFOmTKGiooLW1lb0ej2lpaVSDr6xsVF6bFpbW4mOjmbz5s3U1dURHh6OTqeTuSI6nS4oYTc6OhqdTkd9fT09PT1y/hm/34/BYECr1UqRNcUjpGiQQF/1U3p6OhEREWi1Wrq6uujq6kKn0xEbGyuNnIkTJ0rJf2VfbW1tdHR0EBsbK9VgVVRUVEYTqlFygNHY2IgQgtTUVIxGIzExMeTn58tqDI1GE5Qc6nK5ZJkr9Mk+T506lZUrV8qSVo/Hw7Rp07BarbS3t9PU1ER6ejoJCQm0tLTg9XoxGo1ERkai1Wqpr6+npaVFanbY7XacTidZWVlUVVXR3d0tPQE7ksnp77XoX73TP4lWkVRfsWLFAC+HQRfK/UvLMVXXcd95Y+nm5zJiM27uf6sUf1yAMGMIVVuqsNlsCCGkRomC0WikoKBAGldRUVG0tbXhdrvx+/1kZGTQ2NgoxeGsVisRERHU1dUhhCAqKgqn00l3dzcTJ06Uhl5BQYHM/eju7paTlwUCAXk+7Xa7FJdzu91s3LgRnU5HTEyMNCr9fj+dnZ3U19cTExOD3W5nxowZrF27FpfLRXd3N6GhoUyYMIGoqCgpEOdyuVQDRUVFZdSgJroeYPT09MicEkCGFAKBABkZGcTExCCEkCEVZZZbs9ks38YtFgtjxozB4/HIJMuenh5KSkrIz88nLCyMxMRE9Ho9sbGxJCUlER0dLb0eNTU1UiNk4sSJMp8hMjKSGTNmyLf57XVGDAYDDodDaoNsL+6lGCRarTYoOdPn81FaWkp4eDi5ublBx+IQ3cS1NTLpt0/STTQQKj/dxDDxuieIrCtH19HnTYqIiKCrqwun0ym9Sn6/n5CQEHw+HzExMVKdVUlm9fl8VFZWEhoaisFgICoqimnTphEfH4/X6yUrK4vx48czbtw4mVCseFR6e3tZt24dGo0GrVbLhg0bZI5PZmYmTU1NQWq3DocDo9GI3++nrq4On89HSEgISUlJ6PV6ioqKKCgokKJpGRkZBAIBkpOTyc3NJTo6Go1GQ29vL5s3byYkJGTABIAqKioq+wrVKDnAMBgMA5JE4+Pj8fl8lJeXS4+IYhiYTCZ8Pp+cy0UhJSWF8ePHy1DJxo0baWxsJCkpidzc3AGTtXk8HrZs2cLSpUuljkhISAhGo5GwsDA0Gg2NjY1yMjgYOB+N1+uVxgAQlEjbfzZfs9lMUlIShx56KA6HA5fLRVZWFuPGjaO3t5fu7m6EEOh0OkIaGrjw6jP5tnk6ALmHO7nlw1ZyD3MC8G3zDC64ai6Na1ZjMBiIjIwkEAiwfv16qfRqNptlPkhrayuxsbFywj7oM0qUKpve3l7a29txu93S06KUZivz37S2tjJmzBgZturu7pZJyV1dXQghiIyMxO12U1RUJOf2SUtLGyBPr9PpOOyww8jIyCAvL4+8vDza29tldVR0dDQpKSls27aNlStXUlJSwubNm1m+fLn02qgT76moqIwW1PDNAUZMTAylpaXU1tbKOVrMZjNjxoyhtLQUnU4nhcsqKyvlZG4tLS0kJCTIwd/v98uEzJycHOx2u8x1cLvd9PT0EBISIgXC1q1bRyAQICkpidraWllds3btWvLy8oiJiaG8vJywsDCp7dGf7SteFJTvlMG2sLCQ5ORk4uLiZD8BmaipCKkpCrZrv/mGgMPOyf7VtFxSytgLwtBo4PwXA0x/YxuzFy7D77DjNZnwezysXbtW7lsRilPKl5V+pqWl0dTURFtbm/RSKOdWWSc/P5+xY8cCSG+G4g0RQmCz2ZgwYQIbN26U+1G2NZlMtLS0yAkLo6KiyMrKIiQkhLS0NJxOJ+vXryczM5OSkhKcTmeQ4ZOYmEhdXR1paWnodDrGjBlDREQEtbW1OJ1OtFotqampxMfHD1CsVVFRUdmXqEbJAYbJZCIxMZHS0lICgQCJiYkYDAbCw8OlMeJ2u9mwYQMGg4GUlBSioqLYuHEjK1askPkZbW1t+Hw+MjIypOpre3s727ZtC5rIzmKxyMF42rRpMrRQXV1NVFQUXV1dFBUVccghh9Dd3c26deuG7Pv06dOl+JqCMl9LZ2cnMTEx1NTUUF5ejtFoxG634/F4ZFIoIKtQsrOzKSsrw2+1suHxxzlqwgSoqKDdbcGr1ZOeEItvXguBGRexwWzGb7XKfSoJp4pHQvE6abVa0tPTKS8vl3k5Op0uSHQNftZzUdRT6+rqGDt2LC6Xi56eHjlXhNvtRqvVMn78eFwuF1qtltjYWEwmE16vl8bGRkpKSsjOzpYVP9BXvaPMTVRSUjKguik6Opqqqircbrfcl8PhkLM2q6ioqIxWVKPkACQjIwONRkNFRQXl5eUy18NoNDJp0iSsVitCCOn5AJgxYwYNDQ20tLTg8/mIi4sjISEBIQTFxcU0NTX1KaTqdCQlJcnZgCsqKnA6ncTFxck8lqSkJGpqamhoaCAzM5MtW7bQ0dFBWloaGzduHLTaRqfTsW3bNmkAKMaIyWSis7OTqqoqysrKZFVLfn4+ISEh9Pb2yrf9np4efD4fQgjy8/N/DgOFhVGv14MQhItu8ENaWArVHUbaoqMxmUz4fwpTQZ+HRK/Xk5SUhE6no7q6Gr/fTyAQYMuWLYSEhMjwVyAQIC0tjfLyciZNmkR9fT2VlZVAX9VLUlISFRUVhISEyKqdyMhI6uvrpedoy5Ytsq/l5eVERUWRkZGB9SdDqbOzU8rEd3V14fF4pLAbMMDb0d+ro6KiorI/oRolBxjd3d1UVFTIKhyNRoPVaiU+Pp7Y2NgB4lsKWq0Wq9Uq80CsViutra1s3LgxqFTVbDZTXV2Nz+eT+hdOp5Pm5mYCgQBarRaTycT48ePZtGkTW7ZsAfpmH1aMmsHw+XxyTpjtjwf6vDRms1lWnGRkZEgPRW9vrzTAlAHZ7/fLbQOBgBQ7CwQCaDQaCgoK5Lno6WeQ9O9PdXU1QJDUfHZ2NnFxcfz44494vV7Gjh1LaWkpERERWCwW0tLS6OzspLW1VXptLBaL1IexWq2ySshsNtPe3k58fDzx8fHo9XpaW1uprKxk/fr1TJ48GYvFQkVFBc3NzVKJV2HTpk2EhITIHB2FxsZGDAYDoaGhg55rFRUVldGKRuyoJvMAZE9Ou7wvcbvdrFu3Tk5UFxoaSmdnp8wbUQa57WlpaWHbtm1BiacmkwmPx4PJZCI8PJza2lomTJhAdHQ0DQ0NUrU0NDRU5mFMnDgxKGHW6XTKSpCRsn1uicViGZAQ23+ZxWKR1SlhYWGEhITQ1tY2rAaKTqcjOTk5yIukkJ6eTnR0NJWVldTX1w+a62K1WmXZLvTJtfefUTgQCLB06VL8fr/0qAgh8Pv9Mmk1Li6O0tJSxowZI3N/hBA4nU5qa2tpamrCarUSGxsrDZrY2FhiY2Pp7u6W8+FYrVamTp0q+9nU1ERhYSGpqamkpaWN+LyrqKiojJQ9OYaqnpIDiKKiIil5ruQgREdHk5iYyLp169iyZQuTJ08O2qa5uZmNGzcSHh5OZmYmFouFuro6Wb3h9XqlpkZdXR0RERHExsbS2NhITU0NU6dOlTMBb+9xcDgcREVF0dDQgMFgICwsjPDwcCm9Phj9DQCTySS9HTabjUAgIMM3er2e3NxceQzQd6P0NzKGEmXz+/3y+LYPcZSVlVFWVhbUn5iYGCwWC+Xl5eh0uiAjKS4ujszMzCAPUG1trTTElNLoqKgoHA4Hvb291NfXU1ZWJkNh0OeZ2bRpE21tbZjNZoxGI52dnUEhmoaGBjnZnpJ30tnZyZo1awgLC6Ojo4POzk5ZcaOioqKyv6EaJQcILpdL6oL0T4oEZNVGYWGhnO4e+gbcrVu3EhERIeeqaW9vlzkQij5HdnY269atw+l0UlhYKD0ixcXFCCFISEigrKxM5pbo9XoCgQD19fU0NDRICXslXKIk4SrYbLYg1VOF/kbO9st9Ph+rV68mLy8P6POSZGZm0traitPplIN7aGhokM7H9mzvxVH62L9/SujHYDAwZcoU1q5di9Vqxel0ypBKdHS0nBOnpaUFi8WCx+PB5XKRl5cXlGSakpLC8uXLZf4LQHFxMR0dHUyYMAGDwUBbW5v8HXp7e0lKSsLhcODxeAgJCSEsLAy/38/KlSvxeDxS5l5Re1XzSVRUVPZHVKPkAEHxICiloduj5B243W5plDidTnp6esjJyZGDWEVFBaGhofINX5lHRpkQrrm5maVLl8okTOgzHjQaDc3NzSxbtgyLxUJPT4+sohk/frwc7Ds7O2VehyKCNphBoqAkvEJfAm1ycjIGg4GtW7dSW1vL+vXr5XoGgwGbzYbD4SAlJYW6ujra29sHDeP0b1dhR5L3SkVMXFwcdXV16HQ6mYiraJaEhobKRF9lVt/tq150Oh3h4eE0NjbS1NSE3W6nqamJiIgIiouLg/rl9XoJDQ2lurqapKSkIFepXq8nPDyc7u5uDjnkkCH7PRLU5FgVFZXRgGqUHCAog74i+b49ioHQP9FVKXlVDAwl2TQrKwutVis9BMXFxQQCATlwKSXDGo2GoqIiGhsbGTt2rMw3URRLAaqqqoImkFPCD0IIJkyYwIYNG4iPj8dgMGA2m3G5XFJrBPrmoFm1apU0Otrb24mMjCQ5OZna2lppRLS2trJ8+XK5XUhICKmpqWRnZ7Ns2bIBxsZgxsdwBkn/mZOzsrLw+/2MHz+ewsJCTCYTKSkpGAwGOjo6qK6ulvHWyMjIQdtLTEyksbGRxsZGaYS0tbWRlJQk5w5SDB6PxyPLoreP3/b09AzwjI0U4XTSWlFBRSBApctHfr6DI4/0Mjk1lqjubrDZoN9vp6KiorKnUY2SA4Tw8HC0Wi21tbWkp6cPWF5XV4derw96a1cSM7u6urDZbHJwNBqNOBwOtm3bhtfrRQjB9OnTcblcbN68WeZ5KOGKsWPHkpSUhEajITU1Vbbf0NCAEAKPxyMNpf45Ixs2bAD6DKbk5GQsFos8BkVNVane8fl8MtdD8TRs355OpyMjI4PQ0FBqamooKSmhvr5eVv30D9UolUl6vT5IFwUGF3ILBAJyjqCWlha0Wi3R0dEYDAZqamqorq4mEAhgsVjIyMggMjKSFStWDJnkq8wcrISblPOuhNSgz8NUUVEhDbntjSaXy0V7ezs5OTnsLMLpxHPssZjqGyl67BW+7DiSRTfamXOjmzNOKOLSa8/EHB2F5oMPQM1PUVFR2UuoMvMHCAaDgcTERCoqKoI8CH6/n6qqKun+75+QqcwzU1VVJXVLdDqdDHmYTCagzyDYsmWL9JxAn8qoMqfNUDkMkZGRUucD+gbVtrY2IDhM0NbWxurVqykqKqKoqAjom/cF+kqBldmHlbCTEkZSjlvpg9/vp7i4mOrqakwmE3q9HpfLRWhoKBqNJsiDJIQYcjLA7Q0dBUVLpLW1lbCwMNauXUt+fj7Nzc3o9XrS0tKYNm0aSUlJsqxaSRLenubmZrkf5bfq6emhurqarq4uJkyYgMVikaqwyv6FELLEecOGDVitVqKjowfdx3A4q6rw1zcSWl/LeVecwba3+0Jonz8XSuTlz2GprkJs2ICYOxfa23e6fRUVFZVdQfWUHECkp6dL70JZWRlms5muri58Ph+JiYlBXgxATiynGAKpqanExcVRU1NDZ2enzPVIT0/H6XRKJdfJkyej1Wrl/51O56CaGHq9npSUFMrKyqT3oaurKyh3w2QyyYRWZQA3m81ERkbKbfx+PxEREURHR+N0Otm0aRM+nw+tVovX60Wj0TBx4kTa2tpkOEmv12O322lra0MIgc/nG5BDAgzwkmyP3W6X+imK10Mp3Q0PD2fcuHHo9Xqam5spLy+nvr6eQCBAb2+vnMm4pKSEMWPGSAOno6NDnvNDDjmEoqIiGYZJTk6moqKCmpoawsPD5fEJIdi8eTM6nU4aJuHh4eTk5AypPTMcFX54YtYHjFn8Dlp/gPXfaYG+vKSHm3/NBuKI83cyv+lTQl0uNYyjoqKyV9glnZLW1lb0ev2w9cmVlZWUl5dzzDHH/KIO7gkOVJ0SBbfbTX19Pb29vRiNRuLi4gbVJ1Gor6+XoZr+KGWmmZmZNDc309bWRkpKCq2trbJUVSEhIYGMjIwBA6QQgoqKCioqKhBCBBkkg4VJNBoNM2bMkKEipTJHr9fLv30+X1DFTkREhCwPdrlcrFmzhqioKNrb2wcck1KJVFVVhcfjGTKPZKi5eBRSUlJIT0+XHp+enh7Wrl1Lb28vdrud2NhYurq6pNdKp9PJ6hnl3KWlpZGWlkZ+fj4+n4/u7m40Gg02m43W1lZiYmJobm6WXp6srCw6OjrkpIb9k413lne+zmfe7MnDrmOkidOu7GbxX5PQ69QEWBUVlT725Bi6U69YP/zwA5MmTSI6Oprw8HAOP/xwvv/++0HXXbhwIccee+xu6eSopb2dQGUljU3NLN1cxtOL6llf2YjP74fq6n3m9g4NDWXs2LHk5OQwZsyYYQ0S6NPaOPzww5k4cSJZWVnk5OQQFxcnB/2SkhK8Xi+ZmZnU1tYihGDSpElyUE5NTaWuro7CwsIBbSsT2E2dOhXo000ZN24cEydOHHAx63Q6YmNjMZvN0piYMmUKMTExctBWPDL9q4xsNpv8WwnntLa2ynX6G0qK+mtUVNSwHgbFINHpdEEhHI1Gg8FgIDU1NSgEtWXLFmks+Hw+aaQdeuihGI1GKaJmsVhITk4Gfp5EMCYmBpfLRU5ODtHR0bT/dN20traSkJBAIBAgLi5OVhUlJyf/IoMEwGDb8czAHqL59O1EihuG9yapqKio7C5GbJQUFxdz0kknsWnTJjIzMxk/fjwrVqzguOOO47HHHtuTfQzC7/dzzz33kJ6ejtlsZuzYsTz44IPDvtXuEdrb8Z94It1HHMkHK8v4v/9F8IfL43j2IyN//+86PEcdDXPm7DfxeK1WS1RUFAkJCcTGxjJu3DiOPPJIYmNj0Wg0JCUlyUnj8vLypABZfHw86enpjBs3jqampqDJ+vqjJNVGRkYSFxdHVFQUU6ZM4bDDDmPatGkcccQRssJGCbcAVFdXk5CQgM1mo6enRw7YFRUVQJ9B0tjYKEMrxcXFQF++zFAJoh6Ph6qqqqBwzvY5Mcr//X7/gARZq9UaZKh0d3fT2tpKWlqanIRQwWg0MnbsWDweD+np6YwfP36AMRYTE0NoaCjFxcU4HA6mT58O9Bktzc3NGI1GacDsLqJsFu5fWr7D9W5c7ERjOuhEn1VUVPYRIzZKHn74Ybq7u1m8eDFFRUUUFBSwfPlyMjIyuOuuu7jnnnv2ZD8ljz32GC+99BIvvPAChYWFPPbYYzz++OM8//zze2X/Ct7WVnpqagmtqWbeNedS/HHfAFf8sY95V5+DsaKc3roGGEaDY7Sj1+vJzs4mOjqaoqIi6uvr0el0rFu3js2bNxMZGUlGRgbQN7AajUZpCGyPwWAYNPHTZDJhtVpxu914PB4MBgMrV66UlTalpaWsX7+erq4u4uPjgzwkJpOJ7OxsPB4P+fn5NDY2ykTa/vPo7Cjnwmq1DiirHSxxV/F2bC97r3iUuru7aWpqGrA/pSxYCdvY7XY0Go1MHNbpdOTl5REaGsrmzZtZsWIF0FdOHRISQl5e3i6X/Q5FbnIMsW3NvBc1F+gc8DHSyIt/+RBHXIBQgxq6UVFR2TuM2Cj55ptvOOWUUzj33HPldzNmzGDFihXMnDmThx9+mLvuumuPdLI/P/74I2eccQannnoqaWlpnHPOOZx44omsXLlyj++7P9UaPfPnfMFttj+zoPocCr7wAm42ftHLgpp53GZ7iMtPXYIvPnGv9mt3o9VqycnJkcqpWq0Wu93O5MmTmTBhghyAlTldlAqV7dFoNCQnJ9Pa2kp5eXmQ96Kzs5OioiLMZjOlpaVSKn/MmDFyn8q8MbGxsUGzAns8HvLy8vB4PGzevDlof8p6ysy8Q9HZ2RnUb51OF9Q/xSBQtEj654V0dXXJiQFrampwOp34/X7Wr18v21Q8Msq5CgkJISYmhvLycun5UYwPRcjOarVyyCGHcMghh2A2m4fs+65iczq57LpzWN58GBA64OMhmonXP8WYwrUkW3evQaSioqIyFCOuvmloaGDSpEkDvg8LC+PTTz/lV7/6FY899hiBQIBHH310t3ayP0cccQR/+9vf2LJlC1lZWeTn5/PDDz/w9NNPD7mNx+ORQmHAkCGGnWFjtZt3Xh3f75snAXABD/z0h/mfd3LXH71MSAgZpIX9B41Gg8PhkAqiinekP8q8NHFxcfj9fmpra6mrq6O7uxudTofNZpOKq+Xl5dTU1GC32+nt7aWjowOLxYJer0en05Gbm4tWq5WqqUporra2ltraWsLCwoiPj6eiokLO9quoxCrrHnrooeTn5wN9HgxFW0VBkW/vT3R0tFRmjYuLA/qMjo6ODiIjI4mNjaW0tBSDwUBBQQEZGRmUlJSg0+mk5kkgECAtLY3KykpWrlxJSkqKNKj6a8RkZmbS09PDunXrcDgchIaG4na7cTqdhIWFkZubKz0zQ+H3+/H5fPK87RQ2G6aoCE6r+ZTN/hw+4VfkHu7khNsDvPN7HRXldv4TOIUH77wa7TE/wE9z9KioqKjsSUZslERFRQ05mJtMJj7++GNOP/10nnjiCQKBwB6bNv2OO+6go6ODcePGSUGsP//5z1x00UX/z95/x0d6lvf++Ht6byqj3lfSrtp2FxwMBmJs4BCKl5BgbAiH2NjGAQ7N5OBgShxqfMKPE0hCMN8EMA7BMRyCMSGYYq+9XatV79LMqMyMNKORps88vz/k57Zmpa3W2lvu9+u1r5c088zz3PNIq/ua6/pcn+uUr3nwwQd54IEHNnUdGsuZ6+yr9fjLY3y8RqOhvLyc2dlZqqurhYeJSiAQIJPJUFpaSnd3txhC5/F4mJmZEWUV1Sskn8+TyWQwGo1s27YNh8PBgQMHRItrLpcjGAySz+cpLi7GZDIRCATQarXE43GxqUejUSoqKojH4ywvL7OysoJGoyEcDp+23XejjE4wGESj0ZDP5wmFQsIMraWlhfLyciYmJtBoNHR1dTE4OEhvby+w2sKsmsRZLJaCgX5qFuXkEpFer2f79u0Eg0FmZ2dZXFzEZDIJsespS07RKPG5OcYzWUYWVjh2zM3OnVGai+00GPSYS0vPrn3X5YLHHuOVb3kLuZl/ofz27TS+w4ZGA3f8e57Zf+7h5h8dwFhZsersKpFIJC8BZ90S/KpXvYpIJCI+fW5EMpnkzW9+M7/61a/EBnYuY+vPhkceeYSPfexjfPnLX6a9vZ1jx47xoQ99iK997WvcfvvtG75mo0xJTU3Ni2pn+u2JYZ5aMmL2zfCZP24iwQsdLhZWeODRMXJbtvAnW5zUOS7tTIlKOp3myJEjKIpCXV0dRUVFYoqw3++nuLiYfD5PNBpl+/btGI1GDh06hN1up6mpSXTxbNu2jYGBAfL5PHv37hUmZ4cPH2b37t04HA7GxsaYmpqipKSEjo4OYLV0V1ZWRiQSIZPJ4HK5RBllZWWFkpISYrFYwc8aCjMgKhu1/BqNRtxut9B6NDY2UlFRQSqVwu/3MzMzI9p4FUXh2WefFa2+drudycnJAuv+lZWVgmvU1dVt6LZ71kSjZP/wD0n5Z/j+Pz7GM2PNPPxBF+/5epRrG4Z51x1vxVxVie7JJ8/eVyQahViMfFUV08sZVjIKNoOGGrsBrd8vreYlEsk6LoqW4Ne//vWcOHHitEGJ2WzmJz/5Ca997WuZmZnZlAWezMc+9jE++clP8s53vpPOzk7e/e538+EPf5gHH3zwlK8xmUw4nc6Cfy+WjqoSyhfn6bznKyQoZW09PoGXjru+TFnQd1nV441GIzt37sRutzM0NMSzzz7L4cOHmZmZQavVEg6HWVxcJJ/PMzAwwOjoKBqNhs7OTjHFN5lMks1m6erqIpVKMTs7K9xk4YWBfTMzM9hsNmKxGPl8nlQqRTqdxmq1ivOomZR0Os2ePXvo6OgQ2pe1qAGJ2t7rdDoLSint7e3A6u9vW1ubMIcbGxvj6aef5tChQ4RCIbZs2SIM6NSMitfrpaWlhaKiImGnX1lZiclkwmw2Y7Vaueaaa9BqtUxNTb2oIF1ZWiIVmMEW8HHLHfsKxdV37sPm95EKzJybuNrlgupqtBoNdQ4jbUUm6hxGtBrNaslGBiQSieQl5KzLN+94xzvo6emhu7t7wz/8Kmop54477hBtm5uJ6gi6lpOFiS8FRSsrvPsDt/CZ4F0AdF0b4cZP5nnyQS3Hn3XzVOgqPnfH29D+7reXRz0+GiUdDjNnMBIzODg2Vcb11yvYUlEWjndTXF+Pp75etIwHg0FCoRAlJSVCG6HqSmZmZkQHy8jISEHb7+TkpPApaWxsZHBwkOHhYTFVWC1tqDqSRCJBS0uL8O2wWq1UVVXh9/vXvQU1IFhbhjSZTGLCshqouN1udu3axaFDh8SAPLfbve73zmKxiHNNTU0B0NLSQnFxMYqicPDgQex2O2azmYqKCvx+P8FgUOhVznS/icWIOp2c8C/wzH4Du3cl+fubnqThkX/H4ovS41sVV/c8meZDfBSvPYLvTbfyjysJ7NGoDCgkEsklx1kHJVu2bOEHP/jBWR1rMpl4+OGHz3dNp+V//I//wRe+8AVqa2tpb2/n6NGjfO1rX+PP/uzPLsj1TonDgbmqktenDxC+bYymdzrRaOCd38hz9aMT3PzdQxjLyy6LerwSiZB6zWvIzs3zxD/8B/vH15YNpnn3Rz6KpbqSlX//d2B1s+7q6uJ3v/udaJeFVUv3TCYj5taopNNpob0AOHbsmPi6trZWbPhOp5PR0VGRIVEt6l0nbb6qs+z09PQZ31s6nWZiYgJYdaVVsdvtoutlbRvyWioqKhgcHCQSiQirfDU4mp+fF9oXWB2Y6Pf715WWNiQaRbnpJhI+P4997bscGKjn7++v4l1fXuJH3177XlfF1cvA//f8F9bvfYKHHmvHXuuCX/5SBiYSieSS4pKbffP1r3+dT3/609x1113Mz89TWVnJHXfcwf333//SLsTlQvPEE7wmFuNVlZVMRJMsZ/K4zUZqHixGe8/fXjb1+JmhIZxz89gDfvbduY+H2w4Bq2WDr/XegsU/RVqvw5rLYTabmZubo6ioSMzeicfjWCwWjh49Cqxu3Nu3b+fAgQMFRmmw6neyuLhIJpMRRmgGgwGr1Uo2myUajRZYuwMcPHiQsrIympub0ev1aDQampqaiMViRCIRysrKSKfTQmy7FlXzYbFY1g3sUzt6TkVZWRlzc3McP35cBDCq4DcQCFBWViayL+ok4DO56wIQi5H0B7D6prn11pv4le67QAOHz+IzwQHzKyibGyK/aFrVhFwGv38SieTK4ZILShwOBw899BAPPfTQy72U1T/4Lhc6oMlz0mZzOZRsWO2SGUll+MYb/4u6R36MxbcoygYnnkzzEPtIONzMvOk9fKeykhqtluHhYex2O2VlZYyPjzM/P49WqxVtuV1dXfT29q7rjtHpdMRiMa677jr6+/uZm5vD7XbT2dmJTqcjm81y6NAhMpkMZrOZjo4ODh8+TFFREaFQiGQyyfbt20WZxel0EolEWFhYKNCQnIzdbmd5eZloNCqOi0ajpFKpU2ZJYNV3pLOzk/HxcaGhmpycxGAw0NDQQG1tLRqNRgQpqmvumUiUeLntxidofOTfMa9EeZzrgRVGjuSAOdo0vfQrLSgU6pW0pHk0+H+AV+EwGfmQzXHp/QeXSCRXNOc1kO9S53IfyLeZLCws8OTBcf7kpj2nPc7izHGwP0tbhYHR0VF8Pp9o2V6LyWRCURTS6TR6vR69Xk9XVxcDAwNCn/GKV7wCg8HAc889RzKZxGw2i+GAyWQSi8XCjh07MJlM9Pf3EwqFqK+vZ3R0lPb2djFNuKenB4/Hg06nK3CatVgsWK1WFEVhYWGBxsZGZmZmcDqdbNu2jZWVFXp6etDr9ezevfu02RJYDdyWlpYYHh5mZWVFBCVOp5OFhQUmJyfJ5XJs2bKF6rMIVp/pD3Jdm/eMx50OoynLweEcXTWXR+eXRCK5eLiQe6j8ICU5LdlsFr39zE1aqieLRqNhy5YtlJaWcuLECRRFEWUc1csDVvUYy8vL2Gw2rFYrXq9XBCUzMzPU1dVRUVHB1NQUbrebRCJBJpPB4XCwc+dOkQ1RO3FGR0fR6XRCOBuNRnG5XGzduhW9Xi+m7tbX1wu/EEVRGBsbY2xsDK1Wy8LCAseOHSMSiWCxWOjo6DhtQKIoCtPT0/h8PuF7omZGhoaGxHFqOelsAhIAzC9etK0xaPAnMnQhgxKJRHLpIIMSyWmxWCwY8lkeeHri9J4s5Xm0mSSZjJZYLMbk5CTZbJYdO3bgcrkYGBgQhmZGo5GWlhZ6enqELiQWiwlr+NnZWerq6kgkEhiNRrZu3Qqs+pQUFxcXdMGoJmShUIjR0VEymQw2m422traCScCq2+paAzM1WFADqHw+j1arpbW1Fa/Xe0aX1OHhYQKBABUVFZSVlaHT6QiFQvh8PvR6PUVFRTgcDioqKs6YbVlLkc0s7vcn/vjas37dWj70aASb3XTmAyUSieQi4qx9SiRXJg6HgyqrlopIiM57vnpKT5biwAQz/Ud5+umnOX78ONlslu3bt4vOmIqKCjKZDBqNhmw2SywWw+v1EolEmJmZYW5uDkVRKCkpETNt5ufnKSsrE2sxGo2ifXctWq1WDAT0eDx0dXXh9XoLgpfS0lLm5+c3dHLV6XSk02mampro6uqioqJClJ5O5SuytLREIBCgpaWF1tZW3G43DoeDhoYGtm/fTjqdxmazUVlZuWFAkkqliMfjG56/pdS5er/v/gobDcuDZcyM8R37/9jwuR+5/4gapqmxy88cEonk0kL+1ZKcka02G9ve/4d8NngPcApPlnveQfynPyHt9WI2m3E4HAWbsdPpFC6/iqJw5MgRTCYTGo1GdNm0tLSwvLyMXq+nu7sbvV5f0KZbXl7O6OgoKysr68YYLC4usrS0JIzQTqaqqoqZmRmOHz9OS0sLjudbtRcXFxkcHMRiseD1elEUhZmZGfx+vwiAnE4nNTU1lJaWivPNzMwI/5GTcTqdlJSUMDMzU1iyiUZZmJxkLJPBt5Knu9vNrl1LtJY6aTDoMRQVgcuF1u/ntrtu4f7QnYCNaw3Psj9zTcE1kjTw/eV7WA0OC/lx5Bb+/n1vwv7cM+Cs2fB+SCQSycXIiwpKZmdn+fGPf8zAwADxeJx/+qd/AlYdNMfHx+ns7LwgE04lLy32igpyVRXcmHmO8O2jNP2JS3iyXPNvk9z88Koni7Gm5pQtqBqNhtbWVvL5vLBxV/UlalZieHhYtOiqk4JVp1dYDUpmZmY4duwY9fX1lJaWoigKc3NzTExM4Ha7TzkN2GQysX37dnp7ezly5AhGoxFFUYRORZ14PDg4yOzsLCUlJdTU1Ijz9/b2Cot5WB3yd3LgtRan00k4HH7hgWiU9Gteg3F2jqP/9DjPjLbw8L0vWMRX3fFWdNVVaH/xC3A4MFWUc3P8OZpT9zC0VMN+rqHzmgjNnSvMfGeK/dlr8bE6gXrnrjle+1cGfvHXWnqec6/+zBaCaM/F2VUikUguAs67++b//t//y//6X/9LbCwajUakont7e+nq6uKb3/wm73//+zdvtZuE7L45D553GE2WljK5lCKFDpfZcM4zUhRF4dixY8RiMSoqKsRwP7/fz+TkJPl8nq1bt1JSUrLhhp9OpxkaGiowYNNoNMKn5Ew6ELXjRvU78Xg8uFwuNBoNwWCQ3t5etm7dus51dWJigomJCTGb58SJE6RSKXbv3r3hdYaHhwmFQlx77aomJD02RvqV12MP+FmsrueNbYfY/2Qx194Y5md9e/D4JkjU1GJ55unVdvJoFPx+lPe9j/8er+IHt32Fpnfa0WigaGQQ5Z7HyAXjaMqdJH7w56SdThQFJv5thT/59od5dd00/Nd/nbtPSTRKKhRiGg2jCyscPGTnuldk6KwupjgeR+N0Su8TieQK50LuoecVlPz0pz/lj/7oj9izZw/3338/P//5z/nmN79ZUB/fuXMnlZWV/OxnP9vUBW8GMih5eclmswwNDYmMiYrD4WDbtm1nZTCWTCZZWlpCo9HgcrkKMirnSj6fZ25ujpGREfL5PBaLhbKyMiorK4UwNp/P89xzz1FUVERra6sIYHbu3LnOUTadTnPgwAEqKipoamoCYHximo9/fpmGRx/DElvka/wvlnHgYIkP8zUSDjfT77qV7/5dNUbDmsDqVAPzcnG0w8Pkm5uZ1llf1CA9VTtjiMfJ3XgjKf8M3/uHx05y7h3i3R+4BXNVJZonnpCBiURyBXPRtQR/+ctfpra2ll//+tfYbDYOHz687pjOzk5+97vfvegFSi4/9Ho9bW1tNDY2srCwgKIoOByOc/rlNpvNmM3m817D8vKyaFMeHx8XXUDqXJ3JyUkCgQA7duzAYrGg1WrxeDxCZ1JcXCwyJmoLtEajIRqNilk9VVVV4nrDwQw/+nbbmhWsWsTHgM8+/4Xl+/fRf1+S7bVrgrLnDfq0cNK0aSPs3bv6+Mlv7mxaj6NRlvx+JrI5xiJJurvdXFczwjX+GewBH/v+/O083HEEeN65t28fFt8USY0GcywmgxKJRHJBOK+g5NixY7z73e9eJzZcS1VVVYFhleTKIJ/PE4vFUBQFm81W0IJ7MmazuUDI+lKwvLzM0NBQwVA+dS3ZbBaDwUA8HheZl97eXmGglslkREePVqulq6uL/v5++vv7GRwcRKvVks1msVqtbN++vSBo0ttPX1aCVa8XrfX8A62zJhol89rXop2Z5bl/fJxnxlb1Lbf/nZdvX/8YWx75N7SBPD2B9c69vje+m/+vokoq5CUSyQXhvP62nOz3sBHz8/MFs0QklzdKJEJgcJDxbJZQzkh3t5sdO4ZpLrbTbDGLzpKXk3g8zrFjxzCZTLS3tzM7O0s4HMZqtRKPx3E4HCSTSXbt2kVPTw8Gg4Hl5WWWlpYwmUwsLCyIcgyszuTp6upieXmZxcVF8vk8TqcTt9u9Tg9TUeQ6K68Xp+nCb/e5SIT0zBz2gJ9b7riF7zw/y6j/8RwHfrV3zZEbZHO+dx/9n0rRWf0SBE8SieSK47x8SlpbW09bmslms/z2t7+ls7PzvBcmuYSIRknecAOut72dwZiFx4+38Jl7m/mP7hZ+P75C+pXXo7z+9av6iJeRiYkJ9Ho9O3bsKOiO2bZtGw0NDcRiMXK5HKOjo9TU1LC8vIxWqyUYDIogZa1viordbqempoa6ujo8Hs+GAt2WUieV0TCdd3/llF4v5UE/NfbTB/ubQUBn5D03P8nHHV/gId8t9Dy5mhHp/9WZJxivOvdecZMpJBLJS8R5BSXvete7OHr0KA888MC653K5HB/96EcZGxvjtttue9ELlFz8LM/MkJsPYg/4edv7387gT1en/g7+NMu+O/dh8/tIBmbgZWxRzWazBINBqqqqRAZERVEUqqqq0Ol0eL1eYrEYIyMjwGpW0Ofzkc1m6erqOmOG8FToAgFuu+sWngqtZiK6ro3w0ccX6LomAsBToav40zveuipSvcAMzKX50bfb+HLsL/ksX2GZCsBOjLWltBhrDdkszPGlR/fjLs/jMJ25FCWRSCTnw3nlij/4wQ/y05/+lM9+9rN873vfE7Xzd7zjHRw6dIiJiQluvPFG3ve+923qYiUXJ9OKlvtv/uVqZ8m6KcK3rGoR3nTry6pFyGQyQueyFr1ez9zcHM3NzZjNZnQ6Hddccw0zMzOMjo4C0NDQQE1NTYFD7DnjcGAsL+Pm5CEi75mkfp9NeL1c+6Mpbv7OqtcLz5u6XUgMtrOxvLcXfJfARsddH2D2Xz9NzY7tF2ZhEonkiue8fUrS6TQPPPAA3/zmN1lcXBSPO51OPvCBD/DAAw+8qDbNC4lsCd5c/vOZId54Xetpj7E4cxzsy9Je9fL8TmSzWZ5++mkaGxupqakhm83yzDPP4HA4WFpaoqWlheHhYerq6qirq2NsbIypqSmcTie7du3anEWcqr33PNp4XwwDc1EeHY1sqG+xssz/5J/4O/5ynXPvx/kin6v/Fsbf/fbsOnwkEsllyUXXEgyrc0i+8IUv8PnPf57BwUEWFhbE6PczGVhJLi8MzjP/Gt37SASN5dTdWi+GeDxOIBBgZWUFnU5HSUkJpaWlBb+Her2ekpIS/H4/FRUV6PV6Kioq8Pv9uFwuYXW/srLCoUOHWF5eRqfTndK2/rw4ZXsvL+km3+J1UnlkhKq7v0KCHxU8F8dGiybAHXd0U/f+qhecex+d5ObvvnTZHIlEcmVyXpmSxsZGbr75Zr7xjW9ciDVdcGSmZHM5EQjz44nl03eWbNnCn2xxrt+MXyRTU1OMjY1hMBhwuVxkMhmi0SgWi4Wurq6CMQcrKyscOXIEi8VCfX09LpeL3t5eIpEIsGp3ryiKMFDbsWPH5dlB5vORfuX1fHriDr7EJ06ZEZn/+X+x5K16WbI5Eonk4uWiy5SEQiG5mUsE28o9VHRPUL3BJ29VizD3/b+iZsfGc2nOl2AwyNjYGLW1tdTX1wvNx8rKCj09PfT09LB3717RDWOz2dixYweDg4OcOHFCnEer1Qo9idFopLy8nOLi4henIbmYWatvuX2S+nes0bf825SYZVRdUQyuNUGZLNlIJJILzHkFJV1dXQwNDW32WiSXKLpAgNvv2senQ3cAp5gi/OdvQbvJWoTp6WncbjcNDQ0Fbbg2m422tjaOHDnCwsJCwZA+h8PBnj17iMVixONxdDodHo/nyio5ulzwxBO8Ohbj+pP1LX9djPbuv5UZEYlE8rJwXkHJJz7xCd7+9rfz61//mhtuuGGz1yS51CjoLJmifp/1gneWZLNZlpaW2Lp164a+IE6nE4vFQjgc3nBysMPhwHElayMuEn2LRCKRrOW8gpLFxUVuvPFGbrzxRt7ylrewd+9eysrKNtwcpFfJFcDpPnl/oRjtXZv/yTufzwOctsSiakQkEolEcmlwXkJXrVaLRqNZ9wd/bVCiKAoajaZgcvDFghS6XvooisJzzz2Hy+Vi27Zt655PJpM8++yztLS0vOTzdSQSieRy5qITun7nO9/Z1EVIJOeKOoV3bGwMr9dbUKLJ5XIMDQ2h1+s3tIWXSCQSycXJeQUlt99++2avQyI5Z6qqqohEIvT09FBUVERRURHpdJq5uTkymQwdHR1XloBVIpFILnHkBHLJJYtWq6W9vZ25uTkCgQBjY2NotVpKS0uprq5eZykvkUgkkoub8wpKpqamzvrY2tra87mERHJWaLVaKioqqKioeLmXIpFIJJIXyXkFJfX19Rt22pyMRqMhm82ezyUkEolEIpFcYZxXUHLbbbdtGJREo1G6u7sZHx/nVa96FfX19S92fRKJRCKRSK4Qzisoefjhh0/5nKIofPWrX+VLX/oS3/72t893XRKJRCKRSK4wNn24h0aj4aMf/Sjt7e187GMf2+zTSyQSiUQiuUy5YBPH9uzZw3//939fqNNLJBKJRCK5zLhgQcno6OgFE7n6/X5uvfVWiouLsVgsdHZ2cujQoQtyLYlEIpFIJC8Nm+pTks/n8fv9PPzwwzz++OO89rWv3czTA6tzd6677jpuuOEGfv7zn1NaWsrw8DAej2fTryWRSCQSieSl47yCEnX2zalQFAWPx8NXv/rV817YqfjiF79ITU1NgdV9Q0PDpl9HIpFIJBLJS8t5BSXXX3/9hkGJVqvF4/Gwd+9e3vve9+L1el/0Ak/mJz/5Ca9//evZt28fv/nNb6iqquKuu+7i/e9//ylfk0qlSKVS4vulpaVNX5dEIpFIJJIXx3lNCX45MZvNAHzkIx9h3759HDx4kL/4i7/gm9/85iln8nzmM5/hgQceWPe4nBIskUgkEsm5cSGnBJ9XUDI1NYXb7T7tYmKxGIuLi5tuM280GtmzZw/PPPOMeOzee+/l4MGD7N+/f8PXbJQpqampkUGJRCKRSCTnyIUMSs6r+6ahoYGHHnrotMf83d/93QXRelRUVNDW1lbw2LZt2047j8dkMuF0Ogv+SSQSiUQiubg4r6DkbJIrF6oqdN111zE4OFjw2NDQEHV1dRfkehKJRCKRSF4aLphPic/nw+FwbPp5P/zhD/Pss8/y13/914yMjPD973+ff/iHf+Duu+/e9GtJJBKJRCJ56Tjr7pvPfvazBd8/9dRTGx6Xy+WYnp7mkUce4ZprrnlRi9uIvXv38thjj3Hffffx2c9+VpSS3vWud236tSQSiUQikbx0nLXQVat9Iami0WjOWJ6prKzkscceY+/evS9uhReACynSkUgkEonkcuZC7qFnnSn59a9/DaxqRV7zmtfwnve8Z8MWXJ1OR1FREVu3bi0IZCQSiUQikUhOx1kHJa961avE13/1V3/FDTfcwPXXX39BFiWRSCQSieTK45IzT9sMZPlGIpFIJJLz46Io35yK6elpAoFAgTnZWmQ2RSKRSCQSydlw3kHJT3/6Uz72sY8xPDx82uNyudz5XkIikUgkEskVxHkpUZ966ine+ta3sry8zD333IOiKFx//fX8+Z//OW1tbSiKwhvf+Ebuv//+zV6vRCKRSCSSy5TzCkr+5m/+BrvdzuHDh/k//+f/AHDDDTfw93//9/T09PCFL3yBX/3qV/zRH/3Rpi5WIpFIJBLJ5ct5BSUHDx7kLW95C2VlZeKxfD4vvr7vvvvYuXOnzJRIJBKJRCI5a84rKInH41RVVYnvTSYTS0tLBcdcc801PP300y9udRKJRCKRSK4YzisoKS8vJxgMiu+rqqro7e0tOCYcDkuRq0QikUgkkrPmvIKS7du3c+LECfH9DTfcwK9//Wt+8IMfsLKywi9+8QseffRRurq6Nm2hEolEIpFILm/OKyh585vfzLFjx5icnATgU5/6FHa7nVtvvRWn08kb3vAGstksn//85zd1sRKJRCKRSC5fNs3RdXR0lK997WuMjY1RV1fHnXfeyY4dOzbj1JuOdHSVSCQSieT8uJB7qLSZl0GJRCKRSCRnzYXcQzdljO/CwgLT09ObcSqJRCKRSCRXKOcdlESjUf7iL/6CsrIySktLaWhoEM8999xzvOENb+Dw4cObskiJRCKRSCSXP+cVlCwsLHD11Vfz9a9/nZqaGrZt28baKlBXVxdPP/003/ve9zZtoRKJRCKRSC5vziso+cxnPsPQ0BCPPPIIhw4dYt++fQXPWywWXvWqV/Hf//3fm7JIiUQikVxgolGU6Wki0SiHxgJ8/XsLDAWXySsK+HwQjb7cK5RcAZxXUPKTn/yEN73pTbzjHe845TH19fX4fL7zXphEIpFIXiKiUXI33kj82ut49PdDfOM/bdx7axEP/jDHPz9xlPQrr4ebbpKBieSCc15ByczMDG1tbac9xmQysbKycl6LkkgkEslLRyoUIukPYPNPs+/OdzD40ywAgz/N8vb3vw3jxDjp2TmIxV7mlUoud/Tn86Li4uIzdtsMDAxQUVFxXouSSCQSyUvHZF7DX970JA2PPobFt0iPLwOscOLJNA+xj4TDTeCNt/NwRdX5bRoSyVlyXr9f119/PY8//jg+n4/q6up1z/f19fHEE0/w3ve+90UvUCKRSCQXlp7pZX707e1rHvkKADHgs89/YfmX+7jvUxnaK40vwwpXyefzhEIhgsEguVwOq9VKZWUlVqv1ZVuTZHM5r/LNX/7lX5LL5bjuuuv43ve+RygUAqC/v59vf/vbvOY1r8FkMvGxj31sUxcrkUgkkguAOX/GQ+59JILG/PJ5baZSKQ4fPkxfXx/JZBKNRsPc3BwHDhxgYmLiZVuXZHM5r0xJZ2cnP/zhD3n3u9/NbbfdBoCiKHR0dKAoCg6Hg0cffZTm5uZNXaxEIpFINh+7QcsDT09g9s3wmT9uIsELmQcLKzzw6Bi58jw2g+ZlWZ+iKJw4cYJMJsOuXbuEi2g+n2dycpKJiQksFgtlZWUvy/okm8d5lwff/OY3Mz4+zne/+12ee+45FhYWcDqdXH311bz3ve+lpKRkM9cpkUgkkgvE1jIPkz1z1NzzVRL8W8FzCWx03PUBZr93PzU7il+W9UWjUWKxGF1dXQW25lqtloaGBmKxGNPT03i9XjSalydwkmwOZx2ULC0tYTabMRpfqCcWFRXx4Q9/+IIsTCKRSCQvDVX5HO+64218Nng3AF3XRrjxk3mefFDL8WfdPBW6is/d8Va0v/stbKAjvNCEw2GMRiMej2fD58vLy+nr6yOdTmMymSAaJR+NMmsw0jezyHMHzFxzdZK2iiLK0im0Lhe4XC/xu5CcDWetKfF4PHzxi18seOy5557j7/7u7zZ9URKJRCJ56dB7PFiqK3l96QHe99Ex3vn/y1Jck+ed38jy/o9PcHP5IYzlZeBwvCzrUxQFnU53yiyITqcTxxGNorz+9SRe8Qf8vyPTfO+ZSv73Bxr416cr+enhKZLX/QHK618vPVcuUs46U6IoCicPFH7iiSf47Gc/y7333rvpC5NIJBLJS4TLhfYXv+A1sRjXeb2MhJaJ56HEYaXub4rRfvBvVwOSlym74HA48Pl8xOPxDTtt1EyK0WiEUIjE854r7/ifb+PhrmMAHPgufHVmH1b/NIlsDovfL7MlFyGy5VwikUgkqxu0y4UJaK8sKnzuZSjZrKWkpASDwcDQ0BCdnZ0iMwIQiUSYnZ2lpqYGrVbLSlEJ77vhJzR/7xG0szl6Zlc9V/oO6bmH+6i2zuNdSfKh974P/ZNPyMDkIkMGJRKJRCK5qNHpdLS1tdHT08P+/fsxGo0ic59MJnG5XNTW1gLQPRnjh/+yc82rvyK++gFAHIoI8W7/f1AWi8mg5CLjvHxKJBKJRCJ5KbFarZhMJrLZLPF4nEQiQTKZFDYUWu3qdnY2Xir7bN/jQ29+gmxF1YVetuQcueSDkr/5m79Bo9HwoQ996OVeikQikUguAIqi0NvbSy6XY9euXbz61a/m1a9+Na985StpaGhgenqa2dlZAEqcVj715ORpz/etlb/g8e9VMTiXeSmWLzkHzql886//+q88++yz4vuRkREA3vCGN2x4vEaj4Wc/+9mLWN7pOXjwIN/61rfo6uq6YNeQSCQSycvL0tISS0tLdHZ2rvMpqaurEz4l5eXlNBXZqEkPnvGcqw61tgu5bMl5cE5BycjIiAhE1vLEE09sePyFNLFZXl7mXe96F//4j//I5z//+Qt2HYlEIpGcmnQ6zczMDPF4HJ1OR0lJCR6PZ1P//ofDYQwGA0VFReuei8fjaLVa4vE4U1NTVCkKt97xVgb5LA/xEbRkya/Z6vSkGfbu4GcaHzbD1k1bo2RzOOugZHx8/EKu45y5++67eeMb38jrXve6MwYlqVSKVColvl9aWrrQy5NIJJLLnsnJScbHx9FoNDidTtLpNIFAAIfDQWdnZ4HZ5othI5+SfD7P4OAgc3NzQk8yPj6OLx5ne5Gbm+KHMab/gS+tFBp8ZrExudCALRamzPjyzfKRbMxZByV1dXUXch3nxCOPPMKRI0c4ePDgWR3/4IMP8sADD1zgVUkkEsnljaIozM/PMzk5STweL3jcYDDQ0tJCOp2mr6+PEydOsHPnzrPKmEQiEaamplhZWUGn01FWVkZlZSUGgwFY9SmZnp5meXkZu90OwODgIMFgkJaWFpaXlwkGg+zatYvJyUl6P/IRXvnJ+/jvxWuB9Q61/5m9mU9/6N3kun4Fra2bd4OiUTILC/i1OoaCSxw8ZOMV16RpryqmNJlA43TKbp8zcMm1BE9PT/MXf/EX/PKXv8RsNp/Va+677z4+8pGPiO+Xlpaoqam5UEuUSCSSi4NolKjPx1ReYTya5OhRF9ddl6HDbkAzNEjA4cCnd9B93MNrX6NlR10ZllBoQ6M0RVHo7+9nfn4eWC3Pa7VaNBoNuVyOpaUljh49ys6dO9m2bRvHjx8nGo3idrtPuTxFURgcHBQiVZXx8XEmJyfZuXMnDoeDkpISjEYjw8PDdHZ2kslkmJubo7m5GavVysjICNXV1VgsFlpbWzns95MpLuJ12f2E3ztG05840Wjgnd/Ic/WjE9z4z8+Rc7tI63RsmqokGiV3442k/QGe/NZj7B9v5uEPunjP16Nc2zDErXe+HUt1FZonpDfK6dAoJ9u0XuT8x3/8B29961sLzHNyuZz4D5JKpQqe24ilpSVcLhfRaLRANCWRSCQvCdEoyWAQv1bHeCTJocM2bni1hu21XszB4Oa4p0ajpF/7WtIzs/zgHx/nmbEtPPxBF+//0gyf+/aNlI70E9zSxqf/7Bf84ycqnt88h7n97n2YKsrhpM3T7/czPDyMXq/H4XCwuLhIa2srXq+Xvr4+FhcXMZlMmM1murq6ePbZZyktLaWxsZFEIoFGo8FisRRkTqamphgbG8NgMNDc3IzL5WJhYYHZ2Vmi0SharZY/+IM/QKvVEo1GOX78ODqdDqvVSjQapbi4mFAohNvtLjBVm5mZYeTwYfSJBLvf8hYml1LEc+A2G6m0ajnx85+T0OtxVFfT2dn54u7z8yjT08SvfQU2v4/F6nre2HaI/U8Wc+2NYX7WtxuPb5JETR2WZ37/spvRvVgu5B56yWVKXvva19LT01Pw2Hvf+162bt3KJz7xiTMGJBKJRPKyEo2See1ryc7M8qt/+I+TPlH3cPtd+zBVrg8KzpXE/Dy5mVnsAT+33HEL32k7BMDAz3KUjAygzeUoGeln4Gc5AAZ/muVrvbdg8k+S1mgwrjEWUxQFv9+P0+kUmebFxUUMBgM6nY6Wlhb279+Pw+Fgfn6eVCqFXq8nEonwzDPPkM1mATCbzVRXV1NVVYVGo2FqagqtVstVV13F4uIiR44cKdD/5fN5RkZGaGlpweVysXv3bnw+H7OzsyiKQiKRYMuWLVRWVgpdCax6muTsdnJ2OxPj41RVVWEymVYDm+4JVlwuysvLRdZnMwiardx905M0PPoYFt8iPb5VJ9kTT6Z5iH0kHG58b7qVh8sq2BylzeXJJReUOBwOOjo6Ch6z2WwUFxeve1wikUguNuJzc+SfDxb23bmPh58PFgZ/muVrfbdg8q0PCs6HaUXLX978y3Wb5NHf6LiJb5PCgi2ncPS3ek7ePANvvJ2HK6rEBpHP54nH43i9XpaXl/F4PBiNRhYWFigpKcFkMuF0OsnlVgOcSCTCysoKGo2GqqoqSkpKyOfzzM3NMTIyQiKRoKamhmw2i9frZWFhgf7+fkpKSmhraxOZkBMnThAIBCgpKaGoqAij0YjX60Wv1zM1NUVHRwcWi2Xde48+P2zParUSDAYJBALiObvdzo4dOwiHw5vaIXRiOs6Pvt225pFVJ9kY8Nnnv7B87z5OfHyFXfUvz2DDS4FLLiiRSCSSS5nJHNy/QbCwNijwv/E2vrsmKFhLMpkkmUyi1+ux2Wyn3FgH57MbbpLLwH9tcHzB5vkv93HfpzK0V65+plevodFoyOfzZDIZKioqhDeI0+kkn8+Tz+dX3+PkqnlZR0cHxcXF4hpFRUU4nU6Gh4dxPD9x2GQyMTo6SmlpKW1tbeJaJSUlaDQaNBoNIyMjuN1u5ubmROADcPz4cfbs2VOQIU8mk/h8Pux2O/F4nKuvvprl5WVyuRwWi0UIZfv7+/F4PBveu/NBaz2zEmLVG0Vuu6fjsrg7Tz311Mu9BIlEIjkr+mdT/Ojbaw0fN/hE/a/38am/zNBuS5CPRpk3mRkdC/DMUzm2XJdHA/T/RmHvdRk62pspz6TX6VAM9vM37D7ZWEyr1eJ2u4UniN/vp7a2lsXFRY4dO0ZRURHLy8uYTCY0Gg2JRAKHwyECEkVRWFpaYnZ2llQqhVarFeLWYDBIOp2mrq6uIMCKxWLCQn5paYlEIkFtbS2lpaUATExMEAqFeOaZZ2hubsZsNhONRvH5fGi1WrZu3crRo0fp7++nvb1ddPLkcjmRrdm2bdt536OTKXHaeODpCcy+GT7zx00keGGasYUVHnh0jFx5Ho/VtGnXvBy55G3mJRKJ5FJCZztzyeDeRyLo0hGyf/iHJF5xHT//TS9jf/odPv6p3fzXb4p58qliPnX/Vcy+74c88dtektf9Adx0EzxftoAXNskv/nA/FuZZzZGs/jMzxpe+/MN1j1uY40uP7sddnsdmKFxnTU0NsVgMm83G5OQk09PTtLe3U1lZSSgUAlY9odSuSEVRGB8fJ5FI0N/fz9GjR1lcXBTZj0gkgk6nI5lMAquGmKqeJJPJcOLECQCRzairq6OhoQG73Y7dbqejo4OGhgZyuRwDAwMcO3aMyclJPB6PWOuWLVuIxWLs37+f3t5e+vv72b9/PzMzM7S2tm6qSHNbuYeKSIjOu79CglLAJv4l8NJx15fxzk9T65CKktNxWWRKJBKJ5FLBbTGe1SdqQzRM0j+DPeDjrX/xbj4YfT6j8uBzKGiARp6cu5av33sb5lkfaa22QIfSWV3Ckf7j1Nz9FRL8qGANSRqwfPyrJHhHweMJbHTc/QHmv/8ZanYUFzxXXFxMU1MTo6OjaLVaJiYmmJiYEM+rWY5EIgGsBig+n0+UcrZu3UpZWRkajYYjR46Qy+VYWVkRrx8YGABWyznpdBpFUfB6vSLg2cjNta6ujnA4jFarZcuWLUxNTREMBgsErA6HA5fLJTIv5eXlVFZWYrVa153vxaALBLjtrlu4P3QnsN4b5anQVXzuzrej/d1vL/numwuJDEokEonkJaSzupTBZ0aouWd9sJDARsddH2Du+/eTqDDx3jc8ScMPH8M0G+GHvAKY55HEKwANMM+jiRupTxwl6XAReEOhONU0P8/td+9bt0n+6oEMR4+U8S/KrQDs2j3Ha+43vLB5Bq/ic+//ow03z5qaGoqKipiZmWFpaYlsNotOp2N5eRlFUdBoNNjtdpaXl8lkMrS2tjI0NCSe02g0xGIxlpaWROfOWo0IILIlVVVVNDU18fvf/160IW+Ew+FgYWGBsbExIpEIjY2NlJeXo9PpCIfDjI2NMT8/z+7duzGZXiidKIpCNBolFAqRz+ex2+1CRHteOByYKsq5OXWIxdsnaHiHXXijXPPoJDd/9xDG8rLVMhusZrViMVJeL/2zEX7/tJ7X3qCjtcyJ1u/fnLbwS5BLzqdkM5A+JRKJ5GXD5yPxiuv4zPRdfIlPrPtE/XG+yOfqv8UTf/33/NGf3nTWp7U4cxzszwpxqupT8puJav7tfQ/R8Merm6RxaQnLn/4DykwMyu0kf3AHaacTRYHJH8V553f+F6+u951VS3IikeDgwYM4HA6i0Sjbtm2jrKyMWCzGkSNHULcXl8tFJpOhsbGRoaEhYHVmzs6dOzl69CgVFRXMzMzgcDiw2+3MzMzQ2NhIJBJhYWEBp9PJrl27NlzD8ePHSSaTxONxOjo6KCkpAVY7hgKBAH6/X2RviouLqampwWq10tvbSzQaxWQyodfrhZvs1q1bhW7lnHk+0MhXVTG9nGElo2AzaKixGwoDjWgU5aabSPoD/Mvf/3tBW/grGke47a5bNvSKuViQPiUSiURyueBwYKmq5Kb0QRZuG6fxnY51n6gN5WXki9a3up6OdVNvXS4GH3qIqnicb/5h3ZpN0klN7yfRDg/Tn8szrV+huq5qdfP8QjHau/72rD+l+/1+tFotLpeL5eVlsZk7HA62b9/OsWPHAET3y4kTJ3C5XKTTabxer8h+OJ1OnE4no6OjxGIxAMbGxsSAv3A4TDweX1dyWVlZYWFhAYfDgdVqFcLafD5Pb28v4XCY0tJSTCYTsViMZDLJsWPHsFgsZLNZMXV4fn6e2dlZ4vE4vb29NDY2UlNTc+4twy4XuFxogbqTtSNrs06xGElfAItvin133sLDbYcB1Svm7Zj8k6QA04tsC78UkUGJRCKRvJS4XPDEE9wQi/Gqkz9RP1iM9p7VoMA8OHGS9mSjpLatQIdysjg1ZTbj9HrRajQnbZJG2LsX8/g49pkZ2orWdIScg94hHA6LQECv1xcYmLndbkpKSgiFQthsNpaWlti2bRter5enn34am80m9CJ2u52pqSmy2Sw2m41sNksul0Or1RIKhTAajXR3d7NlyxZxvVAoxMjICFarFb1eLzp/AAKBAOFwmK6uLoqKivD7/USjUfbs2UN3dzeRSIT29nZsNhtHjhwhkUhQXFyMw+FgdnaWsbExYrEY27ZtK3hPm0XU6eZ/vv4JGh79MRZfZOO28De8+5Rt4ZczV9r7lUgkkpefs/hEva28iKmeOWru+SoJ/u2Up1orTq3sdJNIJNDr9RgMBsxm82mnosdisbOeIaaiDuWbnp4mkUiQSCQwGAxkMpmCgXmAmI0Ti8XQaDQUFxej0WgwmUyiRdjlcjE3N0cwGAQQ4leLxcKOHTsYGhpicXERu91Ob2+vCDwURcHtdrNt2zbGx8eJRCJCu+L3+/F6vUIcG4vFRNCivt94PM709DT5fJ6rrrpKZGEsFgujo6MEg0FWVlZwuVx4vV7cbvemma0dHA6fldHafX+ZpqPqymohlkGJRCKRnCOKopDP58WmeyGoVvLceufbeCB4NwBvNP2cqtQU/8AdALyfb+E31fGfqZt4KngVn3nvmzj8t18l+bymwuPx4PF4CIVChEIhobVQiUajLCws0HqOU3InJiaYnJwURmjJZBKn00koFKK7u5trrrmGXC5Hf38/i4uLBa999tlnqaqqQq/XEw6HMRgMFBcX4/P5gFXticlkYn5+nmQySXd3N21tbYTDYcrKymhubhZurW63WwRAFRUVzM7OMjc3h9frJZFIUFVVJXxR5ufnqa2tBVZ/djqdjkgkwtLSEh0dHSIgURSFSCQCIPxWFEVhZmYGt9tNR0fH+Qth16BLR854zL2PRMgbTYAMSiQSiURyMtEoifl5JnN5hkIxjh51sXt3jK1lbuq0GgxFRZta/9e53ViqKnl9+gCRP+7j07++n565OlLvuQlFgbd+95d0lk3y4Osa+MN/fZaMy0FFSwvOmhqSySR+v5/x8XGcTie9vb1UV1fj9XrRaDQEg0Gmp6dxuVxCsKiWQNRMhc1mW7cBx2IxJicnaWhooK6ujmg0ytGjR7Hb7ZjNZnw+H/v37xdBGyAG8anlmsnJSQwGA3q9nkwmIwKS1Vv8gs+KoijE43GOHTuG1WplaWmJqqqqDbtwnE4nXq+XwcFBEVSMjIwUHLOwsEBZWdnqXJxcjnQ6jU6nK3CcVcs+Op2O9vZ2jh8/zrZt28hkMvT19TEwMPDix5lEo+y+8z1MV9byk//9dT5813WkeSFbZWWZI82v5z9tEZymqhd3rUsQGZRIJBLJmYhGyf3hH5L3z/Dbf3h+LP29LjFZ9113vBVddRXaX/xi8wITlwvNL37Ba2Ixrq+oYGLyMWqjy/xVYzkajYb0bV8k73FyVzRI4lW3Y7z2WurKysTLy8rKOHHiBLFYjKqqKgKBANPT08BqWaW4uJhMJsOBAwc2vLxOp6OiooKGhgZh4x4IBDCZTCLr4HK5qK2tLfArUYfvqdepqamhpqYGvV5PKpXiwIEDVFRUEA6HC449Fdlslmw2Sz6fF+WZk9FoNGzduhVFUYRT7No1qLN7jh07RmNjI4A4n4qiKMJTRV2veu7i4mKam5sZGBjYUHB7JlKpFAsLC+TzeWyLixhCIaoDPtrv+Rpp3lxwbBwbc6MuyicHqX1lwzld53JABiUSiURyBpSlJZKBGWwB3wZD9PZh8/uIazRYN7tb4nntiR7Y0niSALWziUwmw/hoH427d2NeE5DA6mbc1NTEwYMHcblcNDQ0FPiJHD9+HJPJREtLC/Pz80SjUYxGI6lUisbGRrLZLD6fj+XlZbq6utBqtaysrODxeERgkMvlWFhYOOXy8/m8yIrAqjGa1+tldnaWdDqN0Wgkk8lgNpuFYZpaFlN1KmrGJZlMcuLECXGM3W6noqICm2214yibzRIOh4HVgGxubo6ioiIcDgfhcJjl5WWy2SzDw8MYjUbRJjw6Oorb7WZ+fp50Oo3VaqWmpobx8XH0er0IQEpLSxkaGiIcDp91UJLL5RgeHi4IlHJ5+Ofrf0TjIz/mv/OvAZ7PTLFMFVMM0cbn8n/JT/73nWhvuPKM1mRQIpFIJGcgbLXzgVOOpb+FhMPN9Jtu5dvFpWyuT+jpUTUPbrd7w+dtNhsGg4F4PE5paSmu5wOm7u5uTCYTu3btIhKJEIlExPC83t5epqenufbaa/F4PHR3dzM/P095eTlarZZ0Oi3OPz09Lco9bW1tRKNRAoEApaWlGAwG/H4/IyMjFBUViY3cbDaTyWSwWCwkEgm0Wi11dXUMDAyg0WgoLS3FbrczPj4urqMGKOFwGLfbjcFgYG5uDp/PR1NTEzU1NczOzpLP57FarbS2toogZWFhoSC7ks1mufrqq1lZWaGvrw+fz4fP5xOBU0tLC9FoFL/fT01NjcgSabVakXVZSzqdFgGNOsXYaDSiKAp9fX0sLi6yZcsWYej2098P8P1HVJHrl8R5VoCh579+TrPESkk9llMYxl3OyKBEIpFIzkCvP3nmbonv38eHPxzhqpaXTpiobphrA4W1rC19BAIBFEXBZDKxuLjI1q1b0ev1wrRMFcI2NDRw8OBB4fHh8XiYmZmhvLyc0tJShoeHSSQSmM1mZmZm0Ov12O12ioqKGBoawmKxsLy8zM6dO5mZmQFWyz5btmwBVnUpWq1WBAH5fF64uCqKwsLCgshiqKwNKnK5HLlcTmhLRkdHsVqtLC4uisnJ09PThMNhampq0Gq1xONx4vG4CKDC4TDV1dXs3buXo0ePkk6ncblcLCwsMDAwQDKZpKioiPr6enHdWCxGNpsV4lpFUZiYmGBqagpYzQIlk0lGRkZwuVyYzWbC4TBtbW14vV5xHqPzzNvux7/rI/jKH1ByhXmUgAxKJBKJ5Izoz3KInvYsjttMrFYrVqsVv99PUVHROr2FGoioWgmNRiN0FEbjaityMpkUGRRYza6sHZTncDiYm5sDVssiU1NT9PT00NraKib+2u12enp6UBSFuro6+vv7CYfDOJ1OEokEy8vLwKoTaCgUoqioSAhS7Xa7WB9QMO8GEEJclXQ6TVFREfF4nGg0ik6nY3JyEp1OJyzv1aCjqalJvG5ycpKJiQm0Wi2Tk5NUVlZisVjYu3cvMzMzzM/Po9VqRfmqurpaeJRks1lGRkYwm82izXh6eprJyUnq6uqorq4mkUhw4sQJ0uk00WhUtGL7fD7cbre430U285lnH20pxVp8ZbqNyynBEolEcga8bvspJ+6unaxb4ngpizerQUZtbS0LCwsMDw+LjEkul8Pv9zM2NoZGo6G1tZVXvvKVXH/99SJj0dfXRzqdxmAwiAAEVjf9XC4nMhnJZBKDwQCsGqRt374dRVE4evQosJrpmJ6eJh6P09nZidfrpaysjIGBAZaXl4WgdHx8nO7ubpxOJ01NTeTzeYxGIxqNpqCjJhwOk8lkxPszmUwiIwRQWVlJRUUFO3bsYNeuXSiKwtLSEk6nk0wmQyKRIJ/PU1X1QueKoijMzc2JgXyZTEYERQaDgdraWvbs2cM111yD1WplYmJCaEEmJiY4ePAgKysrtLW1odFoyOVyTE1NUVVVRUNDA9lslu7ubsxmM3v27KGiogJFUbDb7SSTSY4fPy7KPl01XsoXg6edJlwW9FFjN2zeL8olhAxKJBKJ5Aw0FdmojIYvqrH0i4uLdHd3i+m6gUCAZ555hueee479+/czPDwsjh0bG2N0dJRsNktZWRlms1kIWb1eLwsLCyKb4fP50Gq1lJSUkEgkCAaDBeUHq9XK3r17aW9vF8EKrGYTJicnWVhYEBOBs9ksmUyGaDSKz+ejrKyMrq4ubDYbTU1NpNNpURbxeDzAalCkZnw0Gg3z8/MFQ/vGx8c5cuQIBw8eFHb1gNDVqMFUIBBgZWWFRCJBT08P8Xgck8lE9fPC0ZMHAcJqgLJz505qamoIh8MMDAwwNTVFUVERu3fvFnNeFhcXyWazIvCZnp5Gq9XS1dWF3W4XjyeTSdrb21leXhbZH3MwyG137eOp0F5gdVDiRx9foOuaCABPha7iXXe8bXVWzhWILN9IJBLJGdD6/dx21y18OrRqXPZyj6WfmZlhcHAQh8NBS0sLer2eUCgkNvC1ZRyj0Ug2myUQCBAIBArOMz09TVdXFwaDgUOHDonHHQ4Hfr9ftBAHg0Hy+TwVFRWYTCZR5lAzGoDooOnp6aG0tJTFxUW0Wi06nY5t27Zht9uJRCIMDg6SzWaxWCw0NTWJ4EHVewCixHSyqFS9TlFRkSiXqBqPZDJJW1sbvb294r2p64fVYGrHjh2iFGSxbDxbSK/X09DQQENDA/l8Xkw3XovayqxOHQ4Gg5SXlxd0GanHLS8v43A4XgjuHA6M5V5et/Is4T8bo+mdztNPE77CkEGJRCKRnAmHA2N5GTcnDxG5fZL6d9he2Ej+bZKbH37pNpJ0Os3Q0BDl5eW0traKDdPr9VJZWSmG4Ol0OoqKimhra2NkZAT/85+8NRoNzc3NTExMkE6n6e7uXneNWCwmrOFLSkrQaDRMTU0xPT1NZ2cner2ekZERqqur8Xg89Pb2FohTVct4k8kkgp7jx4+LDdpkMhEKhUQL7rmg0+kIBALC0VXN8CiKQklJCXv27OHo0aOiBGW1Wqmurqa0tJRsNsvExAROp7PADv9UnGrujRrQhEIhEomE6AwymUyUlZWJwKekpITh4WHMZrNwiA3HYvg++1lcKyt8tC1DzJDE6HDjthgLZh9daYP4VDTKWveYK4QLOXZZIpFcppztWPoLzOTkJJOTk1x77bXkcjkCgQALCwtCw6CKUr1eL7FYjObmZo4fP05zczPpdFo4ssZisQJBqUajwe12o9frCQaD6HQ6rFYru3fvBiCTyXDixAlWVlbE5N62tjYxvG4tGo0Gm83Grl270Gg0HDt2jEQiQUdHh/ibm8/nOXDgQIGe5WzQaDSUl5eLzh4Vh8MhXGuXlpaExqO6uhqr1crKygo+n490Os2OHTs2dIY9WxRF4dlnnyWVSqHRaES7cDabRavVYjQa0ev17Nq1S9jyn4xWq8VsNpNMJlEUhdraWurr6y/Y2ILN5ELuoTJTIpFIJGfD2Y6lv8AsLS1hNBoZHh4mGAyi1WopLS1Fq9UyPz8vjisvL2d+fp6xsTFsNhuVlZVkMhkmJyeZmZkRwYBWq8Vms1FcXEwgEBAeIg0NDfT19RGLxXA4HBgMBtra2ti/f78QjZ6cZVFbcqPRKPF4XAzji0ajBQEJrGZT1DXo9Xra2tro7+8nk8mg1+sL3F5LS0tZWFhAp9ORTqfXubbq9Xp0Oh39/f2EQiHa2trYuXMnExMTDA0NieNKSkro6OgQhmvny8rKimhjVi30g8EgFRUVzM3NkUgk2L59OxqNRoh0W1tbWVxcZH5+nsbGRiorK8X7VDt59Ho9NTU1L2ptlzoyKJFIJJJLAEVRGBsbE66l6oaez+dxOBxUVVXhdrvp6+sTr1GdTdUyh5oYX5udUDML9fX1VFdX8/vf/55sNitmwsRiMVHqUAfsqUPtcrkcBoOBbDaL0WjEarWKNt1cLkc0GiUSiaDX6wtmzCiKIoKF2tpapqamMJvNYh6OwWAgn88LTYmaeVADATU7oYpVm5qaqKioIBgM0tvbi8/no6amhs7OTtLpNJlMBqPRiMFgEEP31MDMYDDg9XopKSkR5RpFUVAU5ZTlG5/Ph8lkor29nYmJCVGumpmZwWQykUqlmJ2dJRAIEAwGqampobS0lJGREWpqaoRNP7ygYUmn06Kj51TXvRKQQYlEIpFcAoyPjzM9PS0CDY1Gw549e/D5fAwPD6PX6wsyEYFAgLa2NhYWFlhZWeHw4cMF51PPk8lkxCaoCjUzmYywjx8bGyvINqif/rPZLFarla1bt9Lf308ikRBBg8rs7CxGoxGdTldQllhcXBQBxVozMofDQSKRwOv1FpQ8/Cd1oqgCVHU9mUyGTCZDaWkpXq8Xv98vHjebzZSWlpJOp5mbm2Nubo5YLIZOpxMOraFQCJvNxtatW5mZmWFubo5cLofRaKS8vJyampqCTiN1uJ/T6aSrq4t0Oi0CEbV8Njc3h8VioaWlhYqKCkKhELlcjsrKyg1/vlVVVczMzBCJRIQXypWIDEokEonkIkedpltXV0d9fT2hUIh8Pk86naa5uXl1Bs74eIFOYmFhAa1WS1VVFZOTk2zZsoXR0VGRLamurmZ+fp5wOExdXZ14naoVGBwcBFY7SNSOG9XWXi2tZDIZuru7MRqNWCwWUqkUVqtViE8XFhZoaWlhampKlIGAAlHs7Owser0es9lMQ0MD8/PzBV1CVqtVtPOuDXrU92E2mxkfH2dycpK2tjby+bxwVjUajaTTafFe1pLL5cjn85hMJvL5vAjcjEYj1dXVWCwWlpaW8Pv9BINBdu7cKQzQ1EyRitFoxGg04nA4aGpq4sSJE2QyGaGpUa8HL3TmnIx67o1ala8krtwckUQikVwihMNhYQimikh1Oh3d3d3C2CuZTBIKhWhubhYZgKeffppIJIKiKIyMjKAoivDQ6OvrExv79PQ0IyMjZLNZKioqgBfaXqurq7nmmmtwuVzrygqZTIZcLkcikRCmZWpAAqudQgsLC0IDEw6HmZycFGUgWA1c1LkwRqORoqKiglZjVZtychYGoKKigquvvpprr70Wl8tFT0+PEO9eddVVXH311Vit1nXrNhgMwgE2m81iMBhE8NDU1ERDQwPl5eW0tLSwe/du4eiqog752wjVzM3lchVkh9SOHdW07WTUx8+1G+lyQwYlEolEcpGztqsDwOPxkM/naW9vx+PxCOFmW1sblZWVmM1mTCYTuVxu3SaoimETiQQ6nQ6Hw0E+n8fn87F///6CzRdWyyMjIyPMz8+Tz+dpbm5etz5VaLoRMzMzaDQalpaW6OnpYWJioqDrR13TwMAA+/fv33DqsDrZ+OTgIhQKMT4+Luzu1zI5OYnP5yMej7Njxw6xPo1Gw1VXXcWePXvI5XIiSFMDtJO9XKxWK7W1tQSDQeGYW1VVRSwWw+fzrVvn2NgY2Wx2XZnG6XRis9kYHx8vEPHCanA3MTGBy+V60SLcSx1ZvpFIJJKLHIvFQj6fFyWQyspKpqenmZubY9u2bQSDQaGLGB8fJx6Ps337duGSCqs6jJmZGYaHh8XU3draWqqrq1leXmZqaqrg079aZlBnwhQVFREKhTCbzaIsAogpv2NjY+h0OkpLS0V3jMFgwOl0Eg6H0Wq1eDwelpaWRJCllio26qhR7eeXlpYoKioSHS9rRa5Op5OpqSnRuaKimrfNz8/jdDoLrmW32zEYDBgMBtHa7Ha7RbC21sRNxWw2ixlCVVVVFBUVUV1dLYK10tJS8vk8c3NzxONxWlpa1mU8VLv/7u5uDh8+TFVVFTabjeXlZfx+P9lslra2tnXXvtKQQYlEIpFc5Hg8HkwmE+Pj43R0dGAymYR76f79+4HVIOL48eMkk0kaGxsLAhJAlHTWCmTHx8fx+XzYbDbRkaMO7dPpdFgsFjo7O4HVLMCxY8fo7+8vcFrV6/WMjo4Cq3qItcFFJpMRWQH1NVu2bKG4uJi+vr4NsyIqiqKwZcsWenp6Co5TFAWbzcbS0pIIdtbqXGA1s1RfX8/w8DDJZLKgpLS2NGS1WllaWsJut4ugZG3JJZFI0N/fL4br+f1+/H4/xcXFtLa24na7xX2E1WxIdXU1ZWVlG74np9MpWpXVjJRGo6G0tJT6+vorvnQD0jxNmqdJJJJLgnA4LGzVVSFmOBzG5/ORy+UwmUy4XC6qqqoKpv6uZXBwkFgsxp49e4BVvcba1lg18LFarSiKQjKZ5JprrhFZk0wmw9GjR4nH4+f1Hmw2GysrK8KfQ+0AgtXgxm63E4vFCsSe6rFarRa3200kEiGfz2OxWHC5XOsyLBuxdjoywK5du3A6nRw/flyUcNRWatXLJJPJcOjQITQaDRaLhZWVFfbu3Us4HGZ0dBSz2czOnTuB1VKR6vGirrmiooL6+vpTlrXUuUAGg6Egy3MpIM3TJBKJ5AqnuLiY7du3MzExQX9/v3i8pKSExsbGs/qUrdPpyGQyQqNhtVppamoSz6uttzU1NQwODqLVajlx4gTt7e2YzWbi8bgYmHeqz7M2mw29Xi+s1uGFLM22bduIxWKiG0YNSAB27tyJzWYjHo9z4MAB8biaAVGzN2q2Z6MWZPU9ntzBopZJVI4cOSI2VbfbXXA/7XY7iqIQCARIp9PU1tYyOTlJY2MjBoOB8vJyrFYrR44cEd1LoVCIyspKvF4vGo2GYDCI3+9neXmZzs7ODX1H9Hr9pgUjiqKwsLCwznvF6/WeMii6WJGZEpkpkUgklxipVEoEB6rp2NkQjUY5evQoHR0dlJSUFDyXz+c5cuQIRqORrq4uJicnRVkCXggszhVVf6IO5uvt7d0woFFt2XO5XIGnysnXVfUwG1FSUlIgol2rfVE5XUCl2r6rwwUB0fW0ZcuWgtKOOl9neXmZtra2gknK8MIU561bt1JeXn6q2/Oiyefz9PX1EQqFsNvtOBwOkskki4uLWCwWampqMJlMuN3uTQtQZKZEIpFIJABi3s3acoHb7aa2tvaMpltOpxOPx8PAwACtra1i2F4ymWR0dJTl5WV27NgBQF1dHaWlpfj9fsLhMMlkUghe1WzAyagTddUgwm63C61KLpdjcHAQo9EoBKtqcKDX69EsLTH229+y5HIR0dro7nazfXuEIk0SUzBI1mIhZ7eLtuWTZ984nU62bt3KM888g8FgEIHb2rWpTq0bYbVa2blzJysrK8zNzTE7O4vD4aC1tXXDjhiLxSICgdLS0nXPezwePB4PMzMzFzQomZiYIBwO097eLn6e8Xicvr4+lpeXhfGdXq+nurqaurq6i3q+ziXXEvzggw+yd+9eHA4HXq+Xt7zlLRsa40gkEsnlRi6Xo7u7m+npaUpLS+no6KC1tZV8Ps/x48fXbdQno9FoaGtrw+Fw0NvbyzPPPMOBAwd49tlnWVhYoL29HYfDQTqdJp/PY7VaaW5uxmQy4XA42Lt3L0tLSxsGJLBaRlib1VhZWRE+IIBwXlXFqbBabtlSWkrHxz5G/fv+JycW9Dx+vIXP3NvM48dbGFgy0/Xhj7Djk5/E+Lx5m/o+zWazuJbT6RReKS0tLQXPmc1mrrvuOmESp3beVFdXs3v3bjo6Okin0/T39+N2u2ltbcVut2M0GjcMSBRFIRaLoSgKTqfzlJu80+k854GD54IaoFZVVVFaWirKWmoWR2137ujooLy8vEBge7FyyWVKfvOb33D33Xezd+9estksn/rUp7jxxhvp6+u74vu7JRLJBSIaZXFqislcnumVHMeOObn+eoXttV7csdhLNiF4enpaZDPWps3Ly8sZGhpiaGiI4uJi4WeyEQaDge3bt7O0tCSsz1XhrM/no7e3F3hBrOn1eolGo7S1tTE6Oio0HlarFbvdTiQSKchIuFwuMpkM8XhczI9Zq/E4uQSUy+WYHx2lMRLFHvCz7459PNy+Wr4Z/GmWr/Xuw+b3kdLrMaZSpJ83IQMKBvr5fD4RrPT29pLP50X5JplMsn//fhEIVVZW0tDQIM7jcDhoaWkpGEBYXl7O8PAwS0tL60oUwWCQlZWVgq6ltaiW8zMzMyJw8Hq9my5oXV5eFoJhlampKTQaDTt37kSr1RIIBEgkEmzZsgWTycTo6ChVVVUXbafPJReUPPHEEwXfP/zww3i9Xg4fPsz111//Mq1KIpFctkSjJF/9agzzQQ7+4+M8M7aFhz/o4j1fj3JtwxC33bUPc2UFPPHEBQ1MVPGlOnNlLRqNhsbGRmZnZ5mdnS0Y+HYqnE6nOE84HBZ28SUlJZhMJnE9NStiNBoJhUJoNBpMJpPoApqfny8oxSwvL+N0OkWHjt1uFy21sBoQJBKJAlfXoNnK527+JQ2P/hiLP0KPPwOscOLJNA+xj4TDzfTNt/I/neNspIpQPT5WVlbw+XxCh7I2WFobGKnDCddmOEpKStDr9YRCIRGUzM3N0d3dTW1tLSUlJeTzeebn5/H5fJSWluLxeBgaGhIBCqwGLP39/aJUZDabGRoaYmJigs7OzoJRAJuF+j5Ur5SysjIxRRpW5yZlMhkqKyuZnJxkbm6uICi7mLjkgpKTURXep6ulplKpApX22v8gEolEcjoWp6YwzAexB/zccsctfKftEPD8p/i+fZh9k6Q0Gkyx2AUNSrLZLOl0ep3/iIrBYMDhcGxo/nU6crkcfX19aDQaYQufz+fRarVUVlYKh1PVGVZRFNxuN4uLi2zdupW6ujomJydFYJLL5UTAofqAwKrGYnFxkUAgIMpIFouFY8eOMZuy8qNvrzUO+woAMeCzz39h+f59/NFbQpSbYhuKVfv6+nA6nQXThFXq6+tJJBKi2yccDjMzMyNcV/P5PPF4vCCro9Pp6OrqYnR0tED0q9frqampob6+HkVR8Pl8dHd3izJXb28vLpeLVCqFoijCpr6vr4/jx49z9dVXb1rGRB03EAwGsT+vt8nn88zOzmI2mykvL2d2dpbi4mL8fr8wv9uoa+li4ZIOSvL5PB/60Ie47rrr6OjoOOVxDz74IA888MBLuDKJRHK5MJFVePAN/0X9D3+MxbdIj2/9p3j/G2/juxVVF/QPqtpWenI3iYqiKKTTaTF192wZHx8nl8tRVFREU1MTNpuNVCrF9PQ0Pp9PeIOo5mKwarM+NzfHxMREgYfIWpMzvV4v5tYoilKQGbFYLBQVFaHX61e9SoJnDqTufSSC3q5Fl9cVCFbVgX2w8QdOtYSh3je1a2Rqaory8vJ1HiN+v59oNCqyI62trTQ2Nopgz+FwFHSxbN++nb6+Pnp7e0XGIhqN4nA4aGtrE+6x7e3tPPfcc8zOzlJdXX12P5wzoNfrKS8vZ3p6Go/HI372JpOJjo4Oenp6cDqdtLe3s7KywpEjR1AU5aKeQnxJtwR/4AMf4Oc//zm///3vT/tD3ihTUlNTI1uCJRLJGXn0l8f44xt3nvYYizPHwf4s7ZWn1nJsBsePHyeVSrF79+513hcLCwscP358nb386VAUhaeffppcLscrX/lKUqkUuVwOi8WCTqdjZGSEQCCwTgei1+sxGAxi2q/a9aGWC3Q6HV6vF7PZTGlpKYcOHaK2tpbS0lLxHtQyUDKZJKqz0a3zYvbN8Jk/biLBC3oHCys88OgYuS1b6EhM4lGSG7YE22w2MShPfd5qtQpxrcFgwOPxEAqF0Ov1pNNpiouLWVhYoLi4WLQSr/U5MZvNdHV1nZX+IhaLcfToUZxOJw0NDRsKYI8fP46iKGzfvv2sfj5nQy6Xo6enh0gkIszp1PKV2Wxm+/btYhjg8ePHWVhYEOZx54tsCd6Ae+65h//3//4fv/3tb88YdZpMplOOi5ZIJJLTYXCcuUnx3kciaMwXXmhfV1fH0aNH6e/vF8JF1ThrYGAAp9OJ2+0+6/OpQkmNRsPBgwdFkKHT6SgvL6eysnLd0DlYLSWpgledTrduwJ46ZwdWhZcmk4nJyUkmJiYKjlODG2dmhfKleWru/goJflRwTAIbHXd9gMC//CU2c4wMhV4jXq9XCE/NZrPo7tFoNBQXFwvBayAQYGVlBavVKozUwuGwCFQAmpubqaqqIhgMCj+V7u5u9u7de8aSi8PhQKPRUFRUdEpHXdW8bjNRy0xq5gpW77/BYKC+vh6j0UgymSQQCIhM1kZmbhcLl1xQoigKH/zgB3nsscd46qmnLlqxjkQiuTwosVt54OmJ03+KL89jM2ye90MqlWJmZoZYLIZWq6W4uJjS0lJcLhdtbW0MDAwIHUEmkyGVSuFyuWhvbz8nDwp1g1TdUjs6OjAYDCwsLODz+QomDHs8Htra2hgcHNwwq6BeVy2tqFOKs9msCHbUY6xWa4HrqzkY5F0ffjefDd0DQNe1EW78ZJ4nH9Ry/Fk3T4Wu4tPv+yN6HvoaqedbX9WgJJ1OoyiKME4rLS0lHA6Ty+Xw+/0iENBqtaRSKTo6Oujr6xPZn7VlpUgkIu61w+FAr9cTiUTOuuSiZmo2EhqrWpuKioqz/OmcGrUctrKyIoKviooK0uk0U1NT7Nixg6GhIQYGBhgYGABWf1bqPbqYXV4vuaDk7rvv5vvf/z6PP/44DodDzD1wuVwiRSWRSCSbRVetl/7fDVJzz6k/xc//4K+o2VG8KdebnZ1lcHAQjUaD2+0mlUoxMDDA+Pg4XV1deL1eioqKmJubE6n6kpISXC7XOZtiqcerpRjVd8PhcJDL5QqyJDqdjkQiQUdHB4uLiwwODha0w+r1ejKZjNB42Gw2crlcgd28Gkio+gzVnbVq61ayLievS+4n/N4xmv7EiUYD7/xGnr0/GOXG7z5Hzu0ka7GI9l3V9TUSiaDRaERwpM7GAYRgF15whh0bGxPPm81mcrkcLpcLt9vN1NQUR48eFeWNxcVFioqKRACoBmnq8Sff76qqKnp7ewkEAkJEq75vtZ36xQYlS0tL9Pf3k0gkhO3+yMgIXq+X6upqxsfHWVlZYffu3cRiMSHgdbvdDAwMYLPZCjxcLjYuOU3Jqf7Tfec73+E973nPWZ1D2sxLJJKzxucjed0f8FdTH+BLfGLdp/iP80U+V/8tjL/7LbxIAaNqA19eXs6WLVtEySAej3PixAlyuRxXXXXVpn3SHR8fZ3JyEqvVislkYnFxEaPRSD6fL5i6azQa0el0JJNJtm3bRjQaxe/3C9Hn2ozK2bCRdXyd2810Xx/J0lKWdDYyWj2GfBZnboVqRWFFqyVyltuVxWIRBnCKouBwOEQbsIper8fj8RCNRqmoqKChoYFkMsnhw4cpLS0llUqRyWQwmUyEw2Hy+fyq86xGQyaTwWaz0d7eXqA3URSF4eFhAoEAbrdbtBGrAWRLS0tBsHKuxONxDh8+LGYWuVwucf7R0VERmEYiEbZu3Sq0PtlslsnJSaanp9m2bdsppxifLVJTsoZLLIaSSCSXOg4H5soKbk4dYvH2CRr+2C4+xV/7oylu/s4hjOVlqwZqL5Lp6WmsViutra0FH8CsVisdHR0cOHCAYDC4abbl8Xgcu90uumTq6+sJhUIsLy8XzI2xWq10dXXR398vpularVbRprwWdaqumnnZiHw+L3w9VlZWyGQyjASDlLa1kQoG8SgJ8pkXgha/RgOnOFdtbS0LCwsFA/dKSkooLS2lp6dHGLmtLfloNBqqqqqYmprC4XAQiUTEsMHS0lJmZmZQFEVMMVZ1G6qAOBKJMDQ0RHd3N3v27BGOtRqNhubmZtxuNz6fT7in2u12Ojs7KS5+cdm0qakpdDod27dvFwGrTqejsrISg8FAb28vnZ2dKIpCb2+v0FMuLy+Tz+dpamp60QHJheaSC0okEonkJcXlgiee4NWxGNdXVTG9nGElo2AzaKj5QjHau/52UxxdVcFqfX39hhlhq9WK0+kkHA5vWlCi1+vJ5XLs2LGDsbGxAiGq2q0yPz9PJBIhk8nQ1NQkOmzS6XRBNgUQ5YR4PM6WLVtEa7Feryefz4sJv4qiUFlZSWVlJb/5zW/E+1XPrZZdzjQAsKSkhOXl5YKABFaDO4fDwdVXX83c3BzhcLggm2O1WqmurmZ2dpZ4PE42my2YTKyi+poUFxfj8XjEOj0eD9u3b+e5555jZmaG2tpa4RFiMBjQarVCRwOrguITJ05QWVm5brDf2aIoCvPz89TW1m4oui0pKcGWzRLu7sZcXcOy0clvDjvZvWuJOk8RzRYz5kugMiCDEolEIjkTLhe4XGiBOsdJbb+b5DkBq5vx6Uoz6ua+WXi9XmZmZshkMuzYsYPl5WUOHTpEQ0MDVVVVHDp0iJKSEhYXF+nr6ytwIz05IIFC11SHw0FlZSXT09MFx9bW1jI3N0cqlRKb/kYZFdVx9XTZcdVhdqPJwX19fZSXl5PL5Qr8U2A1OzM1NUVdXZ0YWHcqtFot8/PzWCyWgsYKtd05EAgQDoeFdkav14uOprKyMlEimpubw+/3k06naW9vP+01N0IN6k6lB9EsLbHtIx+B8ALf/4f/YP94c4HzcNOdb0CprkJzgZ2HXywXb1+QRCKRXEFoNBrRvbER2WyWSCSyqTblbrcbt9tNf38/c3NzYsPL5XKcOHGCdDpNXV0dnZ2dxGKxDduDtVot5eXl69pMFxcX0Wq16x5X9R6xWEwMU9XpdKIEYjQaaWxsFG29a5/bCEVRTtlmOz8/TzgcRqPR4PV6xfVhNZsyPDyMxWKhqanplNkLRVEoLy9nampqnRNqJpMhmUyiKAqtra20tbWJwEydMFxeXk5rayt79+4V7qsnZ3bOBq1Wi8FgOKUjeWZhAcILq/OD7tzH4E9XA8HBn2bZd+c+rL5pkv4ZiMXO+dovJTIokUgkkouEyspKFhYWCtxTYXVjHBkZQVGUdd0biqIQiUQYHx9nbGyMYDB41tkUjUZDe3s7TqeT/v5+9u/fj0ajYWpqing8TldXF3a7HZfLtaFr9rZt24QI9uqrry54bmJigt/97nfr1jIwMEA+n2dxcVGUIerq6sRxmUyGsbExYDU7kMvlhLB0o/UD7N69my1bthQ8t7ZkVFJSIkpDra2tQpyqKAqJRILR0VEURcFgMKDRaOjq6irIZoTDYWEpr5JMJllcXMRkMrFz504qKipEZqeoqIhYLIbf7xfHWywW0SqsWvefCxqNhoqKCubm5oSD7Vr6Y3Hee/Mv+bjjCzzku4WeJ9c4D/v28XHH53nfm35Dpvz8hbYvBbJ8I5FIJBcJ5eXlolSizizJ5XJC+7B169YCI8hUKkVvby9LS0tCyzA1NYXRaKSoqIh0Oi0MvcrKyjbUIhgMBrq6ulheXiYcDrOyssL8/DzFxcUFlvUnZyMMBgMlJSUsLS0xPz9PVVXVunOvLeec/FrVaVWn0+FyucSxWq2W+vp6EZionDzTRy3bpNNpgsHguizG2pJRKBQSOpZgMEg8Hi8Q8q59j62trRQVFYnzrc3ETE9Ps7S0RHNzM5OTkwAFGiA1A6Le60AgQE1NjTh/UVER4+PjBXqTc6GmpoZQKMTRo0epqamhuLiYTCbD7OwsfTNJfvTtPWuO3mB+0Pfuo++TSbbXXpwTgkEGJRKJRLIp5HI5IpEIuVwOm8224Sf7M6HRaNi2bRsej4dAIMDw8DBarZaioiJaW1sLnELz+TzHjx8nk8nQ2dlJUVERGo2G0dFRpqenmZ2dRa/Xo9frCYfDTE5OiszHyailmYWFBRRFwWq1MjMzw/z8PC6Xi0wmQ2xN2l/1Itm/fz9Op5NMJlMgFC0qKmJhYeGUmpC1AY6iKPT39xfcx9HRUWB96/Ba1Fk/sNqVcvJ9XHtd1d3U7XZz4MABGhsbMZvN9PX1CQ0IrJaRVIMzNehYq1fxeDwkEgkOHz4sMitrRcdq0BeLxYRIeK1XihroGI3nN47AYDCwY8cORkdHRWYMVl3Lnd4zz7O595EIGsvF7W4ugxKJRCJ5ESiRCP6BAcazWcJ5E93dbrZvn6TWoWerzYa1rOychIVqmr6ioqKghfVkVGv13bt3C53J1NQU09PT4hidTkcqlUKr1aLT6Th+/DhXXXVVQcZkbm6O/v5+zGYzlZWVaLVaoWuxWq2ixbe6upqpqSlWVlbQ6XTCIfTkUhMghKXqfBtYFbiGQqF1otN8Pi9M2NYGABuJV8+mI0fVjKjzddT7oAYaOp2OqqqqdffW6XQSj8cJBoMkEgkCgQA6nY5rrrmG3/3ud0Ch+6uq8Vj7sykpKWF0dFRkSDQaTYHTrdrd9GIG8hmNRrZt28aWLVuEMZrNZuNEYOGsnIddplPrcy4GpKZEIpFIzpdolNQNN+B++y0MLdt4/HgLn7m3mcePt3B4Jo9yw2vJ33gjrHE1PRfWbmonEwwGcblcIiBZWVlhbGwMnU7HK17xCqqrq1EUhWuvvRan00kqlSKdThcEEclkkoGBAcrKyrjqqqtoaGigrq6OXbt2sWXLFmKxGBUVFbS1tVFWViZ0FrFYTJSVThckaDQakskktbW1BVoYi8WCXq9fJ4Jdm0HYSLx68vFrgyuz2Ux7ezu5XI5kMinafvP5PIlEgnA4TDqdxmQyMTMzw8GDBwuuk8vlhNnasWPHgFWH1qNHj4r3UlZWRllZGQaDQbQ+r3WstVgswjBtcnISu91OLpdjeXmZo0ePsry8LBxzXywGg0H8/LVaLe2VRVREQnTe/RUSlAI28S+Bl467vkzZvI8ahwxKJBKJ5LIkMT9Pdj6IPeDnbe9/W0HHwy133IIt4CMVmL0gHQ/ZbLZgE1dFldXV1UJ8mslk6O3tFZut6k6qMjMzg1arpbm5ed2GX11djdPpLBBrWq1WGhsbz7g2u92OzWYTAdX8/DxTU1MiS5JIJIRJ3NoW6JN1I1qttsAx9eQAKJvNisxIMpmkt7eXdDqNx+Nhx44d4l5oNBox7TgejzMyMkIqlcJoNFJSUiKurZ5fLbNMTU2xvLyMVqtlz5495HI55ubmCgKm7u5uFhcXRealsbFRdAvFYjF+//vfc+jQIeGCumPHjjPev/NBFwhw21238FRoL7A6P+ijjy/QdU0EgKdCV/GuO9+Gds3P82JElm8kEonkPPFrDdx38y9pePQxLL5FenxrOh64hYTDzfSbbuVhbzmbXcm3Wq3C/lyr1YoNf62GBF7IPsRiMVKpVEF77dLSEh6P55QTcEtKSsR5VNQyzEatqWobr16vp7y8nIGBAQwGA5FIRMyocbvdYlKvqiVRNSgnn6u2tpb6+nqefvppMpnMhlkZ9TH1HCaTCZvNRjgcprS0lB07dnDgwIENz68O87v22ms5evSoKCOpjrQqHR0d9PT0kM/naW5uJpfLMTY2JkpM3d3dmM1m9Ho9y8vL6HQ6GhoaWF5eJpPJYDQaqa+vLwiwNh2HA1NF+QvOw+94wXn4mn+b5OaHN895+EIigxKJRCI5T8YXFX707bY1j2zQ8fD9++j/ZIIddSf9uY1GySws4NNoGQoucfCgjauvTtBWUURFNoP2ecO2U1FRUUEgEMDv91NTUyMyIcFgUIhSm5qaRPdHb2+v8MiIx+NCL3K68ovqwLqWVCpFLBbD4XCQzWbZsmULQ0ND2Gw2Ojs7mZubY2BgQGQg1OGBKsvLyywuLmK1WjGbzSSTyQJDMHXysDoJNxAIiMzEWgGrepya1VCDjlwuRzAYZHp6mpGRERoaGsRr1LJLLpejvLwci8XC+Pg4/f394n2azWYxoFDVzszOzpLNZtmzZw9Go5HDhw/j8Xjwer3Ca8XpdKLT6SgqKmJlZYWJiQkURRE+Lhd8Mu/pnIf/uhjt3ZvjPHyhkUGJRCKRnCdG55nr8/c+EkFvO2mCeTRK/sYbSfsD/PJbj61z37z1zrdjqapE84tfnHITcTgc1NTUMDo6ytLSEkajkUQiITIYbrdbtOnmcjlRttHr9fj9fpqbm/F4PIyNjZFKpQpajWFVmDk3N0dRUWFXRywWQ1EUSktLGRsbw2q1kk6nhbCztLSUgYEBgsEgRqORUCgkXqvRaKiurmZlZYVgMCgCKdUC3mKx4HK5mJ2dRVGUAr2GuiZV2BmLxaiqqhItwbCqAWlqakKr1bKyssLQ0JBwbK2pqWF2dlasc63TrGpKV1xcTDKZFF09uVyOXC7H/Py8mCEzPT1NIpGgtbVVtAAbDAZMJhMlJSV0d3djMplobGzEYrEQi8WE6+vOnTtXA7BoFGVpiaDZwnAwxrMHLLzmBg2d1SXoZ2bOP3h4iZyHLyRSUyKRSCTnSWWRmweenuCLP9yPhXlgWfyzMMeXHt2PuzyPw1T4KVlZWiLhn8Hm923gvvmOVffNwJndNxsbG2lpaWF5eZlYLFbgzaEoCn6/n4mJCfbv308+n6ehoQGv1yu6SNRP8L29vQU+H7lcjqGhIRKJxLpOETWjUFRUhF6vZ2hoCL1eL0ofauZFnSCby+VESSefzzM+Pk4oFMLj8aDVajGbzeLaLpeLrVu3ct11123Yumy1WqmpqRHak5WVFTGlVtW/HD16lNHRUaampgramNVBdNFoFLfbze7du6mrqxMC3OrqarLZLPF4HIPBwM6dO0W2B1YzRCdOnCCVStHV1YXD4WBubg6Xy4XNZiOVSjEwMIDdbmfPnj3U1NRQUlJCQ0MDe/as+oeMjIxANEruxhuJX/sK/uPAOP/030V89L3l/N1PzfzzE0dJ/cEr4aabzlscfakjMyUSiURynjQV26haGqby7q+Q4EcFzyWw0XHXB5j7/l9Rs6NwOuyi3ckdN/3i9FqUN97Kd0rL2HjSySoajYbKykoqKipIJpNMT0+LVtZUKsXY2JgoXVRXV1NXVyecYeEF47Tjx4/z7LPP4vF4hFdHLpdj69at60bTO51OtFotoVCI9vZ2enp6gFWXUoPBIEo1brdbzIBRFEUMq1MfW1hYwOFwEIvFRCATDoc5duwYer0eg8EgjlfXG4/HCzQukUhEZCtaW1tFK28wGESn01FbW8vy8rIwHMvlciwuLha09qpMTEyIko06hddut/Pss8+SyWSw2+0sLy/T1NSE0+lkYmKCaDRKe3s7IyMj6PV6EokEW7duXVeqMZlM1NbWMjw8TMJkIu8PPB+QvoOH2w4BqwHp1/puweSbJI0GYyx20ZdaLgQyKJFIJJLzROv38+4PvJ1Ph+4AVjsebvxknicf1HL8WTdPha7ic3/+FrS/+21B+rxnauWstCg9/yvK3i2eM65D9RJpaWkhkUiIqb5arRaPx0N1dTVutxtFUQiFQgUmbE6nk6uvvprZ2VkWFhbIZDJUVFRQWVkpOlvWYjAYqKioYGpqira2Nnbt2sXU1BTz8/OMj48Dq903HR0dHDx4UAQUqh5jaGhItCWrmQw1cMlkMkSjUYxGo8ieqNoRVURbW1tLTU0NwWCQ/v5+kR1SBa5rsxuACJqsVit1dXWcOHECWBUAZzIZqqurRUkGVocUqsJfNUA5cuSIELCOjo4yPDxMOp2moaGBfD5PKpWitLQUrVa7LohT8XhWf46TOfj0TU+eIiDdR8Lhxv/G2/huRdUVuUFfie9ZIpFINgeHA2N5GTcnDxF57xT1t1hFx8O1P5ri5u9s3PGgPQuz13sfiYBJES2pFovlrEbeNzU1cejQISoqKgoGzSmKwtjYGMlkkra2toLXGAwGampqCizRVfL5PLOzs8zMzJBMJtHr9ZSWluJyuThx4gR2ux273S5cXmG15feZZ54RGRCNRsPAwABtbW20tbXR2NhIMBgUzq2qtiSXy5HNZtdZxqvdMFu2bKG4uJipqal182NmZ2fXlZqy2awQwCaTyQLn1nQ6jVarFWZzJpNJeLmsxW63s2PHDo4dOyYEuF6vl/LycmKxGAMDA5SWlmKz2cjn82Sz2Q0HCKpi3cH5DD/69topwRsEpP96H5/6ywztlefn/Hopo1FONxf6MkXtF1drnhKJRHLeRKMQi5E/uePBblj1hNhAtDgwH+XRkcgp3Tf/+jvHMZR7qXGkyecUurvdXHVVnK4aL5W5LBqn87Spfb/fz/DwMGazGafTyfLyMolEAkVR8Hg862bonIpcLsfx48eJRqMUFxfjdDpJJBLMz8+LttfFxUXh+eH1etHpdCKQCgQCJBIJ6urqRBeNy+VCq9UWlFA8Hg/bt29HURTC4TD9/f1CzKooCmazmWw2W6CZUVmbSbnuuusKSicTExNMTExQUVEh1qnT6airq2NhYUGsob6+ntraWp5++mkAXvnKV667ztLSEkePHi2wr9doNJSXl9Pc3Ewmk+HZZ5+loaFBDN5bS39/P5FIhAWThzft3nba+/6J/wxz29U22oouTkv4C7mHykyJRCKRvBjOo+OhpdRJ5eERqk6hRdn5/s+zo3iEf/vOT3l6tJGH713tzJkODfHuD9yCpaoSnnjilIFJVVUVNpuNwcFBUSqxWCxYLBai0SgHDx6kq6trww0lmUwyMzNDPB5nZWWFRCLBjh07cLvd4piGhga6u7sJBALs3r17XQanuHhVQxMKhYS7qeqEGovFRKlEtY1X58doNBpKSkpobW2lr6+PyspKAoGAENGuRafT4XA4iEQiwi/kwIEDNDc3C68WdapvU1MTiqJw6NAhMpkMo6OjYm7N7OwsbrcbrVaL2+0mHA6ztLS07t5EIhEURWHr1q0iCCoqKhLBnclkoqKigvHxceHTotVqyWazTE9PMzc3R3NzM9lI8qzs4G2GM2fFLkdkUCKRSCQvMVq/n9vu2ndKLcp/Zm/mVXOf5JY/ezP/3HUMUIWQ+7D4pkhptZjOIIRMJpMkEgmam5uprKwUgUMmk6Gnp4eenh6uueaagsyCmmHR6XTY7XZRjhkZGaGzsxOj0UgkEiEWi+F0OpmdnWVwcBCz2UxRUREOh6MgQHG73UxPT1NfX8/MzIwoy6zVbOTzebEGRVFEYKLX60Wr78loNBra29vxeDyMjIzg9/sxGAyiQ0Y9t9vtZnFxkWw2i9lsxuVyiXlBWq2W+fl5ZmdnRWCh1+vRaDR0d3dTVVVVMKV5fn6empqaggF8J7NlyxbRuTQ+Po7JZCIej5PP56mvr6eyshKbfYn+iSFq7jm1OHr2Xz9NzY7tp7zO5YwMSiQSieSlZo0W5WT3zd3fHyPyDQufTn8S7WyWntnzE0L6fD6KioqEV4mKwWBg27ZtPPfcc8zPz4uW2FAoxPDwMFVVVTQ0NBCPxzly5Aitra2Mj4/T3d0NrHbAqCUTWNVy6HQ6JiYmcLlctLW1iU1eFcSurKxw1VVXkUwmURQFRVE4fPgwmUwGvV7P+Pg4Q0NDpNNpDAYDZWVl5PP5DY3ddu/ezfDwMENDQ1x99dW4XC78fj9ut5tgMCj8V0wmE4qisH//fqampmhpaaGsrIyenh4WFxfxeDxMT0/jcrmEZiUYDFJTU0Mul8Pv94vpw2azWQR3p0Or1bJt2zZqa2uFHX1paSllZWXCIM4di/HuD9zCZ4J3AacQR9/5tnXi6CsFqSmRmhKJRPJysIEWxaqH/ftP8Kc37TntSy3OHAf7s6cUQuZyOX73u9+xdevWU36yP3z4MDabja1btwKIwXM7duxAo9GwtLTEkSNH2LlzJ8lkUkwSbmxsZGhoCJPJxMrKijAzU1teDQaDyETA6uDAvr4+9Ho9VqsVRVFIJBJkMhkxmTebzVJUVERJSQnxeJyZmRlyuZzIqKhzftLpNJWVlbjdbvr6+igtLRWmcF6vl9nZWdrb2yktLRXv0+fzMTIyQllZGdXV1YyNjRGJRISwtbOzk3Q6zfj4uDB3CwaDpFIp9Ho9JSUlVFdXi0BMo9G8OHfWaBTlppv49Xgl37/tyzS904lGA4oC448u86ff/Rivrvedtjz3ciM1JRKJRHK5sYEWRVEUDjvOvOHd+0gEjfnMLTyn+8y59jm1FXfr1q2i/GK324XviBpgeDwe0cZbVVXF0NAQzc3Nwmq9s7OTw4cPEwwGhVlZSUkJZWVlzM7OrnNoXVpaQq/X43a7WVhYQKPR4HK5RACQzWZpaGhgfHxcdMUEAgHReRMKhaioqGB2dlZ0t5w8gbe8vBxFUZicnCywu1d1KsePHwdWS02ZTIaRkRGKioooLS1lZWWF6RMnCHd3ky4rYy6to7vbzR/8QZbttV5KEolzd191udA88QSvicV4VWUlE9Eky5k8brORmgeL0d5zadjBXyhkUCKRSCQXCRqNBq/L8aKFkKoINBgMivLMWuLxOMvLy6KFVi2TrB3Mp9VqqaqqYmJiQpiZaTQagsEgHo+H8fFxPB6PmMEzPz9Pe3s7LpeL+fl5EZSMj48zOztLfX09VVVVYq7MyMgI4XCYbDaL1WrFYrGwsLBQMMUYVjtodDoder1eWL3r9XrS6TRlZWVYrVby+TzRaJTS0lJRJgmFQkxPT4tAyGw2i1Zmi8WC2WwmGo2iKAoOh4OJiQmWl5fZvXu3CGzyi4vEb70Vwgv84B//g2fGmoXoeDQwxG137cNcWXHuWY3nA1Id0OQ5aUjfFViyWYu0mZdIJJKLiB11ZZQvBum85yskKAVs4l8CLx13f5mK8Aw19tPP3amurmZhYQGfz1eQFUmn0/T392M0GkWZw2g0YjAYCAQCws0VoK6ujrKyMrLZLJlMhuXlZZLJJMFgEJPJxLZtq62tZrNZZCrU9l31WtPT09TV1VFfXy/8OywWiygr6fV65ubmhBC2pKSEnTt3iunGFotFlFg0Go0o4wDMz8+vWrez2v3S3NwMwPT0tBC8Njc309TUhM1mY2ZmhlAohMPhwGQy4fV6KSsrQ6fTMT8/T319fUGmZW5kBMIL2AN+bvnzW04aB7AP89Qk6Zm5M44DkJw9MlMikUgkFxGOSITb797H/cE7gQ2EkMGr+Nz7/+iMQkiv18vy8jIjIyMEAgE8Hg+ZTIZQKIRWq6Wrq2vVjn5+nvHjx0nr9YxFUjz2mxC7do3TVuGh0aCnpayMYDBIPp9HURR0Oh0Wi4Vdu3ah1WpRFIWlpSWKiorEED21fTgUCqEoyjqxLSB0GSd7j6i6jZKSEmFd73Q66ezsZHBwsMBYTe3c8Xq9eDweFEUhHo8zOjpKZWUl+Xye0dFRkQmyWq2EQiFmZ2cLRKtqNsXr9RasZTyb5/+84b+o++GPsfgX6fGvFx0H3ngbD1+h7qsXAnkfJRKJ5GLC4cBUUc7NqUNEbp+gfk1nzulcYk9Go9HQ1NREcXGxyICo82AqKytXbdZDIdKvfS01ixGe+fZP+N3wC54oM5Ehyu94O3mPC82DD6JxOGhpaSEWizE0NMTS0hJut5tAIEAqlRJlnGQyKUpG2WwWnU4nsh5rWVsqqqqqwuv1Eo/HxVA9VUAZjUbZv3//unZjlVwux8zMDDMzM8BqZkWn0xEOh8nn89TV1eFyuUilUvj9fgAmJyfP2EmTz+eZWtLz6D+tNTrb2H31vivUffVCIIMSiUQiuZhwueCJJ3h1LMb1J7vEfqEY7V3nJoR0u90FxmdrmRkaonghgi3g463/823809rhcL37sPmniWtge2Mjw4kEx44do6ysDLvdTnd3N1arlZWVFYqKivD7/czNzVFZWSlm65jNZnK5HCsrK9hshcLcsbExIWg1mUw4nU5cLhder5fDhw+L7EVnZyeLi4skEgny+bxwUVUnI6vlnKqqKqxWqxg4qNVq2b17t9CYAOLcy8vL5HI5ka1R1zs/Py90NhqNBoP9zAqHsxUdS84OGZRIJBLJxcZ5uMSeD1OKho+98ZfUPfLjUw+He/O7+ZwFUpEIuVyuYObMysoKAAsLC5hMJrZs2VJQqikpKcFgMDA+Pk57e7vIdKhDA41GIzqdjrGxMfx+PzabjXg8Ljpj1IxHS0sLgUCAcDhMV1cXer2eI0eOoNfrueaaa5ienmZ8fJw9e/bgcrmIRCJYrdaCgARWAw3Vdj8YDApdi6ovmZiYwOl04nQ60Wg0FDts0n31JUYGJRKJRHIFoigKvmUjj/7jmcsT/+PNR9lRt9omm81mmZ2dZXFxUXh/aLVarFYrGo2GXC4nxLIWCAuQGAAAGYJJREFUi4Xm5mb6+vo4duwY1dXVmM1mZmdngdUSyc6dO4VraiqVwuPx4PV66e7uxuPxEAgE0Gq1LCwsUFxcjNVqFZN/Gxsb0Wq11NTU4Pf7hXYmEomwvLy87j3n83nC4TBarVa41aq0tLTQ3d3NkSNH8Hg82Gw27JkY5YtRak4xDqDjrg8w/4O/omZH8Wb9WK54ZFAikUgkVyAajQaT6/QdPLBanqjfWsvWuhcMycrKyggEAgwNDVFeXi5EppOTk0xPTxeIV+12O1u2bGFubo7e3t6Cczc3N4uyzloTLlXMWlJSgtPpZGJignw+TzKZ5Nlnn0Wj0WC1WoUuRKvV4nK5iMfjVFVVMT4+Ti6XIxqNitJMMplkeHiYVCqFVqst0LTAqsZl586dwno+HA5jj0R49wf+nM+ETuO++v63XLHuqxcCGZRIJBLJFUqZ23lW5YmKovX6lYqKCnw+HzMzM8K3ZGpqiqqqKqqqqjCZTEQiESYmJhgfH2fnzp3odDoymQwmk4kjR44QDoeFn8la/H4/Wq1WzMCpqKjg2WefxW63i4m/qseIWhJSLeptNpsY0Hf06FGsVis6nY5YLIZOpxND/kpKStZdV6vVUl5e/oILbjQKVZXcnFk/DuBcRMeSs+eS9Sn5xje+QX19PWazmauvvpoDBw683EuSSCSSS4qd9eWrnih3n8IT5a4vUzo3vaEnikajwe12E4/HSaVSYvBec3OzCASKi4vZsWMHRqORiYkJLBYLTqcTk8lEfX298BlRfUey2SyTk5NMTU1RU1MjshkGg0E4rDqdTioqKkgmk4RCIQCWl5eFeVo6nRYtwG63G4fDgc1mo6mpiYaGBmZnZ4Xp2hlRRccH/5ZvPljHnzY7eXOdgz9tdvJ/v1DDqw/+7UVtB38pcklmSn74wx/ykY98hG9+85tcffXVPPTQQ7z+9a9ncHBwXZ+5RCKRSDbGEgqteqKETuGJErqKz7z/LWj3P71heSKVSgnjMXVuzMnodDqqq6sZHh4mk8kIA7WKigqy2Szj4+P4/X5MJpMIKKqrq6mvrwdWyy7j4+PMz8+jKAoHDhzAbrfjdDrp6+ujvLychYUFoWk5duwYWq2W+vp6JiYmiEQiWCwWgsEguVyOsrIyWlpazv4mPR9waP1+yr1eToQWePL3el75B1k6qryY5ucLjpO8OC7JoORrX/sa73//+3nve98LwDe/+U1+9rOf8c///M988pOffJlXJ5FIJJcIBZ4ok9S/w1ZQnnj9tw+QcdrRmUyc7MKRSCRYWFigqamJVCqFyWRap9NQUXUja4MSgJqaGsrLy5mfnyeZTGI0GvF6vWLKcDKZ5OjRoyiKQkNDg+jUUUWsGo1G+JMA9PX14XA4aG9vx2azUVFRwfz8PIlEQpisnVWGZC3PD9BL+gP8y9//O/vHm3n4g6teLtc2HOfdH7gFS9V5WM1LNuSSC0rS6TSHDx/mvvvuE49ptVpe97rXsX///g1fk0qlClwAl5aWLvg6JRKJ5KLnDJ4omfd9iaMjI+gnJ2k1m3E4HMLBdWBgAKPRSHl5ubCIPznoUFGDiI2eMxgMGzq+wqqXiaIo7N69WwQqaqAxMTFBOp2mtbUVRVFQFEVkUFT0ev0ZTdLOSCxG0j+DZXqKfXfewsNth4HnvVz6bsHimyQJmGMxGZRsApdcUBIKhUQKbi1lZWUMDAxs+JoHH3yQBx544KVYnkQikbwsKJEI4YkJfGgIJKG7283rXqtne50X49zcqQ3XTuOJYmpqoqOsjBMnTnD48GHMZjOKopBKpbBarWzfvh29Xo/X62VsbAyfz0dDQ0PBObLZLH6/X3iWnC2ZTIZgMEhjY6MISOAFMarT6eTAgQPCTO2siUbJRSLMGoyMRxIcOGDlda/T015ZhC4QWHefUt5ybrvx5zQ8+mMsvsiGXi6+N97Kw2UV67JJknPnkgtKzof77ruPj3zkI+L7paUlampqXsYVSSQSyeaRX1wk+epXYw6FOfhPj/PM6BYe/qCLoa9HeUVjN7fdtQ9TRfl5lRjsdjtXXXUVCwsLwmXV4/Hg8XhE54vJZKKuro6JiQkymQxVVVUYjUai0ajIaHR0dJzTdZPJJIqinNKN1mq1YjQaSSQSZ3/SaJTsH/4hqcAMP/vWj9k/3iJKMa9oPMptd92y7j4dGYvyo2+3rTnJBl4u37+Pox9e5OoW6VfyYrnkgpKSkhJ0Oh1zc3MFj8/NzZ0yWjaZTAWRtkQikVxOTPf1URwKi2m23ymwi78Fk3+StEaD8TxLDGp77kZttCp1dXXodDqmpqYKXF8dDgc7duxYZzN/JlQL+FQqVTC5VyWbzYrZOmdLYn6enH8Ge8DHvjvfwcMF9+ntG94nxZQ93SmBVS+XvDF31uuQnJpLLigxGo3s3r2bX/3qV7zlLW8BVl36fvWrX3HPPfe8vIuTSCSSl5hcLsdETuHjb/wVdY/8+ynt4mfeeDvfuYDTbDUaDTU1NVRWVhKNRslms1itVux2+3mdz2KxYLfb8fv9FBcXrxvGNzs7Sz6fp7S09BRnWM9EVuH+m5+k4dHHTnmfAm+4vWDqr9tiPCsvF49FfvDdDDSKoigv9yLOlR/+8IfcfvvtfOtb3+Kqq67ioYce4tFHH2VgYGBDI56TWVpawuVyEY1GC0RREolEcqkRi8X42TND/MlNe057nMWZ42B/9oJPs1UUhXQ6jaIomEymDSf7ni2hUIgTJ05QXl4ufKlUS/qRkRHKy8tpbW096/P96Ffd7HvdjtMec/J9yuXz/PMTR6l+z4O8Ifijdcf/Z8nb8X33U/zZTTvRaS9Z669z4kLuoZdcpgTgj//4jwkGg9x///3Mzs6yY8cOnnjiibMKSCQSieRyQ38RTLNVIhGCY2NM5HIEEqtC2z17lmmrKKJOq0H7vKD2XCgpKaG1tZXh4WFmZ2cxm81kMhlyuRzl5eU0Nzef0/m0Z9ENfPJ90gUC3HbXLdwfPLWXy2fvugXd738nreY3gUsyKAG45557ZLlGIpFc8dhsNixa5eWdZhuNknrNa7DOzXP8n37C06NNPHyv6uUxzK13vg1LdRWa8xDaVlRUUFpaKvxG1G4fi8Vyzst0GHXnfp+e93K5KXmQ8G1jNL3TKbxcrnpkjJv+v4Or4lhpNb8pXLJBiUQikUhWRahbyzz4+4PU3PNVEvxbwfMvTLP9zAWbZrsyO4syN4894Oftf/52/nmtgLRvH1bfNEmt9ry9PDbFbwRoqyhm/KjvtPdp7vv3F96n571cbojFeFVVFaMLKyylsrjMBhq/WIz23odO3W4tOWeujAKYRCKRXMY06HXceufbeCq4qivpujbCRx9foOuaCABPha7iT97/R2j9/gty/am8hvfe/Es+7vgCD/luoefJNQJS3y183PF5/uyNvyVbsbFJ2ktFZS7LrXe+/bT36U///K3r75PLBdXVaDUamovt7K50s6XIhlajWS3ZyIBk05CZEolEIrnE0bpcWKqreH3mAAu3jdP4TsdLOs12JKyc2cvje/cx+L8zF1xoezo0TufqfUofIHx7YSnmmkcnuPm7curvy80l2X3zYpHdNxKJ5LIjGoVYjPzJdvF2w+on/wtYYniie5ibd5x+yN0n/jPMbVfbaCt6mVtnn79PucpKJqJJVrIKLrPhJblPlwuy+0YikUgkp+c0dvEXuiukzO18eYW258Lz90kHNHlOaseR3TMvO1JTIpFIJJIXRUdVMRWREJ13f4UEpYBN/Evg/f+3d/8xUdYPHMDfdxA/tDsB+Z0ISG7YVFR+ObGAZEFRwWKQpU6Zo1D8lVZmlqBrwqTUiQ6xFpqrcKYWQUlMPVwONCRNcFqomDtURE2ICpH7fP8wbt0XNEjuPg/c+7XxB8997rn3fWTy5nk+z3MYOz8Xns2N8Hm49599Q9aJpYSIiB7IQ1euYPb8ZOiaQwHcawFpotkW2tLgwdM3RET0YDQa2Hl54On2avw2+yL8UoZadKEtDR5c6MqFrkRED07iQluyLC50JSIiZZO40JYGD64pISIiIkVgKSEiIiJFYCkhIiIiRWApISIiIkVgKSEiIiJFYCkhIiIiRbDKS4K7bs3S0tIiOQkREdHA0vW70xy3ObPKUtLa2goA8PHxkZyEiIhoYGptbcWwfr4hnlXe0dVgMKCxsREajQYqVe8+tbKlpQU+Pj64dOmS1d4FlnPAOejCeeAcAJwDwDrnQAiB1tZWeHt7Q63u31UgVnmkRK1WY8R/vMOgVqu1mh+8e+EccA66cB44BwDnALC+OejvIyRduNCViIiIFIGlhIiIiBSBpaSX7O3tkZmZCXt7e9lRpOEccA66cB44BwDnAOAc9DerXOhKREREysMjJURERKQILCVERESkCCwlREREpAgsJURERKQILCX/UWlpKcLDw+Ho6AhnZ2ckJibKjiRFe3s7JkyYAJVKhRMnTsiOY1ENDQ2YO3cu/P394ejoiICAAGRmZuL27duyo5nVli1b4OfnBwcHB4SHh+PYsWOyI1lMdnY2QkNDodFo4O7ujsTERJw9e1Z2LKlycnKgUqmwZMkS2VEsTq/XY+bMmRg+fDgcHR0xbtw4VFdXy441oLGU/Ad79uzBrFmzkJqaipMnT+LIkSN4+eWXZceS4s0334S3t7fsGFKcOXMGBoMBBQUFqKurw4YNG7B161a8/fbbsqOZza5du7B06VJkZmaipqYGQUFBiI2NRVNTk+xoFlFRUYGMjAxUVVWhvLwcHR0deOqpp9DW1iY7mhQ//PADCgoKMH78eNlRLO7mzZuIiIjAQw89hG+//RanT5/GBx98AGdnZ9nRBjZBfdLR0SEeeeQR8dFHH8mOIt0333wjAgMDRV1dnQAgfvzxR9mRpFu3bp3w9/eXHcNswsLCREZGhvH7zs5O4e3tLbKzsyWmkqepqUkAEBUVFbKjWFxra6sYPXq0KC8vF5GRkWLx4sWyI1nU8uXLxdSpU2XHGHR4pKSPampqoNfroVarMXHiRHh5eeHpp59GbW2t7GgWdfXqVaSlpWHnzp0YMmSI7DiKcevWLbi4uMiOYRa3b9/G8ePHERMTY9ymVqsRExODyspKicnkuXXrFgAM2n/z+8nIyEB8fLzJz4M1KS4uRkhICJKTk+Hu7o6JEyfiww8/lB1rwGMp6aPz588DALKysvDOO++gpKQEzs7OiIqKwo0bNySnswwhBObMmYP09HSEhITIjqMY9fX1yMvLw6uvvio7ilk0Nzejs7MTHh4eJts9PDxw5coVSankMRgMWLJkCSIiIjB27FjZcSyqqKgINTU1yM7Olh1FmvPnzyM/Px+jR49GWVkZ5s2bh0WLFmHHjh2yow1oLCV/e+utt6BSqe771bWGAABWrlyJpKQkBAcHo7CwECqVCrt375b8Lh5Mb+cgLy8Pra2tWLFihezIZtHbefgnvV6PuLg4JCcnIy0tTVJysqSMjAzU1taiqKhIdhSLunTpEhYvXoxPP/0UDg4OsuNIYzAYMGnSJKxduxYTJ07EK6+8grS0NGzdulV2tAHNVnYApVi2bBnmzJlz3zGjRo3C5cuXAQCPPfaYcbu9vT1GjRqFX3/91ZwRza63c3Dw4EFUVlZ2+6yHkJAQzJgxY8D/pdDbeejS2NiI6OhoTJkyBdu2bTNzOnlcXV1hY2ODq1evmmy/evUqPD09JaWSY8GCBSgpKcHhw4cxYsQI2XEs6vjx42hqasKkSZOM2zo7O3H48GFs3rwZ7e3tsLGxkZjQMry8vEx+DwDAmDFjsGfPHkmJBgeWkr+5ubnBzc3tX8cFBwfD3t4eZ8+exdSpUwEAHR0daGhogK+vr7ljmlVv52DTpk147733jN83NjYiNjYWu3btQnh4uDkjWkRv5wG4e4QkOjraeMRMrR68Bx/t7OwQHByMAwcOGC+BNxgMOHDgABYsWCA3nIUIIbBw4ULs27cPOp0O/v7+siNZ3LRp03Dq1CmTbampqQgMDMTy5cutopAAQERERLfLwX/++ecB/3tANpaSPtJqtUhPT0dmZiZ8fHzg6+uL3NxcAEBycrLkdJYxcuRIk+8ffvhhAEBAQIBV/dWo1+sRFRUFX19fvP/++7h27ZrxscF65GDp0qWYPXs2QkJCEBYWho0bN6KtrQ2pqamyo1lERkYGPvvsM3z11VfQaDTGtTTDhg2Do6Oj5HSWodFouq2hGTp0KIYPH25Va2tee+01TJkyBWvXrkVKSgqOHTuGbdu2DeqjpZbAUvIf5ObmwtbWFrNmzcKff/6J8PBwHDx4kNenW5ny8nLU19ejvr6+WxkTg/TDt1988UVcu3YNq1atwpUrVzBhwgTs37+/2+LXwSo/Px8AEBUVZbK9sLDwX0/50eASGhqKffv2YcWKFVizZg38/f2xceNGzJgxQ3a0AU0lBuv/nkRERDSgDN4T4ERERDSgsJQQERGRIrCUEBERkSKwlBAREZEisJQQERGRIrCUEBERkSKwlBAREZEisJQQERGRIrCUEBERkSKwlBANcg0NDVCpVPf9+u2338yeQ6fTQaVSISsry+yv1d/y8vKQmpqK8ePHw9bWFiqVCjqdTnYsokGHn31DZCUCAgIwc+bMHh9zcHCwcJqBZdGiRQDufly9m5ub8YP4iKh/sZQQWYlHH310QB6lUIKSkhIEBwfD09MT6enpKCgokB2JaFDi6RsiMvHTTz9h+vTp8PLygp2dHXx9fbFw4UJcv36929iPP/4YCQkJ8PPzg4ODA1xcXBAbG4tDhw6ZjMvKykJ0dDQAYPXq1SanjhoaGgDc/eRdlUrVY6Y5c+aYjAWA7du3Q6VSYfv27fj6668REREBjUYDPz8/45jbt29j/fr1mDRpEoYOHQqNRoPHH38cxcXFfZqT+Ph4eHp69uk5RNR3PFJCREbFxcVISUmBWq1GQkICfHx8cPr0aWzevBllZWU4evQonJ2djeMzMjIQFBSEmJgYuLm5Qa/X48svv0RMTAz27t2LhIQEAHcLR0NDA3bs2IHIyEhERUUZ9+Hk5PRAmXfv3o3vvvsOzz77LObPn4+WlhYAQHt7O+Li4qDT6TBhwgTMnTsXHR0dKC0tRUJCAvLy8rBgwYIHem0i6l8sJURWor6+vsfTN3FxcZg8eTKuX7+OWbNmwdXVFUeOHIGvr69xTFFREV566SWsWrUKeXl5xu2nT5+Gv7+/yf4uX76MkJAQvPHGGyalBAB27NiBqKiofj2NtH//fpSVlSEmJsZk+5o1a6DT6fDuu+8aj84AQGtrK5588kksW7YML7zwAry9vfstCxE9GJYSIitx7tw5rF69utt2JycnTJ48GZ988glaWlqwefNmk0ICANOnT0dubi6KiopMSsn/FxLg7mLQpKQk5OXl4eLFi9321d8SEhK6FRKDwYD8/HwEBASYFBIA0Gg0WLVqFZ5//nns3buXR0uIFISlhMhKxMbGYv/+/fd8vKqqCgBw9OhRnDt3rtvjf/31F5qbm9Hc3AxXV1cAwPnz55GdnY2DBw9Cr9ejvb3d5DmNjY1mLyVhYWHdtp09exY3b96Et7d3j0Xs2rVrAIAzZ86YNRsR9Q1LCREBAG7cuAEA2LJly33HtbW1wdXVFfX19QgLC0NLSwuio6Px3HPPQavVQq1WQ6fToaKioltJMQcPD49u27reS11dHerq6u753La2NrPlIqK+YykhIgCAVqsFAJw6dQpjx4791/EbNmzAzZs3sXPnzm73P0lPT0dFRUWfXl+tvnsx4J07d2Bra/pf061bt+75vJ6u2Ol6L0lJSfjiiy/6lIOI5OElwUQEAAgPDwcAVFZW9mp81ymersWsXYQQOHLkSLfxNjY2AIDOzs4e99d1VY9erzfZbjAYcPLkyV5l6jJmzBhotVpUV1ejo6OjT88lInlYSogIAJCamgqNRoOVK1f2eMrjjz/+MK47AWBcK/L999+bjMvJyUFtbW2357u4uAAALl261OPrh4aGArh7/5F/Wr9+PS5cuND7NwLA1tYW8+bNw8WLF/H666/3WExqa2vR1NTUp/0SkXnx9A0RAQDc3Nzw+eefIzk5GUFBQYiLi0NgYCDa29vR0NCAiooKTJkyxbhYNj09HYWFhUhKSkJKSgqGDx+Oqqoq1NTUID4+HqWlpSb7DwwMhLe3N4qKimBvb48RI0ZApVJh4cKFGDZsGFJTU7Fu3TpkZWXhxIkTCAgIQHV1NWpraxEZGdnn00GrV69GTU0NNm3ahNLSUjzxxBNwd3eHXq/HqVOncPLkSVRWVsLd3f1f95WTk2NcFNt1JCknJ8dYoBITE5GYmNinfETUA0FEg9qFCxcEABEbG9ur8WfOnBFz584Vvr6+ws7OTjg7O4tx48aJRYsWiWPHjpmMPXTokIiIiBAajUY4OTmJZ555Rhw/flxkZmYKAOLQoUMm46uqqkRkZKTQaDQCgAAgLly4YHz8xIkTYtq0aWLIkCFCq9WKhIQE8csvv4jZs2d3G1tYWCgAiMLCwnu+lzt37oiCggIREREhtFqtsLe3FyNHjhRxcXEiPz9f/P77772ak8jISGPenr4yMzN7tR8iuj+VEEJIaUNERERE/8A1JURERKQILCVERESkCCwlREREpAgsJURERKQILCVERESkCCwlREREpAgsJURERKQILCVERESkCCwlREREpAgsJURERKQILCVERESkCCwlREREpAj/Ayf9CC3UdnCJAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# select data using n-similarity methods\n", + "# -------------------------------------------\n", + "size = 50\n", + "\n", + "# Jaccard-Tanimoto\n", + "selector = NSimilarity(similarity_index=\"JT\", preprocess_data=True)\n", + "selected_jt = selector.select(X, size=size, labels=labels)\n", + "\n", + "# Austin-Colwell\n", + "selector = NSimilarity(similarity_index=\"AC\", preprocess_data=True)\n", + "selected_ac = selector.select(X, size=size, labels=labels)\n", + "\n", + "# Russel-Rao\n", + "selector = NSimilarity(similarity_index=\"RR\", preprocess_data=True)\n", + "selected_rr = selector.select(X, size=size, labels=labels)\n", + "\n", + "# Faith\n", + "selector = NSimilarity(similarity_index=\"Fai\", preprocess_data=True)\n", + "selected_fai = selector.select(X, size=size, labels=labels)\n", + "\n", + "\n", + "graph_data(\n", + " X,\n", + " figsize=(6, 4),\n", + " indices=[selected_jt, selected_ac, selected_rr, selected_fai],\n", + " labels=[\n", + " \"Jaccard-Tanimoto\",\n", + " \"Austin-Colwell\",\n", + " \"Russel-Rao\",\n", + " \"Faith\",\n", + " ],\n", + " title=\"Comparing NSimilarity-Based Selectors\",\n", + " xlabel=\"Feature 1\",\n", + " ylabel=\"Feature 2\",\n", + " fname=\"quick_start_compare_nsim_methods_cluster.png\",\n", + ")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.5" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/pyproject.toml b/pyproject.toml index 8c7cda4a..e67bbfe3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,420 +1,420 @@ -# The Selector library provides a set of tools for selecting a -# subset of the dataset and computing diversity. -# -# Copyright (C) 2023 The QC-Devs Community -# -# This file is part of Selector. -# -# Selector is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 -# of the License, or (at your option) any later version. -# -# Selector is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see -# -# -- - - -[project] -# https://packaging.python.org/en/latest/specifications/declaring-project-metadata/ -name = "qc-selector" -description = "Subset selection with maximum diversity." -readme = {file = 'README.md', content-type='text/markdown'} -#requires-python = ">=3.9,<4.0" -requires-python = ">=3.9" -# "LICENSE" is name of the license file, which must be in root of project folder -license = {file = "LICENSE"} -authors = [ - {name = "QC-Devs Community", email = "qcdevs@gmail.com"}, -] -keywords = [ - "subset selection", - "variable selection", - "chemical diversity", - "compound selection", - "maximum diversity", - "chemical library design", - "compound acquisition", -] - -# https://pypi.org/classifiers/ -# Add PyPI classifiers here -classifiers = [ - "Development Status :: 5 - Production/Stable", - "Environment :: Console", - "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", - "Natural Language :: English", - "Operating System :: MacOS", - "Operating System :: Microsoft :: Windows", - "Operating System :: Unix", - "Operating System :: POSIX", - "Operating System :: POSIX :: Linux", - "Programming Language :: Python", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.12", - "Programming Language :: Python :: 3.13", - "Topic :: Scientific/Engineering", - "Topic :: Sociology", - -] - -# version = "0.0.2b4" -dynamic = [ - "dependencies", - "optional-dependencies", - "version", - ] - -# not using this section now but it's here for reference -# # Required dependencies for install/usage of your package or application -# # If you don't have any dependencies, leave this section empty -# # Format for dependency strings: https://peps.python.org/pep-0508/ -# # dependencies from requirements.txt -# dependencies = [ -# "bitarray>=2.5.1", -# "numpy>=1.21.2", -# "scipy>=1.11.1", -# ] - -# [project.optional-dependencies] -# tests = [ -# 'coverage>=5.0.3', -# "pandas>=1.3.5", -# "pytest>=7.4.0", -# "scikit-learn>=1.0.1", -# ] - -[project.scripts] -# Command line interface entrypoint scripts -# selector = "selector.__main__:main" - -[project.urls] -# Use PyPI-standard names here -# Homepage -# Documentation -# Changelog -# Issue Tracker -# Source -# Discord server -homepage = "https://github.com/theochem/Selector" -documentation = "https://selector.qcdevs.org/" -repository = "https://github.com/theochem/Selector" - -# Development dependencies -# pip install -e .[lint,test,exe] -# pip install -e .[dev] - -# we can only provide one optional dependencies or dynamic dependencies -# we can't provide both, which leads to errors -# [project.optional-dependencies] -# lint = [ -# # ruff linter checks for issues and potential bugs -# "ruff", -# # checks for unused code -# # "vulture", -# # # required for codespell to parse pyproject.toml -# # "tomli", -# # # validation of pyproject.toml -# # "validate-pyproject[all]", -# # automatic sorting of imports -# "isort", -# # # automatic code formatting to follow a consistent style -# # "black", -# ] - -# test = [ -# # Handles most of the testing work, including execution -# # Docs: https://docs.pytest.org/en/stable/contents.html -# "pytest>=7.4.0", -# # required by pytest -# "hypothesis", -# # "Coverage" is how much of the code is actually run (it's "coverage") -# # Generates coverage reports from test suite runs -# "pytest-cov>=3.0.0", -# "tomli", -# "scikit-learn>=1.0.1", -# # Better parsing of doctests -# "xdoctest", -# # Colors for doctest output -# "Pygments", -# ] - -# exe = [ -# "setuptools", -# "wheel", -# "build", -# "tomli", -# "pyinstaller", -# "staticx;platform_system=='Linux'", -# ] - -# dev = [ -# # https://hynek.me/articles/python-recursive-optional-dependencies/ -# "selector[lint,test,exe]", - -# # # Code quality tools -# # "mypy", - -# # # Improved exception traceback output -# # # https://github.com/qix-/better-exceptions -# # "better_exceptions", - -# # # Analyzing dependencies -# # # install graphviz to generate graphs -# # "graphviz", -# # "pipdeptree", -# ] - -[build-system] -# Minimum requirements for the build system to execute. -requires = ["setuptools>=64", "setuptools-scm>=8", "wheel"] -build-backend = "setuptools.build_meta" - -[tool.setuptools.dynamic] -dependencies = {file = ["requirements.txt"]} -optional-dependencies = {dev = { file = ["requirements_dev.txt"] }} - -[tool.setuptools_scm] -# can be empty if no extra settings are needed, presence enables setuptools-scm - -[tool.setuptools] -# https://setuptools.pypa.io/en/latest/userguide/pyproject_config.html -platforms = ["Linux", "Windows", "MacOS"] -include-package-data = true -# This just means it's safe to zip up the bdist -zip-safe = true - -# Non-code data that should be included in the package source code -# https://setuptools.pypa.io/en/latest/userguide/datafiles.html -[tool.setuptools.package-data] -selector = ["*.xml"] - -# Python modules and packages that are included in the -# distribution package (and therefore become importable) -[tool.setuptools.packages.find] -exclude = ["*/*/tests", "tests_*", "examples", "notebooks"] - - -# PDM example -#[tool.pdm.scripts] -#isort = "isort selector" -#black = "black selector" -#format = {composite = ["isort", "black"]} -#check_isort = "isort --check selector tests" -#check_black = "black --check selector tests" -#vulture = "vulture --min-confidence 100 selector tests" -#ruff = "ruff check selector tests" -#fix = "ruff check --fix selector tests" -#codespell = "codespell --toml ./pyproject.toml" -#lint = {composite = ["vulture", "codespell", "ruff", "check_isort", "check_black"]} - - -#[tool.codespell] -## codespell supports pyproject.toml since version 2.2.2 -## NOTE: the "tomli" package must be installed for this to work -## https://github.com/codespell-project/codespell#using-a-config-file -## NOTE: ignore words for codespell must be lowercase -#check-filenames = "" -#ignore-words-list = "word,another,something" -#skip = "htmlcov,.doctrees,*.pyc,*.class,*.ico,*.out,*.PNG,*.inv,*.png,*.jpg,*.dot" - - -[tool.black] -line-length = 100 -# If you need to exclude directories from being reformatted by black -# force-exclude = ''' -# ( -# somedirname -# | dirname -# | filename\.py -# ) -# ''' - - -[tool.isort] -profile = "black" -known_first_party = ["selector"] -# If you need to exclude files from having their imports sorted -#extend_skip_glob = [ -# "selector/somefile.py", -# "selector/somedir/*", -#] - - -# https://beta.ruff.rs/docs -[tool.ruff] -line-length = 100 -show-source = true - -# Rules: https://beta.ruff.rs/docs/rules -# If you violate a rule, lookup the rule on the Rules page in ruff docs. -# Many rules have links you can click with a explanation of the rule and how to fix it. -# If there isn't a link, go to the project the rule was source from (e.g. flake8-bugbear) -# and review it's docs for the corresponding rule. -# If you're still confused, ask a fellow developer for assistance. -# You can also run "ruff rule " to explain a rule on the command line, without a browser or internet access. -select = [ - "E", # pycodestyle - "F", # Pyflakes - "W", # Warning - "B", # flake8-bugbear - "A", # flake8-builtins - "C4", # flake8-comprehensions - "T10", # flake8-debugger - "EXE", # flake8-executable, - "ISC", # flake8-implicit-str-concat - "G", # flake8-logging-format - "PIE", # flake8-pie - "T20", # flake8-print - "PT", # flake8-pytest-style - "RSE", # flake8-raise - "RET", # flake8-return - "TID", # flake8-tidy-imports - "ARG", # flake8-unused-arguments - "PGH", # pygrep-hooks - "PLC", # Pylint Convention - "PLE", # Pylint Errors - "PLW", # Pylint Warnings - "RUF", # Ruff-specific rules - - # ** Things to potentially enable in the future ** - # DTZ requires all usage of datetime module to have timezone-aware - # objects (so have a tz argument or be explicitly UTC). - # "DTZ", # flake8-datetimez - # "PTH", # flake8-use-pathlib - # "SIM", # flake8-simplify -] - -# Files to exclude from linting -extend-exclude = [ - "*.pyc", - "__pycache__", - "*.egg-info", - ".eggs", - # check point files of jupyter notebooks - "*.ipynb_checkpoints", - ".tox", - ".git", - "build", - "dist", - "docs", - "examples", - "htmlcov", - "notebooks", - ".cache", - "_version.py", -] - -# Linting error codes to ignore -ignore = [ - "F403", # unable to detect undefined names from star imports - "F405", # undefined locals from star imports - "W605", # invalid escape sequence - "A003", # shadowing python builtins - "RET505", # unnecessary 'else' after 'return' statement - "RET504", # Unnecessary variable assignment before return statement - "RET507", # Unnecessary {branch} after continue statement - "PT011", # pytest-raises-too-broad - "PT012", # pytest.raises() block should contain a single simple statement - "PLW0603", # Using the global statement to update is discouraged - "PLW2901", # for loop variable overwritten by assignment target - "G004", # Logging statement uses f-string - "PIE790", # no-unnecessary-pass - "PIE810", # multiple-starts-ends-with - "PGH003", # Use specific rule codes when ignoring type issues - "PLC1901", # compare-to-empty-string -] - -# Linting error codes to ignore on a per-file basis -[tool.ruff.per-file-ignores] -"__init__.py" = ["F401", "E501"] -"selector/somefile.py" = ["E402", "E501"] -"selector/somedir/*" = ["E501"] - - -# Configuration for mypy -# https://mypy.readthedocs.io/en/stable/config_file.html#using-a-pyproject-toml-file -[tool.mypy] -python_version = "3.9" -follow_imports = "skip" -ignore_missing_imports = true -files = "selector" # directory mypy should analyze -# Directories to exclude from mypy's analysis -exclude = [ - "book", -] - - -# Configuration for pytest -# https://docs.pytest.org/en/latest/reference/customize.html#pyproject-toml -[tool.pytest.ini_options] -addopts = [ - # Allow test files to have the same name in different directories. - "--import-mode=importlib", - "--cache-clear", - "--showlocals", - "-v", - "-r a", - "--cov-report=term-missing", - "--cov=selector", -] -# directory containing the tests -testpaths = [ - "selector/measures/tests", - "selector/methods/tests", -] -norecursedirs = [ - ".vscode", - "__pycache__", - "build", -] -# Warnings that should be ignored -filterwarnings = [ - "ignore::DeprecationWarning" -] -# custom markers that can be used using pytest.mark -markers = [ - "slow: lower-importance tests that take an excessive amount of time", -] - - -# Configuration for coverage.py -[tool.coverage.run] -# files or directories to exclude from coverage calculations -omit = [ - 'selector/measures/tests/*', - 'selector/methods/tests/*', -] - - -# Configuration for vulture -[tool.vulture] -# Files or directories to exclude from vulture -# The syntax is a little funky -exclude = [ - "somedir", - "*somefile.py", -] - -# configuration for bandit -[tool.bandit] -exclude_dirs = [ - "selector/measures/tests", - "selector/methods/tests", -] -skips = [ - "B101", # Ignore assert statements - "B311", # Ignore pseudo-random generators - "B404", # Ignore subprocess import - "B603", # Ignore subprocess call - "B607", # Ignore subprocess call -] +# The Selector library provides a set of tools for selecting a +# subset of the dataset and computing diversity. +# +# Copyright (C) 2023 The QC-Devs Community +# +# This file is part of Selector. +# +# Selector is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 +# of the License, or (at your option) any later version. +# +# Selector is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see +# +# -- + + +[project] +# https://packaging.python.org/en/latest/specifications/declaring-project-metadata/ +name = "qc-selector" +description = "Subset selection with maximum diversity." +readme = {file = 'README.md', content-type='text/markdown'} +#requires-python = ">=3.9,<4.0" +requires-python = ">=3.9" +# "LICENSE" is name of the license file, which must be in root of project folder +license = {file = "LICENSE"} +authors = [ + {name = "QC-Devs Community", email = "qcdevs@gmail.com"}, +] +keywords = [ + "subset selection", + "variable selection", + "chemical diversity", + "compound selection", + "maximum diversity", + "chemical library design", + "compound acquisition", +] + +# https://pypi.org/classifiers/ +# Add PyPI classifiers here +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Environment :: Console", + "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", + "Natural Language :: English", + "Operating System :: MacOS", + "Operating System :: Microsoft :: Windows", + "Operating System :: Unix", + "Operating System :: POSIX", + "Operating System :: POSIX :: Linux", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Topic :: Scientific/Engineering", + "Topic :: Sociology", + +] + +# version = "0.0.2b4" +dynamic = [ + "dependencies", + "optional-dependencies", + "version", + ] + +# not using this section now but it's here for reference +# # Required dependencies for install/usage of your package or application +# # If you don't have any dependencies, leave this section empty +# # Format for dependency strings: https://peps.python.org/pep-0508/ +# # dependencies from requirements.txt +# dependencies = [ +# "bitarray>=2.5.1", +# "numpy>=1.21.2", +# "scipy>=1.11.1", +# ] + +# [project.optional-dependencies] +# tests = [ +# 'coverage>=5.0.3', +# "pandas>=1.3.5", +# "pytest>=7.4.0", +# "scikit-learn>=1.0.1", +# ] + +[project.scripts] +# Command line interface entrypoint scripts +# selector = "selector.__main__:main" + +[project.urls] +# Use PyPI-standard names here +# Homepage +# Documentation +# Changelog +# Issue Tracker +# Source +# Discord server +homepage = "https://github.com/theochem/Selector" +documentation = "https://selector.qcdevs.org/" +repository = "https://github.com/theochem/Selector" + +# Development dependencies +# pip install -e .[lint,test,exe] +# pip install -e .[dev] + +# we can only provide one optional dependencies or dynamic dependencies +# we can't provide both, which leads to errors +# [project.optional-dependencies] +# lint = [ +# # ruff linter checks for issues and potential bugs +# "ruff", +# # checks for unused code +# # "vulture", +# # # required for codespell to parse pyproject.toml +# # "tomli", +# # # validation of pyproject.toml +# # "validate-pyproject[all]", +# # automatic sorting of imports +# "isort", +# # # automatic code formatting to follow a consistent style +# # "black", +# ] + +# test = [ +# # Handles most of the testing work, including execution +# # Docs: https://docs.pytest.org/en/stable/contents.html +# "pytest>=7.4.0", +# # required by pytest +# "hypothesis", +# # "Coverage" is how much of the code is actually run (it's "coverage") +# # Generates coverage reports from test suite runs +# "pytest-cov>=3.0.0", +# "tomli", +# "scikit-learn>=1.0.1", +# # Better parsing of doctests +# "xdoctest", +# # Colors for doctest output +# "Pygments", +# ] + +# exe = [ +# "setuptools", +# "wheel", +# "build", +# "tomli", +# "pyinstaller", +# "staticx;platform_system=='Linux'", +# ] + +# dev = [ +# # https://hynek.me/articles/python-recursive-optional-dependencies/ +# "selector[lint,test,exe]", + +# # # Code quality tools +# # "mypy", + +# # # Improved exception traceback output +# # # https://github.com/qix-/better-exceptions +# # "better_exceptions", + +# # # Analyzing dependencies +# # # install graphviz to generate graphs +# # "graphviz", +# # "pipdeptree", +# ] + +[build-system] +# Minimum requirements for the build system to execute. +requires = ["setuptools>=64", "setuptools-scm>=8", "wheel"] +build-backend = "setuptools.build_meta" + +[tool.setuptools.dynamic] +dependencies = {file = ["requirements.txt"]} +optional-dependencies = {dev = { file = ["requirements_dev.txt"] }} + +[tool.setuptools_scm] +# can be empty if no extra settings are needed, presence enables setuptools-scm + +[tool.setuptools] +# https://setuptools.pypa.io/en/latest/userguide/pyproject_config.html +platforms = ["Linux", "Windows", "MacOS"] +include-package-data = true +# This just means it's safe to zip up the bdist +zip-safe = true + +# Non-code data that should be included in the package source code +# https://setuptools.pypa.io/en/latest/userguide/datafiles.html +[tool.setuptools.package-data] +selector = ["*.xml"] + +# Python modules and packages that are included in the +# distribution package (and therefore become importable) +[tool.setuptools.packages.find] +exclude = ["*/*/tests", "tests_*", "examples", "notebooks"] + + +# PDM example +#[tool.pdm.scripts] +#isort = "isort selector" +#black = "black selector" +#format = {composite = ["isort", "black"]} +#check_isort = "isort --check selector tests" +#check_black = "black --check selector tests" +#vulture = "vulture --min-confidence 100 selector tests" +#ruff = "ruff check selector tests" +#fix = "ruff check --fix selector tests" +#codespell = "codespell --toml ./pyproject.toml" +#lint = {composite = ["vulture", "codespell", "ruff", "check_isort", "check_black"]} + + +#[tool.codespell] +## codespell supports pyproject.toml since version 2.2.2 +## NOTE: the "tomli" package must be installed for this to work +## https://github.com/codespell-project/codespell#using-a-config-file +## NOTE: ignore words for codespell must be lowercase +#check-filenames = "" +#ignore-words-list = "word,another,something" +#skip = "htmlcov,.doctrees,*.pyc,*.class,*.ico,*.out,*.PNG,*.inv,*.png,*.jpg,*.dot" + + +[tool.black] +line-length = 100 +# If you need to exclude directories from being reformatted by black +# force-exclude = ''' +# ( +# somedirname +# | dirname +# | filename\.py +# ) +# ''' + + +[tool.isort] +profile = "black" +known_first_party = ["selector"] +# If you need to exclude files from having their imports sorted +#extend_skip_glob = [ +# "selector/somefile.py", +# "selector/somedir/*", +#] + + +# https://beta.ruff.rs/docs +[tool.ruff] +line-length = 100 +show-source = true + +# Rules: https://beta.ruff.rs/docs/rules +# If you violate a rule, lookup the rule on the Rules page in ruff docs. +# Many rules have links you can click with a explanation of the rule and how to fix it. +# If there isn't a link, go to the project the rule was source from (e.g. flake8-bugbear) +# and review it's docs for the corresponding rule. +# If you're still confused, ask a fellow developer for assistance. +# You can also run "ruff rule " to explain a rule on the command line, without a browser or internet access. +select = [ + "E", # pycodestyle + "F", # Pyflakes + "W", # Warning + "B", # flake8-bugbear + "A", # flake8-builtins + "C4", # flake8-comprehensions + "T10", # flake8-debugger + "EXE", # flake8-executable, + "ISC", # flake8-implicit-str-concat + "G", # flake8-logging-format + "PIE", # flake8-pie + "T20", # flake8-print + "PT", # flake8-pytest-style + "RSE", # flake8-raise + "RET", # flake8-return + "TID", # flake8-tidy-imports + "ARG", # flake8-unused-arguments + "PGH", # pygrep-hooks + "PLC", # Pylint Convention + "PLE", # Pylint Errors + "PLW", # Pylint Warnings + "RUF", # Ruff-specific rules + + # ** Things to potentially enable in the future ** + # DTZ requires all usage of datetime module to have timezone-aware + # objects (so have a tz argument or be explicitly UTC). + # "DTZ", # flake8-datetimez + # "PTH", # flake8-use-pathlib + # "SIM", # flake8-simplify +] + +# Files to exclude from linting +extend-exclude = [ + "*.pyc", + "__pycache__", + "*.egg-info", + ".eggs", + # check point files of jupyter notebooks + "*.ipynb_checkpoints", + ".tox", + ".git", + "build", + "dist", + "docs", + "examples", + "htmlcov", + "notebooks", + ".cache", + "_version.py", +] + +# Linting error codes to ignore +ignore = [ + "F403", # unable to detect undefined names from star imports + "F405", # undefined locals from star imports + "W605", # invalid escape sequence + "A003", # shadowing python builtins + "RET505", # unnecessary 'else' after 'return' statement + "RET504", # Unnecessary variable assignment before return statement + "RET507", # Unnecessary {branch} after continue statement + "PT011", # pytest-raises-too-broad + "PT012", # pytest.raises() block should contain a single simple statement + "PLW0603", # Using the global statement to update is discouraged + "PLW2901", # for loop variable overwritten by assignment target + "G004", # Logging statement uses f-string + "PIE790", # no-unnecessary-pass + "PIE810", # multiple-starts-ends-with + "PGH003", # Use specific rule codes when ignoring type issues + "PLC1901", # compare-to-empty-string +] + +# Linting error codes to ignore on a per-file basis +[tool.ruff.per-file-ignores] +"__init__.py" = ["F401", "E501"] +"selector/somefile.py" = ["E402", "E501"] +"selector/somedir/*" = ["E501"] + + +# Configuration for mypy +# https://mypy.readthedocs.io/en/stable/config_file.html#using-a-pyproject-toml-file +[tool.mypy] +python_version = "3.9" +follow_imports = "skip" +ignore_missing_imports = true +files = "selector" # directory mypy should analyze +# Directories to exclude from mypy's analysis +exclude = [ + "book", +] + + +# Configuration for pytest +# https://docs.pytest.org/en/latest/reference/customize.html#pyproject-toml +[tool.pytest.ini_options] +addopts = [ + # Allow test files to have the same name in different directories. + "--import-mode=importlib", + "--cache-clear", + "--showlocals", + "-v", + "-r a", + "--cov-report=term-missing", + "--cov=selector", +] +# directory containing the tests +testpaths = [ + "selector/measures/tests", + "selector/methods/tests", +] +norecursedirs = [ + ".vscode", + "__pycache__", + "build", +] +# Warnings that should be ignored +filterwarnings = [ + "ignore::DeprecationWarning" +] +# custom markers that can be used using pytest.mark +markers = [ + "slow: lower-importance tests that take an excessive amount of time", +] + + +# Configuration for coverage.py +[tool.coverage.run] +# files or directories to exclude from coverage calculations +omit = [ + 'selector/measures/tests/*', + 'selector/methods/tests/*', +] + + +# Configuration for vulture +[tool.vulture] +# Files or directories to exclude from vulture +# The syntax is a little funky +exclude = [ + "somedir", + "*somefile.py", +] + +# configuration for bandit +[tool.bandit] +exclude_dirs = [ + "selector/measures/tests", + "selector/methods/tests", +] +skips = [ + "B101", # Ignore assert statements + "B311", # Ignore pseudo-random generators + "B404", # Ignore subprocess import + "B603", # Ignore subprocess call + "B607", # Ignore subprocess call +] diff --git a/requirements.txt b/requirements.txt index 2e5846e6..18837b02 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ -bitarray>=2.5.1 -numpy>=2.0.0 -scipy>=1.11.1 +bitarray>=2.5.1 +numpy>=2.0.0 +scipy>=1.11.1 diff --git a/requirements_dev.txt b/requirements_dev.txt index 4106a3d4..bb277eda 100644 --- a/requirements_dev.txt +++ b/requirements_dev.txt @@ -1,13 +1,13 @@ -bitarray>=2.5.1 -coverage>=6.3.2 -hypothesis -numpy>=1.21.2 -pre-commit -pytest>=7.4.0 -pytest-cov>=3.0.0 -scikit-learn>=1.0.1 -scipy>=1.11.1 -setuptools>=64.0.0 -tomli -xdoctest -setuptools-scm>=8.0.0 +bitarray>=2.5.1 +coverage>=6.3.2 +hypothesis +numpy>=1.21.2 +pre-commit +pytest>=7.4.0 +pytest-cov>=3.0.0 +scikit-learn>=1.0.1 +scipy>=1.11.1 +setuptools>=64.0.0 +tomli +xdoctest +setuptools-scm>=8.0.0 diff --git a/selector/__init__.py b/selector/__init__.py index 00a9a839..aac5be96 100644 --- a/selector/__init__.py +++ b/selector/__init__.py @@ -1,27 +1,27 @@ -# -*- coding: utf-8 -*- -# -# The Selector is a Python library of algorithms for selecting diverse -# subsets of data for machine-learning. -# -# Copyright (C) 2022-2024 The QC-Devs Community -# -# This file is part of Selector. -# -# Selector is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 -# of the License, or (at your option) any later version. -# -# Selector is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see -# -# -- - -"""Selector Package.""" - -from selector.methods import * +# -*- coding: utf-8 -*- +# +# The Selector is a Python library of algorithms for selecting diverse +# subsets of data for machine-learning. +# +# Copyright (C) 2022-2024 The QC-Devs Community +# +# This file is part of Selector. +# +# Selector is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 +# of the License, or (at your option) any later version. +# +# Selector is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see +# +# -- + +"""Selector Package.""" + +from selector.methods import * diff --git a/selector/measures/__init__.py b/selector/measures/__init__.py index e8247618..82d239c9 100644 --- a/selector/measures/__init__.py +++ b/selector/measures/__init__.py @@ -1,23 +1,23 @@ -# -*- coding: utf-8 -*- -# -# The Selector is a Python library of algorithms for selecting diverse -# subsets of data for machine-learning. -# -# Copyright (C) 2022-2024 The QC-Devs Community -# -# This file is part of Selector. -# -# Selector is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 -# of the License, or (at your option) any later version. -# -# Selector is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see -# -# -- +# -*- coding: utf-8 -*- +# +# The Selector is a Python library of algorithms for selecting diverse +# subsets of data for machine-learning. +# +# Copyright (C) 2022-2024 The QC-Devs Community +# +# This file is part of Selector. +# +# Selector is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 +# of the License, or (at your option) any later version. +# +# Selector is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see +# +# -- diff --git a/selector/measures/converter.py b/selector/measures/converter.py index 3f480b10..6dd807c5 100644 --- a/selector/measures/converter.py +++ b/selector/measures/converter.py @@ -1,416 +1,416 @@ -# -*- coding: utf-8 -*- -# -# The Selector is a Python library of algorithms for selecting diverse -# subsets of data for machine-learning. -# -# Copyright (C) 2022-2024 The QC-Devs Community -# -# This file is part of Selector. -# -# Selector is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 -# of the License, or (at your option) any later version. -# -# Selector is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see -# -# -- -"""Module for converting similarity measures to distance/dissimilarity measures.""" - -from typing import Union - -import numpy as np - -__all__ = [ - "sim_to_dist", - "reverse", - "reciprocal", - "exponential", - "gaussian", - "correlation", - "transition", - "co_occurrence", - "gravity", - "probability", - "covariance", -] - - -def sim_to_dist( - x: Union[int, float, np.ndarray], metric: str, scaling_factor: float = 1.0 -) -> Union[float, np.ndarray]: - """Convert similarity coefficients to distance array. - - Parameters - ---------- - x : float or ndarray - A similarity value as float, or a 1D or 2D array of similarity values. - If 2D, the array is assumed to be symmetric. - metric : str - String or integer specifying which conversion metric to use. - Supported metrics are "reverse", "reciprocal", "exponential", - "gaussian", "membership", "correlation", "transition", "co-occurrence", - "gravity", "confusion", "probability", and "covariance". - scaling_factor : float, optional - Scaling factor for the distance array. Default is 1.0. - - Returns - ------- - dist : float or ndarray - Distance value or array. - """ - # scale the distance matrix - x = x * scaling_factor - - frequency = { - "transition": transition, - "co-occurrence": co_occurrence, - "gravity": gravity, - } - method_dict = { - "reverse": reverse, - "reciprocal": reciprocal, - "exponential": exponential, - "gaussian": gaussian, - "correlation": correlation, - "probability": probability, - "covariance": covariance, - } - - # check if x is a single value - single_value = False - if isinstance(x, (float, int)): - x = np.array([[x]]) - single_value = True - - # check x - if not isinstance(x, np.ndarray): - raise ValueError(f"Argument x should be a numpy array instead of {type(x)}") - # check that x is a valid array - if x.ndim != 1 and x.ndim != 2: - raise ValueError(f"Argument x should either have 1 or 2 dimensions, got {x.ndim}.") - if x.ndim == 1 and metric in ["co-occurrence", "gravity"]: - raise ValueError(f"Argument x should be a 2D array when using the {metric} metric.") - # check if x is symmetric - if x.ndim == 2 and not np.allclose(x, x.T): - raise ValueError("Argument x should be a symmetric array.") - - # call correct metric function - if metric in frequency: - if np.any(x <= 0): - raise ValueError( - "There is a negative or zero value in the input. Please " - "make sure all frequency values are positive." - ) - dist = frequency[metric](x) - elif metric in method_dict: - dist = method_dict[metric](x) - elif metric == "membership" or metric == "confusion": - if np.any(x < 0) or np.any(x > 1): - raise ValueError( - "There is an out of bounds value. Please make " - "sure all input values are between [0, 1]." - ) - dist = 1 - x - # unsupported metric - else: - raise ValueError(f"{metric} is an unsupported metric.") - - # convert back to float if input was single value - if single_value: - dist = dist.item((0, 0)) - - return dist - - -def reverse(x: np.ndarray) -> np.ndarray: - r"""Calculate distance array from similarity using the reverse method. - - .. math:: - \delta_{ij} = min(s_{ij}) + max(s_{ij}) - s_{ij} - - where :math:`\delta_{ij}` is the distance between points :math:`i` - and :math:`j`, :math:`s_{ij}` is their similarity coefficient, - and :math:`max` and :math:`min` are the maximum and minimum - values across the entire similarity array. - - Parameters - ----------- - x : ndarray - Similarity array. - - Returns - ------- - dist : ndarray - Distance array. - - """ - dist = np.max(x) + np.min(x) - x - return dist - - -def reciprocal(x: np.ndarray) -> np.ndarray: - r"""Calculate distance array from similarity using the reciprocal method. - - .. math:: - \delta_{ij} = \frac{1}{s_{ij}} - - where :math:`\delta_{ij}` is the distance between points :math:`i` - and :math:`j`, and :math:`s_{ij}` is their similarity coefficient. - - Parameters - ----------- - x : ndarray - Similarity array. - - Returns - ------- - dist : ndarray - Distance array. - """ - - if np.any(x <= 0): - raise ValueError( - "There is an out of bounds value. Please make " "sure all similarities are positive." - ) - return 1 / x - - -def exponential(x: np.ndarray) -> np.ndarray: - r"""Calculate distance matrix from similarity using the exponential method. - - .. math:: - \delta_{ij} = -\ln{\frac{s_{ij}}{max(s_{ij})}} - - where :math:`\delta_{ij}` is the distance between points :math:`i` - and :math:`j`, and :math:`s_{ij}` is their similarity coefficient. - - Parameters - ----------- - x : ndarray - Similarity array. - - Returns - ------- - dist : ndarray - Distance array. - - """ - max_sim = np.max(x) - if max_sim == 0: - raise ValueError("Maximum similarity in `x` is 0. Distance cannot be computed.") - dist = -np.log(x / max_sim) - return dist - - -def gaussian(x: np.ndarray) -> np.ndarray: - r"""Calculate distance matrix from similarity using the Gaussian method. - - .. math:: - \delta_{ij} = \sqrt{-\ln{\frac{s_{ij}}{max(s_{ij})}}} - - where :math:`\delta_{ij}` is the distance between points :math:`i` - and :math:`j`, and :math:`s_{ij}` is their similarity coefficient. - - Parameters - ----------- - x : ndarray - Similarity array. - - Returns - ------- - dist : ndarray - Distance array. - - """ - max_sim = np.max(x) - if max_sim == 0: - raise ValueError("Maximum similarity in `x` is 0. Distance cannot be computed.") - y = x / max_sim - dist = np.sqrt(-np.log(y)) - return dist - - -def correlation(x: np.ndarray) -> np.ndarray: - r"""Calculate distance array from correlation array. - - .. math:: - \delta_{ij} = \sqrt{1 - r_{ij}} - - where :math:`\delta_{ij}` is the distance between points :math:`i` - and :math:`j`, and :math:`r_{ij}` is their correlation. - - Parameters - ----------- - x : ndarray - Correlation array. - - Returns - ------- - dist : ndarray - Distance array. - - """ - if np.any(x < -1) or np.any(x > 1): - raise ValueError( - "There is an out of bounds value. Please make " - "sure all correlations are between [-1, 1]." - ) - dist = np.sqrt(1 - x) - return dist - - -def transition(x: np.ndarray) -> np.ndarray: - r"""Calculate distance array from frequency using the transition method. - - .. math:: - \delta_{ij} = \frac{1}{\sqrt{f_{ij}}} - - where :math:`\delta_{ij}` is the distance between points :math:`i` - and :math:`j`, and :math:`f_{ij}` is their frequency. - - Parameters - ----------- - x : ndarray - Symmetric frequency array. - - Returns - ------- - dist : ndarray - Distance array. - - """ - dist = 1 / np.sqrt(x) - return dist - - -def co_occurrence(x: np.ndarray) -> np.ndarray: - r"""Calculate distance array from frequency using the co-occurrence method. - - .. math:: - \delta_{ij} = \left(1 + \frac{f_{ij}\sum_{i,j}{f_{ij}}}{\sum_{i}{f_{ij}}\sum_{j}{f_{ij}}} \right)^{-1} - - where :math:`\delta_{ij}` is the distance between points :math:`i` - and :math:`j`, and :math:`f_{ij}` is their frequency. - - Parameters - ----------- - x : ndarray - Frequency array. - - Returns - ------- - dist : ndarray - Co-occurrence array. - - """ - # compute sums along each axis - i = np.sum(x, axis=0, keepdims=True) - j = np.sum(x, axis=1, keepdims=True) - # multiply sums to scalar value - bottom = np.dot(i, j) - # multiply each element by the sum of entire array - top = x * np.sum(x) - # evaluate function as a whole - dist = (1 + (top / bottom)) ** -1 - return dist - - -def gravity(x: np.ndarray) -> np.ndarray: - r"""Calculate distance array from frequency using the gravity method. - - .. math:: - \delta_{ij} = \sqrt{\frac{\sum_{i}{f_{ij}}\sum_{j}{f_{ij}}} - {f_{ij}\sum_{i,j}{f_{ij}}}} - - where :math:`\delta_{ij}` is the distance between points :math:`i` - and :math:`j`, and :math:`f_{ij}` is their frequency. - - Parameters - ----------- - x : ndarray - Symmetric frequency array. - - Returns - ------- - dist : ndarray - Symmetric gravity array. - - """ - # compute sums along each axis - i = np.sum(x, axis=0, keepdims=True) - j = np.sum(x, axis=1, keepdims=True) - # multiply sums to scalar value - top = np.dot(i, j) - # multiply each element by the sum of entire array - bottom = x * np.sum(x) - # take square root of the fraction - dist = np.sqrt(top / bottom) - return dist - - -def probability(x: np.ndarray) -> np.ndarray: - r"""Calculate distance array from probability array. - - .. math:: - \delta_{ij} = \sqrt{-\ln{\frac{s_{ij}}{max(s_{ij})}}} - - where :math:`\delta_{ij}` is the distance between points :math:`i` - and :math:`j`, and :math:`p_{ij}` is their probablity. - - Parameters - ----------- - x : ndarray - Symmetric probability array. - - Returns - ------- - dist : ndarray - Distance array. - - """ - if np.any(x <= 0) or np.any(x > 1): - raise ValueError( - "There is an out of bounds value. Please make " - "sure all probabilities are between (0, 1]." - ) - y = np.arcsin(x) - dist = 1 / np.sqrt(y) - return dist - - -def covariance(x: np.ndarray) -> np.ndarray: - r"""Calculate distance array from similarity using the covariance method. - - .. math:: - \delta_{ij} = \sqrt{s_{ii}+s_{jj}-2s_{ij}} - - where :math:`\delta_{ij}` is the distance between points :math:`i` - and :math:`j`, :math:`s_{ii}` and :math:`s_{jj}` are the variances - of feature :math:`i` and feature :math:`j`, and :math:`s_{ij}` - is the covariance between the two features. - - Parameters - ----------- - x : ndarray - Covariance array. - - Returns - ------- - dist : ndarray - Distance array. - - """ - variance = np.diag(x).reshape([x.shape[0], 1]) * np.ones([1, x.shape[0]]) - if np.any(variance < 0): - raise ValueError("Variance of a single variable cannot be negative.") - - dist = variance + variance.T - 2 * x - dist = np.sqrt(dist) - return dist +# -*- coding: utf-8 -*- +# +# The Selector is a Python library of algorithms for selecting diverse +# subsets of data for machine-learning. +# +# Copyright (C) 2022-2024 The QC-Devs Community +# +# This file is part of Selector. +# +# Selector is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 +# of the License, or (at your option) any later version. +# +# Selector is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see +# +# -- +"""Module for converting similarity measures to distance/dissimilarity measures.""" + +from typing import Union + +import numpy as np + +__all__ = [ + "sim_to_dist", + "reverse", + "reciprocal", + "exponential", + "gaussian", + "correlation", + "transition", + "co_occurrence", + "gravity", + "probability", + "covariance", +] + + +def sim_to_dist( + x: Union[int, float, np.ndarray], metric: str, scaling_factor: float = 1.0 +) -> Union[float, np.ndarray]: + """Convert similarity coefficients to distance array. + + Parameters + ---------- + x : float or ndarray + A similarity value as float, or a 1D or 2D array of similarity values. + If 2D, the array is assumed to be symmetric. + metric : str + String or integer specifying which conversion metric to use. + Supported metrics are "reverse", "reciprocal", "exponential", + "gaussian", "membership", "correlation", "transition", "co-occurrence", + "gravity", "confusion", "probability", and "covariance". + scaling_factor : float, optional + Scaling factor for the distance array. Default is 1.0. + + Returns + ------- + dist : float or ndarray + Distance value or array. + """ + # scale the distance matrix + x = x * scaling_factor + + frequency = { + "transition": transition, + "co-occurrence": co_occurrence, + "gravity": gravity, + } + method_dict = { + "reverse": reverse, + "reciprocal": reciprocal, + "exponential": exponential, + "gaussian": gaussian, + "correlation": correlation, + "probability": probability, + "covariance": covariance, + } + + # check if x is a single value + single_value = False + if isinstance(x, (float, int)): + x = np.array([[x]]) + single_value = True + + # check x + if not isinstance(x, np.ndarray): + raise ValueError(f"Argument x should be a numpy array instead of {type(x)}") + # check that x is a valid array + if x.ndim != 1 and x.ndim != 2: + raise ValueError(f"Argument x should either have 1 or 2 dimensions, got {x.ndim}.") + if x.ndim == 1 and metric in ["co-occurrence", "gravity"]: + raise ValueError(f"Argument x should be a 2D array when using the {metric} metric.") + # check if x is symmetric + if x.ndim == 2 and not np.allclose(x, x.T): + raise ValueError("Argument x should be a symmetric array.") + + # call correct metric function + if metric in frequency: + if np.any(x <= 0): + raise ValueError( + "There is a negative or zero value in the input. Please " + "make sure all frequency values are positive." + ) + dist = frequency[metric](x) + elif metric in method_dict: + dist = method_dict[metric](x) + elif metric == "membership" or metric == "confusion": + if np.any(x < 0) or np.any(x > 1): + raise ValueError( + "There is an out of bounds value. Please make " + "sure all input values are between [0, 1]." + ) + dist = 1 - x + # unsupported metric + else: + raise ValueError(f"{metric} is an unsupported metric.") + + # convert back to float if input was single value + if single_value: + dist = dist.item((0, 0)) + + return dist + + +def reverse(x: np.ndarray) -> np.ndarray: + r"""Calculate distance array from similarity using the reverse method. + + .. math:: + \delta_{ij} = min(s_{ij}) + max(s_{ij}) - s_{ij} + + where :math:`\delta_{ij}` is the distance between points :math:`i` + and :math:`j`, :math:`s_{ij}` is their similarity coefficient, + and :math:`max` and :math:`min` are the maximum and minimum + values across the entire similarity array. + + Parameters + ----------- + x : ndarray + Similarity array. + + Returns + ------- + dist : ndarray + Distance array. + + """ + dist = np.max(x) + np.min(x) - x + return dist + + +def reciprocal(x: np.ndarray) -> np.ndarray: + r"""Calculate distance array from similarity using the reciprocal method. + + .. math:: + \delta_{ij} = \frac{1}{s_{ij}} + + where :math:`\delta_{ij}` is the distance between points :math:`i` + and :math:`j`, and :math:`s_{ij}` is their similarity coefficient. + + Parameters + ----------- + x : ndarray + Similarity array. + + Returns + ------- + dist : ndarray + Distance array. + """ + + if np.any(x <= 0): + raise ValueError( + "There is an out of bounds value. Please make " "sure all similarities are positive." + ) + return 1 / x + + +def exponential(x: np.ndarray) -> np.ndarray: + r"""Calculate distance matrix from similarity using the exponential method. + + .. math:: + \delta_{ij} = -\ln{\frac{s_{ij}}{max(s_{ij})}} + + where :math:`\delta_{ij}` is the distance between points :math:`i` + and :math:`j`, and :math:`s_{ij}` is their similarity coefficient. + + Parameters + ----------- + x : ndarray + Similarity array. + + Returns + ------- + dist : ndarray + Distance array. + + """ + max_sim = np.max(x) + if max_sim == 0: + raise ValueError("Maximum similarity in `x` is 0. Distance cannot be computed.") + dist = -np.log(x / max_sim) + return dist + + +def gaussian(x: np.ndarray) -> np.ndarray: + r"""Calculate distance matrix from similarity using the Gaussian method. + + .. math:: + \delta_{ij} = \sqrt{-\ln{\frac{s_{ij}}{max(s_{ij})}}} + + where :math:`\delta_{ij}` is the distance between points :math:`i` + and :math:`j`, and :math:`s_{ij}` is their similarity coefficient. + + Parameters + ----------- + x : ndarray + Similarity array. + + Returns + ------- + dist : ndarray + Distance array. + + """ + max_sim = np.max(x) + if max_sim == 0: + raise ValueError("Maximum similarity in `x` is 0. Distance cannot be computed.") + y = x / max_sim + dist = np.sqrt(-np.log(y)) + return dist + + +def correlation(x: np.ndarray) -> np.ndarray: + r"""Calculate distance array from correlation array. + + .. math:: + \delta_{ij} = \sqrt{1 - r_{ij}} + + where :math:`\delta_{ij}` is the distance between points :math:`i` + and :math:`j`, and :math:`r_{ij}` is their correlation. + + Parameters + ----------- + x : ndarray + Correlation array. + + Returns + ------- + dist : ndarray + Distance array. + + """ + if np.any(x < -1) or np.any(x > 1): + raise ValueError( + "There is an out of bounds value. Please make " + "sure all correlations are between [-1, 1]." + ) + dist = np.sqrt(1 - x) + return dist + + +def transition(x: np.ndarray) -> np.ndarray: + r"""Calculate distance array from frequency using the transition method. + + .. math:: + \delta_{ij} = \frac{1}{\sqrt{f_{ij}}} + + where :math:`\delta_{ij}` is the distance between points :math:`i` + and :math:`j`, and :math:`f_{ij}` is their frequency. + + Parameters + ----------- + x : ndarray + Symmetric frequency array. + + Returns + ------- + dist : ndarray + Distance array. + + """ + dist = 1 / np.sqrt(x) + return dist + + +def co_occurrence(x: np.ndarray) -> np.ndarray: + r"""Calculate distance array from frequency using the co-occurrence method. + + .. math:: + \delta_{ij} = \left(1 + \frac{f_{ij}\sum_{i,j}{f_{ij}}}{\sum_{i}{f_{ij}}\sum_{j}{f_{ij}}} \right)^{-1} + + where :math:`\delta_{ij}` is the distance between points :math:`i` + and :math:`j`, and :math:`f_{ij}` is their frequency. + + Parameters + ----------- + x : ndarray + Frequency array. + + Returns + ------- + dist : ndarray + Co-occurrence array. + + """ + # compute sums along each axis + i = np.sum(x, axis=0, keepdims=True) + j = np.sum(x, axis=1, keepdims=True) + # multiply sums to scalar value + bottom = np.dot(i, j) + # multiply each element by the sum of entire array + top = x * np.sum(x) + # evaluate function as a whole + dist = (1 + (top / bottom)) ** -1 + return dist + + +def gravity(x: np.ndarray) -> np.ndarray: + r"""Calculate distance array from frequency using the gravity method. + + .. math:: + \delta_{ij} = \sqrt{\frac{\sum_{i}{f_{ij}}\sum_{j}{f_{ij}}} + {f_{ij}\sum_{i,j}{f_{ij}}}} + + where :math:`\delta_{ij}` is the distance between points :math:`i` + and :math:`j`, and :math:`f_{ij}` is their frequency. + + Parameters + ----------- + x : ndarray + Symmetric frequency array. + + Returns + ------- + dist : ndarray + Symmetric gravity array. + + """ + # compute sums along each axis + i = np.sum(x, axis=0, keepdims=True) + j = np.sum(x, axis=1, keepdims=True) + # multiply sums to scalar value + top = np.dot(i, j) + # multiply each element by the sum of entire array + bottom = x * np.sum(x) + # take square root of the fraction + dist = np.sqrt(top / bottom) + return dist + + +def probability(x: np.ndarray) -> np.ndarray: + r"""Calculate distance array from probability array. + + .. math:: + \delta_{ij} = \sqrt{-\ln{\frac{s_{ij}}{max(s_{ij})}}} + + where :math:`\delta_{ij}` is the distance between points :math:`i` + and :math:`j`, and :math:`p_{ij}` is their probablity. + + Parameters + ----------- + x : ndarray + Symmetric probability array. + + Returns + ------- + dist : ndarray + Distance array. + + """ + if np.any(x <= 0) or np.any(x > 1): + raise ValueError( + "There is an out of bounds value. Please make " + "sure all probabilities are between (0, 1]." + ) + y = np.arcsin(x) + dist = 1 / np.sqrt(y) + return dist + + +def covariance(x: np.ndarray) -> np.ndarray: + r"""Calculate distance array from similarity using the covariance method. + + .. math:: + \delta_{ij} = \sqrt{s_{ii}+s_{jj}-2s_{ij}} + + where :math:`\delta_{ij}` is the distance between points :math:`i` + and :math:`j`, :math:`s_{ii}` and :math:`s_{jj}` are the variances + of feature :math:`i` and feature :math:`j`, and :math:`s_{ij}` + is the covariance between the two features. + + Parameters + ----------- + x : ndarray + Covariance array. + + Returns + ------- + dist : ndarray + Distance array. + + """ + variance = np.diag(x).reshape([x.shape[0], 1]) * np.ones([1, x.shape[0]]) + if np.any(variance < 0): + raise ValueError("Variance of a single variable cannot be negative.") + + dist = variance + variance.T - 2 * x + dist = np.sqrt(dist) + return dist diff --git a/selector/measures/diversity.py b/selector/measures/diversity.py index 8a8c89bf..c83962a0 100644 --- a/selector/measures/diversity.py +++ b/selector/measures/diversity.py @@ -1,561 +1,561 @@ -# -*- coding: utf-8 -*- -# -# The Selector is a Python library of algorithms for selecting diverse -# subsets of data for machine-learning. -# -# Copyright (C) 2022-2024 The QC-Devs Community -# -# This file is part of Selector. -# -# Selector is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 -# of the License, or (at your option) any later version. -# -# Selector is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see -# -# -- - -"""Subset diversity calculation module.""" - -import warnings - -import numpy as np - -from selector.measures.similarity import tanimoto - -__all__ = [ - "compute_diversity", - "logdet", - "shannon_entropy", - "explicit_diversity_index", - "wdud", - "hypersphere_overlap_of_subset", - "gini_coefficient", - "nearest_average_tanimoto", -] - - -def compute_diversity( - feature_subset: np.array, - div_type: str = "shannon_entropy", - normalize: bool = False, - truncation: bool = False, - features: np.array = None, - cs: int = None, -) -> float: - """Compute diversity metrics. - - Parameters - ---------- - feature_subset : np.ndarray - Feature matrix. - div_type : str, optional - Method of calculation diversity for a given molecule set, which - includes "logdet", "shannon_entropy", "wdud", - "gini_coefficient" "hypersphere_overlap", and - "explicit_diversity_index". - The default is "shannon_entropy". - normalize : bool, optional - Normalize the entropy to [0, 1]. Default is "False". - truncation : bool, optional - Use the truncated Shannon entropy. Default is "False". - features : np.ndarray, optional - Feature matrix of entire molecule library, used only if - calculating `hypersphere_overlap_of_subset`. Default is "None". - cs : int, optional - Number of common substructures in molecular compound dataset. - Used only if calculating `explicit_diversity_index`. Default is "None". - - - Returns - ------- - float, computed diversity. - - """ - func_dict = { - "logdet": logdet, - "wdud": wdud, - "gini_coefficient": gini_coefficient, - } - - if div_type in func_dict: - return func_dict[div_type](feature_subset) - - # hypersphere overlap of subset - elif div_type == "hypersphere_overlap": - if features is None: - raise ValueError( - "Please input a feature matrix of the entire " - "dataset when calculating hypersphere overlap." - ) - return hypersphere_overlap_of_subset(features, feature_subset) - - elif div_type == "shannon_entropy": - return shannon_entropy(feature_subset, normalize=normalize, truncation=truncation) - - elif div_type == "explicit_diversity_index": - if cs is None: - raise ValueError( - "Attribute `cs` is missing. " - "Please input `cs` value to use explicit_diversity_index." - ) - elif cs == 0: - raise ValueError("Divide by zero error: Attribute `cs` cannot be 0.") - return explicit_diversity_index(feature_subset, cs) - else: - raise ValueError(f"Diversity type {div_type} not supported.") - - -def logdet(x: np.ndarray) -> float: - r"""Compute the log determinant function. - - Given a :math:`n_s \times n_f` feature matrix :math:`x`, where :math:`n_s` is the number of - samples and :math:`n_f` is the number of features, the log determinant function is defined as: - - .. math: - F_\text{logdet} = \log{\left(\det{\left(\mathbf{x}\mathbf{x}^T + \mathbf{I}\right)}\right)} - - where the :math:`I` is the :math:`n_s \times n_s` identity matrix. - Higher values of :math:`F_\text{logdet}` mean more diversity. - - Parameters - ---------- - x: ndarray of shape (n_samples, n_features) - Feature matrix of `n_samples` samples in `n_features` dimensional feature space, - - Returns - ------- - f_logdet: float - The volume of parallelotope spanned by the matrix. - - Notes - ----- - The log-determinant function is based on the formula in Nakamura, T., Sci Rep 2022. - Please note that we used the - natural logrithim to avoid the numerical stability issues, - https://github.com/theochem/Selector/issues/229. - - References - ---------- - Nakamura, T., Sakaue, S., Fujii, K., Harabuchi, Y., Maeda, S., and Iwata, S.., Selecting - molecules with diverse structures and properties by maximizing submodular functions of - descriptors learned with graph neural networks. Scientific Reports 12, 2022. - - """ - mid = np.dot(x, np.transpose(x)) + np.identity(x.shape[0]) - logdet_mid = np.linalg.slogdet(mid) - f_logdet = logdet_mid.sign * logdet_mid.logabsdet - return f_logdet - - -def shannon_entropy(x: np.ndarray, normalize=True, truncation=False) -> float: - r"""Compute the shannon entropy of a binary matrix. - - Higher values mean more diversity. - - Parameters - ---------- - x : ndarray - Bit-string matrix. - normalize : bool, optional - Normalize the entropy to [0, 1]. Default=True. - truncation : bool, optional - Use the truncated Shannon entropy by only counting the contributions of one-bits. - Default=False. - - Returns - ------- - float : - The shannon entropy of the matrix. - - Notes - ----- - Suppose we have :math:`m` compounds and each compound has :math:`n` bits binary fingerprints. - The binary matrix (feature matrix) is :math:`\mathbf{x} \in m \times n`, where each - row is a compound and each column contains the :math:`n`-bit binary fingerprint. - The equation for Shannon entropy is given by [1]_ and [3]_, - - .. math:: - H = \sum_i^m \left[ - p_i \log_2{p_i } - (1 - p_i)\log_2(1 - p_i) \right] - - where :math:`p_i` represents the relative frequency of `1` bits at the fingerprint position - :math:`i`. When :math:`p_i = 0` or :math:`p_i = 1`, the :math:`SE_i` is zero. - When `completeness` is True, the entropy is calculated as in [2]_ instead - - .. math:: - H = \sum_i^m \left[ - p_i \log_2{p_i } \right] - - When `normalize` is True, the entropy is normalized by a scaling factor so that the entropy is in the range of - [0, 1], [2]_ - - .. math:: - H = \frac{ \sum_i^m \left[ - p_i \log_2{p_i } - (1 - p_i)\log_2(1 - p_i) \right]} - {n \log_2{2} / 2} - - But please note, when `completeness` is False and `normalize` is True, the formula has not been - used in any literature. It is just a simple normalization of the entropy and the user can use it at their own risk. - - References - ---------- - .. [1] Wang, Y., Geppert, H., & Bajorath, J. (2009). Shannon entropy-based fingerprint similarity - search strategy. Journal of Chemical Information and Modeling, 49(7), 1687-1691. - .. [2] Leguy, J., Glavatskikh, M., Cauchy, T., & Da Mota, B. (2021). Scalable estimator of the - diversity for de novo molecular generation resulting in a more robust QM dataset (OD9) and a - more efficient molecular optimization. Journal of Cheminformatics, 13(1), 1-17. - .. [3] Weidlich, I. E., & Filippov, I. V. (2016). Using the Gini coefficient to measure the - chemical diversity of small molecule libraries. Journal of Computational Chemistry, 37(22), 2091-2097. - - """ - # check if matrix is binary - if np.count_nonzero((x != 0) & (x != 1)) != 0: - raise ValueError("Attribute `x` should have binary values.") - - p_i_arr = np.sum(x, axis=0) / x.shape[0] - h_x = 0 - - for p_i in p_i_arr: - if p_i == 0 or p_i == 1: - # p_i = 0 - se_i = 0 - else: - if truncation: - # from https://jcheminf.biomedcentral.com/articles/10.1186/s13321-021-00554-8 - se_i = -p_i * np.log2(p_i) - else: - # from https://pubs.acs.org/doi/10.1021/ci900159f - se_i = -p_i * np.log2(p_i) - (1 - p_i) * np.log2(1 - p_i) - - h_x += se_i - - if normalize: - if truncation: - warnings.warn( - "Computing the normalized Shannon entropy only counting the on-bits has not been reported in " - "literature. The user can use it at their own risk." - ) - - h_x /= x.shape[1] * np.log2(2) / 2 - - return h_x - - -# todo: add tests for edi -def explicit_diversity_index( - x: np.ndarray, - cs: int, -) -> float: - """Compute the explicit diversity index. - - Parameters - ---------- - x: ndarray of shape (n_samples, n_features) - Feature matrix of `n_samples` samples in `n_features` dimensional feature space. - cs : int - Number of common substructures in the compound set. - - Returns - ------- - edi_scaled : float - Explicit diversity index. - - Notes - ----- - This method hasn't been tested. - - This method is used only for datasets of molecular compounds. - - Papp, Á., Gulyás-Forró, A., Gulyás, Z., Dormán, G., Ürge, L., - and Darvas, F.. (2006) Explicit Diversity Index (EDI): - A Novel Measure for Assessing the Diversity of Compound Databases. - Journal of Chemical Information and Modeling 46, 1898-1904. - """ - nc = len(x) - sdi = (1 - nearest_average_tanimoto(x)) / (0.8047 - (0.065 * (np.log(nc)))) - cr = -1 * np.log10(nc / (cs**2)) - edi = (sdi + cr) * 0.7071067811865476 - edi_scaled = ((np.tanh(edi / 3) + 1) / 2) * 100 - return edi_scaled - - -def wdud(x: np.ndarray) -> float: - r"""Compute the Wasserstein Distance to Uniform Distribution(WDUD). - - The equation for the Wasserstein Distance for a single feature to uniform distribution is - - .. math:: - WDUD(x) = \int_{0}^{1} |U(x) - V(x)|dx - - where the feature is normalized to [0, 1], :math:`U(x)=x` is the cumulative distribution - of the uniform distribution on [0, 1], and :math:`V(x) = \sum_{y <= x}1 / N` is the discrete - distribution of the values of the feature in :math:`x`, where :math:`y` is the ith feature. This - integral is calculated iteratively between :math:`y_i` and :math:`y_{i+1}`, using trapezoidal method. - - Lower values of the WDUD mean more diversity because the features of the selected set are - more evenly distributed over the range of feature values. - - Parameters - ---------- - x: ndarray of shape (n_samples, n_features) - Feature matrix of `n_samples` samples in `n_features` dimensional feature space. - - Returns - ------- - float : - The mean of the WDUD of each feature over all samples. - - Notes - ----- - Nakamura, T., Sakaue, S., Fujii, K., Harabuchi, Y., Maeda, S., and Iwata, S.. (2022) - Selecting molecules with diverse structures and properties by maximizing - submodular functions of descriptors learned with graph neural networks. - Scientific Reports 12. - - """ - if x.ndim != 2: - raise ValueError(f"The number of dimensions {x.ndim} should be two.") - - # find the range of each feature - col_diff = np.ptp(x, axis=0) - # Normalization of each feature to [0, 1] - if np.any(np.abs(col_diff) < 1e-30): - # warning if some feature columns are constant - warnings.warn( - "Some of the features are constant which will cause the normalization to fail. " - "Now removing them." - ) - if np.all(col_diff < 1.0e-30): - raise ValueError( - "Unfortunately, all the features are constants and wdud cannot be calculated." - ) - else: - # remove the constant feature columns - mask = np.ptp(x, axis=0) > 1e-30 - x = x[:, mask] - x_norm = (x - np.min(x, axis=0)) / np.ptp(x, axis=0) - - # min_max normalization: - n_samples, n_features = x_norm.shape - ans = [] # store the Wasserstein distance for each feature - for i in range(0, n_features): - wdu = 0.0 - y = np.sort(x_norm[:, i]) - # Round to the sixth decimal place and count number of unique elements - # to construct an accurate cumulative discrete distribution func \sum_{x <= y_{i + 1}} 1/k - y, counts = np.unique(np.round(x_norm[:, i], decimals=6), return_counts=True) - p = 0 - # Ignore 0 and because v_min= 0 - for j in range(1, len(counts)): - # integral from y_{i - 1} to y_{i} of |x - \sum_{x <= y_{i}} 1/k| dx - yi1 = y[j - 1] - yi = y[j] - # Make a grid from yi1 to yi - grid = np.linspace(yi1, yi, num=1000, endpoint=True) - # Evaluate the integrand |x - \sum_{x <= y_{i + 1}} 1/k| - p += counts[j - 1] - integrand = np.abs(grid - p / n_samples) - # Integrate using np.trapezoid - wdu += np.trapezoid(y=integrand, x=grid) - ans.append(wdu) - return np.average(ans) - - -def hypersphere_overlap_of_subset(x: np.ndarray, x_subset: np.array) -> float: - r"""Compute the overlap of subset with hyper-spheres around each point - - The edge penalty is also included, which disregards areas - outside of the boundary of the full feature space/library. - This is calculated as: - - .. math:: - g(S) = \sum_{i < j}^k O(i, j) + \sum^k_m E(m) - - where :math:`i, j` is over the subset of samples, e.g. molecules, - :math:`O(i, j)` is the approximate overlap between hyperspheres, - :math:`k` is the number of features and :math:`E` - is the edge penalty of a sample. - - Lower values mean more diversity. - - Parameters - ---------- - x : ndarray - Feature matrix of all samples. - x_subset : ndarray - Feature matrix of selected subset of samples. - - Returns - ------- - float : - The approximate overlapping volume of hyperspheres - drawn around the selected points/samples. - - Notes - ----- - The hypersphere overlap volume is calculated using an approximation formula from Agrafiotis (1997). - - Agrafiotis, D. K.. (1997) Stochastic Algorithms for Maximizing Molecular Diversity. - Journal of Chemical Information and Computer Sciences 37, 841-851. - """ - # check if x is binary matrix or not - if np.array_equal(x, x.astype(bool)): - raise ValueError( - "Input matrix cannot be binary because the diversity measurement is designed for continuous orthogonal features." - ) - - # Find the maximum and minimum over each feature across all samples. - max_x = np.max(x, axis=0) - min_x = np.min(x, axis=0) - - if np.all(np.abs(max_x - min_x) < 1e-30): - raise ValueError("All of the features are redundant which causes normalization to fail.") - - # Remove redundant features - non_red_feat = np.abs(max_x - min_x) > 1e-30 - x = x[:, non_red_feat] - x_subset = x_subset[:, non_red_feat] - max_x = max_x[non_red_feat] - min_x = min_x[non_red_feat] - - d = len(x_subset[0]) - k = len(x_subset[:, 0]) - - # normalization of each feature to [0, 1] - x_norm = (x_subset - min_x) / (max_x - min_x) - - # r_o = hypersphere radius - r_o = d * np.sqrt(1 / k) - if r_o > 0.5: - warnings.warn("The number of samples should be much larger" " than the number of features.") - g_s = 0 - edge = 0 - - # lambda parameter controls edge penalty - lam = (d - 1.0) / d - # calculate overlap volume - for i in range(0, (k - 1)): - for j in range((i + 1), k): - dist = np.linalg.norm(x_norm[i] - x_norm[j]) - # Overlap penalty - if dist <= (2 * r_o): - with np.errstate(divide="ignore"): - # min(100) ignores the inf case with divide by zero - g_s += min(100, 2 * (r_o / dist) - 1) - # Edge penalty: lambda (1 - \sum^d_j e_{ij} / (dr_0) - edge_pen = 0.0 - for j_dim in range(0, d): - # calculate dist to closest boundary in jth coordinate, - # with max value = 1, min value = 0 - dist_max = np.abs(1 - x_norm[i, j_dim]) - dist_min = x_norm[i, j_dim] - dist = min(dist_min, dist_max) - # truncate distance at r_o - if dist > r_o: - dist = r_o - edge_pen += dist - edge_pen /= d * r_o - edge_pen = lam * (1.0 - edge_pen) - edge += edge_pen - g_s += edge - return g_s - - -def gini_coefficient(x: np.ndarray): - r""" - Gini coefficient of bit-wise fingerprints of a database of molecules. - - Measures the chemical diversity of a database of molecules defined by - the following formula: - - .. math:: - G = \frac{2 \sum_{i=1}^L i ||y_i||_1 }{N \sum_{i=1}^L ||y_i||_1} - \frac{L+1}{L}, - - where :math:`y_i \in \{0, 1\}^N` is a vector of zero and ones of length the - number of molecules :math:`N` of the `i`th feature, and :math:`L` is the feature length. - - Lower values mean more diversity. - - Parameters - ---------- - x : ndarray(N, L) - Molecule features in L bits with N molecules. - - Returns - ------- - float : - Gini coefficient in the range [0,1]. - - References - ---------- - Weidlich, Iwona E., and Igor V. Filippov. "Using the gini coefficient to measure the - chemical diversity of small‐molecule libraries." (2016): 2091-2097. - - """ - # Check that `x` is a bit-wise fingerprint. - if np.count_nonzero((x != 0) & (x != 1)) != 0: - raise ValueError("Attribute `x` should have binary values.") - if x.ndim != 2: - raise ValueError(f"Attribute `x` should have dimension two rather than {x.ndim}.") - - num_features = x.shape[1] - # Take the bit-count of each column/molecule. - bit_count = np.sum(x, axis=0) - - # Sort the bit-count since Gini coefficients relies on cumulative distribution. - bit_count = np.sort(bit_count) - - # Mean of denominator - denominator = num_features * np.sum(bit_count) - numerator = np.sum(np.arange(1, num_features + 1) * bit_count) - - return 2.0 * numerator / denominator - (num_features + 1) / num_features - - -def nearest_average_tanimoto(x: np.ndarray) -> float: - """Computes the average tanimoto for nearest molecules. - - Parameters - ---------- - x : ndarray - Feature matrix. - - Returns - ------- - nat : float - Average tanimoto of closest pairs. - - Notes - ----- - This computes the tanimoto coefficient of pairs with the shortest - distances, then returns the average of them. - This calculation is explictly for the explicit diversity index. - - Papp, Á., Gulyás-Forró, A., Gulyás, Z., Dormán, G., Ürge, L., - and Darvas, F.. (2006) Explicit Diversity Index (EDI): - A Novel Measure for Assessing the Diversity of Compound Databases. - Journal of Chemical Information and Modeling 46, 1898-1904. - """ - tani = [] - for idx, _ in enumerate(x): - # arbitrary distance for comparison: - short = 100 - a = 0 - b = 0 - # search for shortest distance point from idx - for jdx, _ in enumerate(x): - dist = np.linalg.norm(x[idx] - x[jdx]) - if dist < short and idx != jdx: - short = dist - a = idx - b = jdx - # calculate tanimoto for each shortest dist pair - tani.append(tanimoto(x[a], x[b])) - # compute average of all shortest tanimoto coeffs - nat = np.average(tani) - return nat +# -*- coding: utf-8 -*- +# +# The Selector is a Python library of algorithms for selecting diverse +# subsets of data for machine-learning. +# +# Copyright (C) 2022-2024 The QC-Devs Community +# +# This file is part of Selector. +# +# Selector is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 +# of the License, or (at your option) any later version. +# +# Selector is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see +# +# -- + +"""Subset diversity calculation module.""" + +import warnings + +import numpy as np + +from selector.measures.similarity import tanimoto + +__all__ = [ + "compute_diversity", + "logdet", + "shannon_entropy", + "explicit_diversity_index", + "wdud", + "hypersphere_overlap_of_subset", + "gini_coefficient", + "nearest_average_tanimoto", +] + + +def compute_diversity( + feature_subset: np.array, + div_type: str = "shannon_entropy", + normalize: bool = False, + truncation: bool = False, + features: np.array = None, + cs: int = None, +) -> float: + """Compute diversity metrics. + + Parameters + ---------- + feature_subset : np.ndarray + Feature matrix. + div_type : str, optional + Method of calculation diversity for a given molecule set, which + includes "logdet", "shannon_entropy", "wdud", + "gini_coefficient" "hypersphere_overlap", and + "explicit_diversity_index". + The default is "shannon_entropy". + normalize : bool, optional + Normalize the entropy to [0, 1]. Default is "False". + truncation : bool, optional + Use the truncated Shannon entropy. Default is "False". + features : np.ndarray, optional + Feature matrix of entire molecule library, used only if + calculating `hypersphere_overlap_of_subset`. Default is "None". + cs : int, optional + Number of common substructures in molecular compound dataset. + Used only if calculating `explicit_diversity_index`. Default is "None". + + + Returns + ------- + float, computed diversity. + + """ + func_dict = { + "logdet": logdet, + "wdud": wdud, + "gini_coefficient": gini_coefficient, + } + + if div_type in func_dict: + return func_dict[div_type](feature_subset) + + # hypersphere overlap of subset + elif div_type == "hypersphere_overlap": + if features is None: + raise ValueError( + "Please input a feature matrix of the entire " + "dataset when calculating hypersphere overlap." + ) + return hypersphere_overlap_of_subset(features, feature_subset) + + elif div_type == "shannon_entropy": + return shannon_entropy(feature_subset, normalize=normalize, truncation=truncation) + + elif div_type == "explicit_diversity_index": + if cs is None: + raise ValueError( + "Attribute `cs` is missing. " + "Please input `cs` value to use explicit_diversity_index." + ) + elif cs == 0: + raise ValueError("Divide by zero error: Attribute `cs` cannot be 0.") + return explicit_diversity_index(feature_subset, cs) + else: + raise ValueError(f"Diversity type {div_type} not supported.") + + +def logdet(x: np.ndarray) -> float: + r"""Compute the log determinant function. + + Given a :math:`n_s \times n_f` feature matrix :math:`x`, where :math:`n_s` is the number of + samples and :math:`n_f` is the number of features, the log determinant function is defined as: + + .. math: + F_\text{logdet} = \log{\left(\det{\left(\mathbf{x}\mathbf{x}^T + \mathbf{I}\right)}\right)} + + where the :math:`I` is the :math:`n_s \times n_s` identity matrix. + Higher values of :math:`F_\text{logdet}` mean more diversity. + + Parameters + ---------- + x: ndarray of shape (n_samples, n_features) + Feature matrix of `n_samples` samples in `n_features` dimensional feature space, + + Returns + ------- + f_logdet: float + The volume of parallelotope spanned by the matrix. + + Notes + ----- + The log-determinant function is based on the formula in Nakamura, T., Sci Rep 2022. + Please note that we used the + natural logrithim to avoid the numerical stability issues, + https://github.com/theochem/Selector/issues/229. + + References + ---------- + Nakamura, T., Sakaue, S., Fujii, K., Harabuchi, Y., Maeda, S., and Iwata, S.., Selecting + molecules with diverse structures and properties by maximizing submodular functions of + descriptors learned with graph neural networks. Scientific Reports 12, 2022. + + """ + mid = np.dot(x, np.transpose(x)) + np.identity(x.shape[0]) + logdet_mid = np.linalg.slogdet(mid) + f_logdet = logdet_mid.sign * logdet_mid.logabsdet + return f_logdet + + +def shannon_entropy(x: np.ndarray, normalize=True, truncation=False) -> float: + r"""Compute the shannon entropy of a binary matrix. + + Higher values mean more diversity. + + Parameters + ---------- + x : ndarray + Bit-string matrix. + normalize : bool, optional + Normalize the entropy to [0, 1]. Default=True. + truncation : bool, optional + Use the truncated Shannon entropy by only counting the contributions of one-bits. + Default=False. + + Returns + ------- + float : + The shannon entropy of the matrix. + + Notes + ----- + Suppose we have :math:`m` compounds and each compound has :math:`n` bits binary fingerprints. + The binary matrix (feature matrix) is :math:`\mathbf{x} \in m \times n`, where each + row is a compound and each column contains the :math:`n`-bit binary fingerprint. + The equation for Shannon entropy is given by [1]_ and [3]_, + + .. math:: + H = \sum_i^m \left[ - p_i \log_2{p_i } - (1 - p_i)\log_2(1 - p_i) \right] + + where :math:`p_i` represents the relative frequency of `1` bits at the fingerprint position + :math:`i`. When :math:`p_i = 0` or :math:`p_i = 1`, the :math:`SE_i` is zero. + When `completeness` is True, the entropy is calculated as in [2]_ instead + + .. math:: + H = \sum_i^m \left[ - p_i \log_2{p_i } \right] + + When `normalize` is True, the entropy is normalized by a scaling factor so that the entropy is in the range of + [0, 1], [2]_ + + .. math:: + H = \frac{ \sum_i^m \left[ - p_i \log_2{p_i } - (1 - p_i)\log_2(1 - p_i) \right]} + {n \log_2{2} / 2} + + But please note, when `completeness` is False and `normalize` is True, the formula has not been + used in any literature. It is just a simple normalization of the entropy and the user can use it at their own risk. + + References + ---------- + .. [1] Wang, Y., Geppert, H., & Bajorath, J. (2009). Shannon entropy-based fingerprint similarity + search strategy. Journal of Chemical Information and Modeling, 49(7), 1687-1691. + .. [2] Leguy, J., Glavatskikh, M., Cauchy, T., & Da Mota, B. (2021). Scalable estimator of the + diversity for de novo molecular generation resulting in a more robust QM dataset (OD9) and a + more efficient molecular optimization. Journal of Cheminformatics, 13(1), 1-17. + .. [3] Weidlich, I. E., & Filippov, I. V. (2016). Using the Gini coefficient to measure the + chemical diversity of small molecule libraries. Journal of Computational Chemistry, 37(22), 2091-2097. + + """ + # check if matrix is binary + if np.count_nonzero((x != 0) & (x != 1)) != 0: + raise ValueError("Attribute `x` should have binary values.") + + p_i_arr = np.sum(x, axis=0) / x.shape[0] + h_x = 0 + + for p_i in p_i_arr: + if p_i == 0 or p_i == 1: + # p_i = 0 + se_i = 0 + else: + if truncation: + # from https://jcheminf.biomedcentral.com/articles/10.1186/s13321-021-00554-8 + se_i = -p_i * np.log2(p_i) + else: + # from https://pubs.acs.org/doi/10.1021/ci900159f + se_i = -p_i * np.log2(p_i) - (1 - p_i) * np.log2(1 - p_i) + + h_x += se_i + + if normalize: + if truncation: + warnings.warn( + "Computing the normalized Shannon entropy only counting the on-bits has not been reported in " + "literature. The user can use it at their own risk." + ) + + h_x /= x.shape[1] * np.log2(2) / 2 + + return h_x + + +# todo: add tests for edi +def explicit_diversity_index( + x: np.ndarray, + cs: int, +) -> float: + """Compute the explicit diversity index. + + Parameters + ---------- + x: ndarray of shape (n_samples, n_features) + Feature matrix of `n_samples` samples in `n_features` dimensional feature space. + cs : int + Number of common substructures in the compound set. + + Returns + ------- + edi_scaled : float + Explicit diversity index. + + Notes + ----- + This method hasn't been tested. + + This method is used only for datasets of molecular compounds. + + Papp, Á., Gulyás-Forró, A., Gulyás, Z., Dormán, G., Ürge, L., + and Darvas, F.. (2006) Explicit Diversity Index (EDI): + A Novel Measure for Assessing the Diversity of Compound Databases. + Journal of Chemical Information and Modeling 46, 1898-1904. + """ + nc = len(x) + sdi = (1 - nearest_average_tanimoto(x)) / (0.8047 - (0.065 * (np.log(nc)))) + cr = -1 * np.log10(nc / (cs**2)) + edi = (sdi + cr) * 0.7071067811865476 + edi_scaled = ((np.tanh(edi / 3) + 1) / 2) * 100 + return edi_scaled + + +def wdud(x: np.ndarray) -> float: + r"""Compute the Wasserstein Distance to Uniform Distribution(WDUD). + + The equation for the Wasserstein Distance for a single feature to uniform distribution is + + .. math:: + WDUD(x) = \int_{0}^{1} |U(x) - V(x)|dx + + where the feature is normalized to [0, 1], :math:`U(x)=x` is the cumulative distribution + of the uniform distribution on [0, 1], and :math:`V(x) = \sum_{y <= x}1 / N` is the discrete + distribution of the values of the feature in :math:`x`, where :math:`y` is the ith feature. This + integral is calculated iteratively between :math:`y_i` and :math:`y_{i+1}`, using trapezoidal method. + + Lower values of the WDUD mean more diversity because the features of the selected set are + more evenly distributed over the range of feature values. + + Parameters + ---------- + x: ndarray of shape (n_samples, n_features) + Feature matrix of `n_samples` samples in `n_features` dimensional feature space. + + Returns + ------- + float : + The mean of the WDUD of each feature over all samples. + + Notes + ----- + Nakamura, T., Sakaue, S., Fujii, K., Harabuchi, Y., Maeda, S., and Iwata, S.. (2022) + Selecting molecules with diverse structures and properties by maximizing + submodular functions of descriptors learned with graph neural networks. + Scientific Reports 12. + + """ + if x.ndim != 2: + raise ValueError(f"The number of dimensions {x.ndim} should be two.") + + # find the range of each feature + col_diff = np.ptp(x, axis=0) + # Normalization of each feature to [0, 1] + if np.any(np.abs(col_diff) < 1e-30): + # warning if some feature columns are constant + warnings.warn( + "Some of the features are constant which will cause the normalization to fail. " + "Now removing them." + ) + if np.all(col_diff < 1.0e-30): + raise ValueError( + "Unfortunately, all the features are constants and wdud cannot be calculated." + ) + else: + # remove the constant feature columns + mask = np.ptp(x, axis=0) > 1e-30 + x = x[:, mask] + x_norm = (x - np.min(x, axis=0)) / np.ptp(x, axis=0) + + # min_max normalization: + n_samples, n_features = x_norm.shape + ans = [] # store the Wasserstein distance for each feature + for i in range(0, n_features): + wdu = 0.0 + y = np.sort(x_norm[:, i]) + # Round to the sixth decimal place and count number of unique elements + # to construct an accurate cumulative discrete distribution func \sum_{x <= y_{i + 1}} 1/k + y, counts = np.unique(np.round(x_norm[:, i], decimals=6), return_counts=True) + p = 0 + # Ignore 0 and because v_min= 0 + for j in range(1, len(counts)): + # integral from y_{i - 1} to y_{i} of |x - \sum_{x <= y_{i}} 1/k| dx + yi1 = y[j - 1] + yi = y[j] + # Make a grid from yi1 to yi + grid = np.linspace(yi1, yi, num=1000, endpoint=True) + # Evaluate the integrand |x - \sum_{x <= y_{i + 1}} 1/k| + p += counts[j - 1] + integrand = np.abs(grid - p / n_samples) + # Integrate using np.trapezoid + wdu += np.trapezoid(y=integrand, x=grid) + ans.append(wdu) + return np.average(ans) + + +def hypersphere_overlap_of_subset(x: np.ndarray, x_subset: np.array) -> float: + r"""Compute the overlap of subset with hyper-spheres around each point + + The edge penalty is also included, which disregards areas + outside of the boundary of the full feature space/library. + This is calculated as: + + .. math:: + g(S) = \sum_{i < j}^k O(i, j) + \sum^k_m E(m) + + where :math:`i, j` is over the subset of samples, e.g. molecules, + :math:`O(i, j)` is the approximate overlap between hyperspheres, + :math:`k` is the number of features and :math:`E` + is the edge penalty of a sample. + + Lower values mean more diversity. + + Parameters + ---------- + x : ndarray + Feature matrix of all samples. + x_subset : ndarray + Feature matrix of selected subset of samples. + + Returns + ------- + float : + The approximate overlapping volume of hyperspheres + drawn around the selected points/samples. + + Notes + ----- + The hypersphere overlap volume is calculated using an approximation formula from Agrafiotis (1997). + + Agrafiotis, D. K.. (1997) Stochastic Algorithms for Maximizing Molecular Diversity. + Journal of Chemical Information and Computer Sciences 37, 841-851. + """ + # check if x is binary matrix or not + if np.array_equal(x, x.astype(bool)): + raise ValueError( + "Input matrix cannot be binary because the diversity measurement is designed for continuous orthogonal features." + ) + + # Find the maximum and minimum over each feature across all samples. + max_x = np.max(x, axis=0) + min_x = np.min(x, axis=0) + + if np.all(np.abs(max_x - min_x) < 1e-30): + raise ValueError("All of the features are redundant which causes normalization to fail.") + + # Remove redundant features + non_red_feat = np.abs(max_x - min_x) > 1e-30 + x = x[:, non_red_feat] + x_subset = x_subset[:, non_red_feat] + max_x = max_x[non_red_feat] + min_x = min_x[non_red_feat] + + d = len(x_subset[0]) + k = len(x_subset[:, 0]) + + # normalization of each feature to [0, 1] + x_norm = (x_subset - min_x) / (max_x - min_x) + + # r_o = hypersphere radius + r_o = d * np.sqrt(1 / k) + if r_o > 0.5: + warnings.warn("The number of samples should be much larger" " than the number of features.") + g_s = 0 + edge = 0 + + # lambda parameter controls edge penalty + lam = (d - 1.0) / d + # calculate overlap volume + for i in range(0, (k - 1)): + for j in range((i + 1), k): + dist = np.linalg.norm(x_norm[i] - x_norm[j]) + # Overlap penalty + if dist <= (2 * r_o): + with np.errstate(divide="ignore"): + # min(100) ignores the inf case with divide by zero + g_s += min(100, 2 * (r_o / dist) - 1) + # Edge penalty: lambda (1 - \sum^d_j e_{ij} / (dr_0) + edge_pen = 0.0 + for j_dim in range(0, d): + # calculate dist to closest boundary in jth coordinate, + # with max value = 1, min value = 0 + dist_max = np.abs(1 - x_norm[i, j_dim]) + dist_min = x_norm[i, j_dim] + dist = min(dist_min, dist_max) + # truncate distance at r_o + if dist > r_o: + dist = r_o + edge_pen += dist + edge_pen /= d * r_o + edge_pen = lam * (1.0 - edge_pen) + edge += edge_pen + g_s += edge + return g_s + + +def gini_coefficient(x: np.ndarray): + r""" + Gini coefficient of bit-wise fingerprints of a database of molecules. + + Measures the chemical diversity of a database of molecules defined by + the following formula: + + .. math:: + G = \frac{2 \sum_{i=1}^L i ||y_i||_1 }{N \sum_{i=1}^L ||y_i||_1} - \frac{L+1}{L}, + + where :math:`y_i \in \{0, 1\}^N` is a vector of zero and ones of length the + number of molecules :math:`N` of the `i`th feature, and :math:`L` is the feature length. + + Lower values mean more diversity. + + Parameters + ---------- + x : ndarray(N, L) + Molecule features in L bits with N molecules. + + Returns + ------- + float : + Gini coefficient in the range [0,1]. + + References + ---------- + Weidlich, Iwona E., and Igor V. Filippov. "Using the gini coefficient to measure the + chemical diversity of small‐molecule libraries." (2016): 2091-2097. + + """ + # Check that `x` is a bit-wise fingerprint. + if np.count_nonzero((x != 0) & (x != 1)) != 0: + raise ValueError("Attribute `x` should have binary values.") + if x.ndim != 2: + raise ValueError(f"Attribute `x` should have dimension two rather than {x.ndim}.") + + num_features = x.shape[1] + # Take the bit-count of each column/molecule. + bit_count = np.sum(x, axis=0) + + # Sort the bit-count since Gini coefficients relies on cumulative distribution. + bit_count = np.sort(bit_count) + + # Mean of denominator + denominator = num_features * np.sum(bit_count) + numerator = np.sum(np.arange(1, num_features + 1) * bit_count) + + return 2.0 * numerator / denominator - (num_features + 1) / num_features + + +def nearest_average_tanimoto(x: np.ndarray) -> float: + """Computes the average tanimoto for nearest molecules. + + Parameters + ---------- + x : ndarray + Feature matrix. + + Returns + ------- + nat : float + Average tanimoto of closest pairs. + + Notes + ----- + This computes the tanimoto coefficient of pairs with the shortest + distances, then returns the average of them. + This calculation is explictly for the explicit diversity index. + + Papp, Á., Gulyás-Forró, A., Gulyás, Z., Dormán, G., Ürge, L., + and Darvas, F.. (2006) Explicit Diversity Index (EDI): + A Novel Measure for Assessing the Diversity of Compound Databases. + Journal of Chemical Information and Modeling 46, 1898-1904. + """ + tani = [] + for idx, _ in enumerate(x): + # arbitrary distance for comparison: + short = 100 + a = 0 + b = 0 + # search for shortest distance point from idx + for jdx, _ in enumerate(x): + dist = np.linalg.norm(x[idx] - x[jdx]) + if dist < short and idx != jdx: + short = dist + a = idx + b = jdx + # calculate tanimoto for each shortest dist pair + tani.append(tanimoto(x[a], x[b])) + # compute average of all shortest tanimoto coeffs + nat = np.average(tani) + return nat diff --git a/selector/measures/similarity.py b/selector/measures/similarity.py index b7443592..ba985699 100644 --- a/selector/measures/similarity.py +++ b/selector/measures/similarity.py @@ -1,326 +1,326 @@ -# -*- coding: utf-8 -*- -# -# The Selector is a Python library of algorithms for selecting diverse -# subsets of data for machine-learning. -# -# Copyright (C) 2022-2024 The QC-Devs Community -# -# This file is part of Selector. -# -# Selector is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 -# of the License, or (at your option) any later version. -# -# Selector is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see -# -# -- -"""Similarity Module.""" - -from itertools import combinations_with_replacement - -import numpy as np - -__all__ = [ - "pairwise_similarity_bit", - "tanimoto", - "modified_tanimoto", - "scaled_similarity_matrix", -] - - -def pairwise_similarity_bit(X: np.array, metric: str) -> np.ndarray: - """Compute pairwise similarity coefficient matrix. - - Parameters - ---------- - X : ndarray of shape (n_samples, n_features) - Feature matrix of `n_samples` samples in `n_features` dimensional space. - metric : str - The metric used when calculating similarity coefficients between samples in a feature array. - Method for calculating similarity coefficient. Options: `"tanimoto"`, `"modified_tanimoto"`. - - Returns - ------- - s : ndarray of shape (n_samples, n_samples) - A symmetric similarity matrix between each pair of samples in the feature matrix. - The diagonal elements are directly computed instead of assuming that they are 1. - - """ - - available_methods = { - "tanimoto": tanimoto, - "modified_tanimoto": modified_tanimoto, - } - if metric not in available_methods: - raise ValueError( - f"Argument metric={metric} is not recognized! Choose from {available_methods.keys()}" - ) - if X.ndim != 2: - raise ValueError(f"Argument features should be a 2D array, got {X.ndim}") - - # make pairwise m-by-m similarity matrix - n_samples = len(X) - s = np.zeros((n_samples, n_samples)) - # compute similarity between all pairs of points (including the diagonal elements) - for i, j in combinations_with_replacement(range(n_samples), 2): - s[i, j] = s[j, i] = available_methods[metric](X[i], X[j]) - return s - - -def tanimoto(a: np.array, b: np.array) -> float: - r"""Compute Tanimoto coefficient or index (a.k.a. Jaccard similarity coefficient). - - For two binary or non-binary arrays :math:`A` and :math:`B`, Tanimoto coefficient - is defined as the size of their intersection divided by the size of their union: - - .. math:: - T(A, B) = \frac{| A \cap B|}{| A \cup B |} = - \frac{| A \cap B|}{|A| + |B| - | A \cap B|} = - \frac{A \cdot B}{\|A\|^2 + \|B\|^2 - A \cdot B} - - where :math:`A \cdot B = \sum_i{A_i B_i}` and :math:`\|A\|^2 = \sum_i{A_i^2}`. - - Parameters - ---------- - a : ndarray of shape (n_features,) - The 1D feature array of sample :math:`A` in an `n_features` dimensional space. - b : ndarray of shape (n_features,) - The 1D feature array of sample :math:`B` in an `n_features` dimensional space. - - Returns - ------- - coeff : float - Tanimoto coefficient between feature arrays :math:`A` and :math:`B`. - - Bajusz, D., Rácz, A., and Héberger, K.. (2015) - Why is Tanimoto index an appropriate choice for fingerprint-based similarity calculations?. - Journal of Cheminformatics 7. - - """ - if a.ndim != 1 or b.ndim != 1: - raise ValueError(f"Arguments a and b should be 1D arrays, got {a.ndim} and {b.ndim}") - if a.shape != b.shape: - raise ValueError( - f"Arguments a and b should have the same shape, got {a.shape} != {b.shape}" - ) - coeff = sum(a * b) / (sum(a**2) + sum(b**2) - sum(a * b)) - return coeff - - -def modified_tanimoto(a: np.array, b: np.array) -> float: - r"""Compute the modified tanimoto coefficient from bitstring vectors of data points A and B. - - Adjusts calculation of the Tanimoto coefficient to counter its natural bias towards - shorter vectors using a Bernoulli probability model. - - .. math:: - {mt} = \frac{2-p}{3} T_1 + \frac{1+p}{3} T_0 - - where :math:`p` is success probability of independent trials, - :math:`T_1` is the number of common '1' bits between data points - (:math:`T_1 = | A \cap B |`), and :math:`T_0` is the number of common '0' - bits between data points (:math:`T_0 = |(1-A) \cap (1-B)|`). - - - Parameters - ---------- - a : ndarray of shape (n_features,) - The 1D bitstring feature array of sample :math:`A` in an `n_features` dimensional space. - b : ndarray of shape (n_features,) - The 1D bitstring feature array of sample :math:`B` in an `n_features` dimensional space. - - Returns - ------- - mt : float - Modified tanimoto coefficient between bitstring feature arrays :math:`A` and :math:`B`. - - Notes - ----- - The equation above has been derived from - - .. math:: - {mt}_{\alpha} = {\alpha}T_1 + (1-\alpha)T_0 - - where :math:`\alpha = \frac{2-p}{3}`. This is done so that the expected value - of the modified tanimoto, :math:`E(mt)`, remains constant even as the number of - trials :math:`p` grows larger. - - Fligner, M. A., Verducci, J. S., and Blower, P. E.. (2002) - A Modification of the Jaccard-Tanimoto Similarity Index for - Diverse Selection of Chemical Compounds Using Binary Strings. - Technometrics 44, 110-119. - - """ - if a.ndim != 1: - raise ValueError(f"Argument `a` should have dimension 1 rather than {a.ndim}.") - if b.ndim != 1: - raise ValueError(f"Argument `b` should have dimension 1 rather than {b.ndim}.") - if a.shape != b.shape: - raise ValueError( - f"Arguments a and b should have the same shape, got {a.shape} != {b.shape}" - ) - - n_features = len(a) - # number of common '1' bits between points A and B - n_11 = sum(a * b) - # number of common '0' bits between points A and B - n_00 = sum((1 - a) * (1 - b)) - - # calculate Tanimoto coefficient based on '0' bits - t_1 = 1 - if n_00 != n_features: - # bit strings are not all '0's - t_1 = n_11 / (n_features - n_00) - # calculate Tanimoto coefficient based on '1' bits - t_0 = 1 - if n_11 != n_features: - # bit strings are not all '1's - t_0 = n_00 / (n_features - n_11) - - # combine into modified tanimoto using Bernoulli Model - # p = independent success trials - # evaluated as total number of '1' bits - # divided by 2x the fingerprint length - p = (n_features - n_00 + n_11) / (2 * n_features) - # mt = x * T_1 + (1-x) * T_0 - # x = (2-p)/3 so that E(mt) = 1/3, no matter the value of p - mt = (((2 - p) / 3) * t_1) + (((1 + p) / 3) * t_0) - return mt - - -def scaled_similarity_matrix(X: np.array) -> np.ndarray: - r"""Compute the scaled similarity matrix. - - .. math:: - X(i,j) = \frac{X(i,j)}{\sqrt{X(i,i)X(j,j)}} - - Parameters - ---------- - X : ndarray of shape (n_samples, n_samples) - Similarity matrix of `n_samples`. - - Returns - ------- - s : ndarray of shape (n_samples, n_samples) - A scaled symmetric similarity matrix. - - """ - if X.ndim != 2: - raise ValueError(f"Argument similarity matrix should be a 2D array, got {X.ndim}") - - if X.shape[0] != X.shape[1]: - raise ValueError( - f"Argument similarity matrix should be a square matrix (having same number of rows and columns), got {X.shape[0]} and {X.shape[1]}" - ) - - if not (np.all(X >= 0) and np.all(np.diag(X) > 0)): - raise ValueError( - "All elements of similarity matrix should be greater than zero and diagonals should be non-zero" - ) - - # scaling does not happen if the matrix is binary similarity matrix with all diagonal elements as 1 - if np.all(np.diag(X) == 1): - print("No scaling is taking effect") - return X - else: - # make a scaled similarity matrix - n_samples = len(X) - s = np.zeros((n_samples, n_samples)) - # calculate the square root of the diagonal elements - sqrt_diag = np.sqrt(np.diag(X)) - # calculate the product of the square roots of the diagonal elements - product_sqrt_diag = np.outer(sqrt_diag, sqrt_diag) - # divide each element of the matrix by the product of the square roots of diagonal elements - s = X / product_sqrt_diag - return s - - -def similarity_index(x: np.array, y: np.array, sim_index: str) -> float: - """Compute similarity index matrix. - - Parameters - ---------- - x : ndarray of shape (n_features,) - Feature array of sample `x` in an `n_features` dimensional space - y : ndarray of shape (n_features,) - Feature array of sample `y` in an `n_features` dimensional space - sim_index : str, optional - The key with the abbreviation of the similarity index to be used for calculations. - Possible values are: - - 'AC': Austin-Colwell - - 'BUB': Baroni-Urbani-Buser - - 'CTn': Consoni-Todschini n (n=1,2) - - 'Fai': Faith - - 'Gle': Gleason - - 'Ja': Jaccard - - 'JT': Jaccard-Tanimoto - - 'RT': Rogers-Tanimoto - - 'RR': Russel-Rao - - 'SM': Sokal-Michener - - 'SSn': Sokal-Sneath n (n=1,2) - Default is 'RR'. - - Returns - ------- - sim : float - The similarity index value between the feature arrays `x` and `y`. - """ - # Define the similarity index functions - similarity_indices = { - "AC": lambda a, d, dis, p: 2 / np.pi * np.arcsin(((a + d) / p) ** 0.5), - "BUB": lambda a, d, dis, p: ((a * d) ** 0.5 + a) / ((a * d) ** 0.5 + a + dis), - "CT1": lambda a, d, dis, p: np.log(1 + a + d) / np.log(1 + p), - "CT2": lambda a, d, dis, p: (np.log(1 + p) - np.log(1 + dis)) / np.log(1 + p), - "Fai": lambda a, d, dis, p: (a + 0.5 * d) / p, - "Gle": lambda a, d, dis, p: 2 * a / (2 * a + dis), - "Ja": lambda a, d, dis, p: 3 * a / (3 * a + dis), - "JT": lambda a, d, dis, p: a / (a + dis), - "RT": lambda a, d, dis, p: (a + d) / (p + dis), - "RR": lambda a, d, dis, p: a / p, - "SM": lambda a, d, dis, p: (a + d) / p, - "SS1": lambda a, d, dis, p: a / (a + 2 * dis), - "SS2": lambda a, d, dis, p: (2 * (a + d)) / (p + (a + d)), - } - - if sim_index not in similarity_indices: - raise ValueError( - f"Argument sim_index={sim_index} is not recognized! Choose from {similarity_indices.keys()}" - ) - if x.ndim != 1 or y.ndim != 1: - raise ValueError(f"Arguments x and y should be 1D arrays, got {x.ndim} and {y.ndim}") - if x.shape != y.shape: - raise ValueError( - f"Arguments x and y should have the same shape, got {x.shape} != {y.shape}" - ) - a, d, dis, p = _compute_base_descriptors(x, y) - return similarity_indices[sim_index](a, d, dis, p) - - -def _compute_base_descriptors(x, y): - """Compute the base descriptors for the similarity indices. - - Parameters - ---------- - x : ndarray of shape (n_features,) - Feature array of sample `x` in an `n_features` dimensional space - y : ndarray of shape (n_features,) - Feature array of sample `y` in an `n_features` dimensional space - - Returns - ------- - tuple(int, int, int, int) - The number of common on bits, number of common off bits, number of 1-0 mismatches, and the - length of the fingerprint. - """ - p = len(x) - a = np.dot(x, y) - d = np.dot(1 - x, 1 - y) - dis = p - a - d - return a, d, dis, p +# -*- coding: utf-8 -*- +# +# The Selector is a Python library of algorithms for selecting diverse +# subsets of data for machine-learning. +# +# Copyright (C) 2022-2024 The QC-Devs Community +# +# This file is part of Selector. +# +# Selector is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 +# of the License, or (at your option) any later version. +# +# Selector is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see +# +# -- +"""Similarity Module.""" + +from itertools import combinations_with_replacement + +import numpy as np + +__all__ = [ + "pairwise_similarity_bit", + "tanimoto", + "modified_tanimoto", + "scaled_similarity_matrix", +] + + +def pairwise_similarity_bit(X: np.array, metric: str) -> np.ndarray: + """Compute pairwise similarity coefficient matrix. + + Parameters + ---------- + X : ndarray of shape (n_samples, n_features) + Feature matrix of `n_samples` samples in `n_features` dimensional space. + metric : str + The metric used when calculating similarity coefficients between samples in a feature array. + Method for calculating similarity coefficient. Options: `"tanimoto"`, `"modified_tanimoto"`. + + Returns + ------- + s : ndarray of shape (n_samples, n_samples) + A symmetric similarity matrix between each pair of samples in the feature matrix. + The diagonal elements are directly computed instead of assuming that they are 1. + + """ + + available_methods = { + "tanimoto": tanimoto, + "modified_tanimoto": modified_tanimoto, + } + if metric not in available_methods: + raise ValueError( + f"Argument metric={metric} is not recognized! Choose from {available_methods.keys()}" + ) + if X.ndim != 2: + raise ValueError(f"Argument features should be a 2D array, got {X.ndim}") + + # make pairwise m-by-m similarity matrix + n_samples = len(X) + s = np.zeros((n_samples, n_samples)) + # compute similarity between all pairs of points (including the diagonal elements) + for i, j in combinations_with_replacement(range(n_samples), 2): + s[i, j] = s[j, i] = available_methods[metric](X[i], X[j]) + return s + + +def tanimoto(a: np.array, b: np.array) -> float: + r"""Compute Tanimoto coefficient or index (a.k.a. Jaccard similarity coefficient). + + For two binary or non-binary arrays :math:`A` and :math:`B`, Tanimoto coefficient + is defined as the size of their intersection divided by the size of their union: + + .. math:: + T(A, B) = \frac{| A \cap B|}{| A \cup B |} = + \frac{| A \cap B|}{|A| + |B| - | A \cap B|} = + \frac{A \cdot B}{\|A\|^2 + \|B\|^2 - A \cdot B} + + where :math:`A \cdot B = \sum_i{A_i B_i}` and :math:`\|A\|^2 = \sum_i{A_i^2}`. + + Parameters + ---------- + a : ndarray of shape (n_features,) + The 1D feature array of sample :math:`A` in an `n_features` dimensional space. + b : ndarray of shape (n_features,) + The 1D feature array of sample :math:`B` in an `n_features` dimensional space. + + Returns + ------- + coeff : float + Tanimoto coefficient between feature arrays :math:`A` and :math:`B`. + + Bajusz, D., Rácz, A., and Héberger, K.. (2015) + Why is Tanimoto index an appropriate choice for fingerprint-based similarity calculations?. + Journal of Cheminformatics 7. + + """ + if a.ndim != 1 or b.ndim != 1: + raise ValueError(f"Arguments a and b should be 1D arrays, got {a.ndim} and {b.ndim}") + if a.shape != b.shape: + raise ValueError( + f"Arguments a and b should have the same shape, got {a.shape} != {b.shape}" + ) + coeff = sum(a * b) / (sum(a**2) + sum(b**2) - sum(a * b)) + return coeff + + +def modified_tanimoto(a: np.array, b: np.array) -> float: + r"""Compute the modified tanimoto coefficient from bitstring vectors of data points A and B. + + Adjusts calculation of the Tanimoto coefficient to counter its natural bias towards + shorter vectors using a Bernoulli probability model. + + .. math:: + {mt} = \frac{2-p}{3} T_1 + \frac{1+p}{3} T_0 + + where :math:`p` is success probability of independent trials, + :math:`T_1` is the number of common '1' bits between data points + (:math:`T_1 = | A \cap B |`), and :math:`T_0` is the number of common '0' + bits between data points (:math:`T_0 = |(1-A) \cap (1-B)|`). + + + Parameters + ---------- + a : ndarray of shape (n_features,) + The 1D bitstring feature array of sample :math:`A` in an `n_features` dimensional space. + b : ndarray of shape (n_features,) + The 1D bitstring feature array of sample :math:`B` in an `n_features` dimensional space. + + Returns + ------- + mt : float + Modified tanimoto coefficient between bitstring feature arrays :math:`A` and :math:`B`. + + Notes + ----- + The equation above has been derived from + + .. math:: + {mt}_{\alpha} = {\alpha}T_1 + (1-\alpha)T_0 + + where :math:`\alpha = \frac{2-p}{3}`. This is done so that the expected value + of the modified tanimoto, :math:`E(mt)`, remains constant even as the number of + trials :math:`p` grows larger. + + Fligner, M. A., Verducci, J. S., and Blower, P. E.. (2002) + A Modification of the Jaccard-Tanimoto Similarity Index for + Diverse Selection of Chemical Compounds Using Binary Strings. + Technometrics 44, 110-119. + + """ + if a.ndim != 1: + raise ValueError(f"Argument `a` should have dimension 1 rather than {a.ndim}.") + if b.ndim != 1: + raise ValueError(f"Argument `b` should have dimension 1 rather than {b.ndim}.") + if a.shape != b.shape: + raise ValueError( + f"Arguments a and b should have the same shape, got {a.shape} != {b.shape}" + ) + + n_features = len(a) + # number of common '1' bits between points A and B + n_11 = sum(a * b) + # number of common '0' bits between points A and B + n_00 = sum((1 - a) * (1 - b)) + + # calculate Tanimoto coefficient based on '0' bits + t_1 = 1 + if n_00 != n_features: + # bit strings are not all '0's + t_1 = n_11 / (n_features - n_00) + # calculate Tanimoto coefficient based on '1' bits + t_0 = 1 + if n_11 != n_features: + # bit strings are not all '1's + t_0 = n_00 / (n_features - n_11) + + # combine into modified tanimoto using Bernoulli Model + # p = independent success trials + # evaluated as total number of '1' bits + # divided by 2x the fingerprint length + p = (n_features - n_00 + n_11) / (2 * n_features) + # mt = x * T_1 + (1-x) * T_0 + # x = (2-p)/3 so that E(mt) = 1/3, no matter the value of p + mt = (((2 - p) / 3) * t_1) + (((1 + p) / 3) * t_0) + return mt + + +def scaled_similarity_matrix(X: np.array) -> np.ndarray: + r"""Compute the scaled similarity matrix. + + .. math:: + X(i,j) = \frac{X(i,j)}{\sqrt{X(i,i)X(j,j)}} + + Parameters + ---------- + X : ndarray of shape (n_samples, n_samples) + Similarity matrix of `n_samples`. + + Returns + ------- + s : ndarray of shape (n_samples, n_samples) + A scaled symmetric similarity matrix. + + """ + if X.ndim != 2: + raise ValueError(f"Argument similarity matrix should be a 2D array, got {X.ndim}") + + if X.shape[0] != X.shape[1]: + raise ValueError( + f"Argument similarity matrix should be a square matrix (having same number of rows and columns), got {X.shape[0]} and {X.shape[1]}" + ) + + if not (np.all(X >= 0) and np.all(np.diag(X) > 0)): + raise ValueError( + "All elements of similarity matrix should be greater than zero and diagonals should be non-zero" + ) + + # scaling does not happen if the matrix is binary similarity matrix with all diagonal elements as 1 + if np.all(np.diag(X) == 1): + print("No scaling is taking effect") + return X + else: + # make a scaled similarity matrix + n_samples = len(X) + s = np.zeros((n_samples, n_samples)) + # calculate the square root of the diagonal elements + sqrt_diag = np.sqrt(np.diag(X)) + # calculate the product of the square roots of the diagonal elements + product_sqrt_diag = np.outer(sqrt_diag, sqrt_diag) + # divide each element of the matrix by the product of the square roots of diagonal elements + s = X / product_sqrt_diag + return s + + +def similarity_index(x: np.array, y: np.array, sim_index: str) -> float: + """Compute similarity index matrix. + + Parameters + ---------- + x : ndarray of shape (n_features,) + Feature array of sample `x` in an `n_features` dimensional space + y : ndarray of shape (n_features,) + Feature array of sample `y` in an `n_features` dimensional space + sim_index : str, optional + The key with the abbreviation of the similarity index to be used for calculations. + Possible values are: + - 'AC': Austin-Colwell + - 'BUB': Baroni-Urbani-Buser + - 'CTn': Consoni-Todschini n (n=1,2) + - 'Fai': Faith + - 'Gle': Gleason + - 'Ja': Jaccard + - 'JT': Jaccard-Tanimoto + - 'RT': Rogers-Tanimoto + - 'RR': Russel-Rao + - 'SM': Sokal-Michener + - 'SSn': Sokal-Sneath n (n=1,2) + Default is 'RR'. + + Returns + ------- + sim : float + The similarity index value between the feature arrays `x` and `y`. + """ + # Define the similarity index functions + similarity_indices = { + "AC": lambda a, d, dis, p: 2 / np.pi * np.arcsin(((a + d) / p) ** 0.5), + "BUB": lambda a, d, dis, p: ((a * d) ** 0.5 + a) / ((a * d) ** 0.5 + a + dis), + "CT1": lambda a, d, dis, p: np.log(1 + a + d) / np.log(1 + p), + "CT2": lambda a, d, dis, p: (np.log(1 + p) - np.log(1 + dis)) / np.log(1 + p), + "Fai": lambda a, d, dis, p: (a + 0.5 * d) / p, + "Gle": lambda a, d, dis, p: 2 * a / (2 * a + dis), + "Ja": lambda a, d, dis, p: 3 * a / (3 * a + dis), + "JT": lambda a, d, dis, p: a / (a + dis), + "RT": lambda a, d, dis, p: (a + d) / (p + dis), + "RR": lambda a, d, dis, p: a / p, + "SM": lambda a, d, dis, p: (a + d) / p, + "SS1": lambda a, d, dis, p: a / (a + 2 * dis), + "SS2": lambda a, d, dis, p: (2 * (a + d)) / (p + (a + d)), + } + + if sim_index not in similarity_indices: + raise ValueError( + f"Argument sim_index={sim_index} is not recognized! Choose from {similarity_indices.keys()}" + ) + if x.ndim != 1 or y.ndim != 1: + raise ValueError(f"Arguments x and y should be 1D arrays, got {x.ndim} and {y.ndim}") + if x.shape != y.shape: + raise ValueError( + f"Arguments x and y should have the same shape, got {x.shape} != {y.shape}" + ) + a, d, dis, p = _compute_base_descriptors(x, y) + return similarity_indices[sim_index](a, d, dis, p) + + +def _compute_base_descriptors(x, y): + """Compute the base descriptors for the similarity indices. + + Parameters + ---------- + x : ndarray of shape (n_features,) + Feature array of sample `x` in an `n_features` dimensional space + y : ndarray of shape (n_features,) + Feature array of sample `y` in an `n_features` dimensional space + + Returns + ------- + tuple(int, int, int, int) + The number of common on bits, number of common off bits, number of 1-0 mismatches, and the + length of the fingerprint. + """ + p = len(x) + a = np.dot(x, y) + d = np.dot(1 - x, 1 - y) + dis = p - a - d + return a, d, dis, p diff --git a/selector/measures/tests/__init__.py b/selector/measures/tests/__init__.py index 22d16e3e..ddfef859 100644 --- a/selector/measures/tests/__init__.py +++ b/selector/measures/tests/__init__.py @@ -1,25 +1,25 @@ -# -*- coding: utf-8 -*- -# -# The Selector is a Python library of algorithms for selecting diverse -# subsets of data for machine-learning. -# -# Copyright (C) 2022-2024 The QC-Devs Community -# -# This file is part of Selector. -# -# Selector is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 -# of the License, or (at your option) any later version. -# -# Selector is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see -# -# -- - -"""Test Module.""" +# -*- coding: utf-8 -*- +# +# The Selector is a Python library of algorithms for selecting diverse +# subsets of data for machine-learning. +# +# Copyright (C) 2022-2024 The QC-Devs Community +# +# This file is part of Selector. +# +# Selector is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 +# of the License, or (at your option) any later version. +# +# Selector is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see +# +# -- + +"""Test Module.""" diff --git a/selector/measures/tests/common.py b/selector/measures/tests/common.py index 041b9d41..a876af00 100644 --- a/selector/measures/tests/common.py +++ b/selector/measures/tests/common.py @@ -1,119 +1,119 @@ -# -*- coding: utf-8 -*- -# -# The Selector is a Python library of algorithms for selecting diverse -# subsets of data for machine-learning. -# -# Copyright (C) 2022-2024 The QC-Devs Community -# -# This file is part of Selector. -# -# Selector is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 -# of the License, or (at your option) any later version. -# -# Selector is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see -# -# -- -"""Common functions for test module.""" - -import numpy as np - -try: - from importlib_resources import path -except ImportError: - from importlib.resources import path - - -def bit_cosine(a, b): - """Compute dice coefficient. - - Parameters - ---------- - a : array_like - molecule A's features in bit string. - b : array_like - molecules B's features in bit string. - - Returns - ------- - coeff : int - dice coefficient for molecule A and B. - """ - a_feat = np.count_nonzero(a) - b_feat = np.count_nonzero(b) - c = 0 - for idx, _ in enumerate(a): - if a[idx] == b[idx] and a[idx] != 0: - c += 1 - b_c = c / ((a_feat * b_feat) ** 0.5) - return b_c - - -def bit_dice(a, b): - """Compute dice coefficient. - - Parameters - ---------- - a : array_like - molecule A's features. - b : array_like - molecules B's features. - - Returns - ------- - coeff : int - dice coefficient for molecule A and B. - """ - a_feat = np.count_nonzero(a) - b_feat = np.count_nonzero(b) - c = 0 - for idx, _ in enumerate(a): - if a[idx] == b[idx] and a[idx] != 0: - c += 1 - b_d = (2 * c) / (a_feat + b_feat) - return b_d - - -def cosine(a, b): - """Compute cosine coefficient. - - Parameters - ---------- - a : array_like - molecule A's features. - b : array_like - molecules B's features. - - Returns - ------- - coeff : int - cosine coefficient for molecule A and B. - """ - coeff = (sum(a * b)) / (((sum(a**2)) + (sum(b**2))) ** 0.5) - return coeff - - -def dice(a, b): - """Compute dice coefficient. - - Parameters - ---------- - a : array_like - molecule A's features. - b : array_like - molecules B's features. - - Returns - ------- - coeff : int - dice coefficient for molecule A and B. - """ - coeff = (2 * (sum(a * b))) / ((sum(a**2)) + (sum(b**2))) - return coeff +# -*- coding: utf-8 -*- +# +# The Selector is a Python library of algorithms for selecting diverse +# subsets of data for machine-learning. +# +# Copyright (C) 2022-2024 The QC-Devs Community +# +# This file is part of Selector. +# +# Selector is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 +# of the License, or (at your option) any later version. +# +# Selector is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see +# +# -- +"""Common functions for test module.""" + +import numpy as np + +try: + from importlib_resources import path +except ImportError: + from importlib.resources import path + + +def bit_cosine(a, b): + """Compute dice coefficient. + + Parameters + ---------- + a : array_like + molecule A's features in bit string. + b : array_like + molecules B's features in bit string. + + Returns + ------- + coeff : int + dice coefficient for molecule A and B. + """ + a_feat = np.count_nonzero(a) + b_feat = np.count_nonzero(b) + c = 0 + for idx, _ in enumerate(a): + if a[idx] == b[idx] and a[idx] != 0: + c += 1 + b_c = c / ((a_feat * b_feat) ** 0.5) + return b_c + + +def bit_dice(a, b): + """Compute dice coefficient. + + Parameters + ---------- + a : array_like + molecule A's features. + b : array_like + molecules B's features. + + Returns + ------- + coeff : int + dice coefficient for molecule A and B. + """ + a_feat = np.count_nonzero(a) + b_feat = np.count_nonzero(b) + c = 0 + for idx, _ in enumerate(a): + if a[idx] == b[idx] and a[idx] != 0: + c += 1 + b_d = (2 * c) / (a_feat + b_feat) + return b_d + + +def cosine(a, b): + """Compute cosine coefficient. + + Parameters + ---------- + a : array_like + molecule A's features. + b : array_like + molecules B's features. + + Returns + ------- + coeff : int + cosine coefficient for molecule A and B. + """ + coeff = (sum(a * b)) / (((sum(a**2)) + (sum(b**2))) ** 0.5) + return coeff + + +def dice(a, b): + """Compute dice coefficient. + + Parameters + ---------- + a : array_like + molecule A's features. + b : array_like + molecules B's features. + + Returns + ------- + coeff : int + dice coefficient for molecule A and B. + """ + coeff = (2 * (sum(a * b))) / ((sum(a**2)) + (sum(b**2))) + return coeff diff --git a/selector/measures/tests/test_converter.py b/selector/measures/tests/test_converter.py index 7baf7840..beb6d86a 100644 --- a/selector/measures/tests/test_converter.py +++ b/selector/measures/tests/test_converter.py @@ -1,269 +1,269 @@ -# -*- coding: utf-8 -*- -# -# The Selector is a Python library of algorithms for selecting diverse -# subsets of data for machine-learning. -# -# Copyright (C) 2022-2024 The QC-Devs Community -# -# This file is part of Selector. -# -# Selector is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 -# of the License, or (at your option) any later version. -# -# Selector is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see -# -# -- -"""Test Converter Module.""" - -import numpy as np -from numpy.testing import assert_almost_equal, assert_equal, assert_raises - -from selector.measures import converter as cv - -# Tests for variations on input `x` for sim_to_dist() - - -def test_sim_2_dist_float_int(): - """Test similarity to distance input handling when input is a float or int.""" - expected_1 = 0.25 - int_out = cv.sim_to_dist(4, "reciprocal") - assert_equal(int_out, expected_1) - expected_2 = 2 - float_out = cv.sim_to_dist(0.5, "reciprocal") - assert_equal(float_out, expected_2) - - -def test_sim_2_dist_array_dimension_error(): - """Test sim to dist function with incorrect input dimensions for `x`.""" - assert_raises(ValueError, cv.sim_to_dist, np.ones([2, 2, 2]), "reciprocal") - - -def test_sim_2_dist_1d_metric_error(): - """Test sim to dist function with an invalid metric for 1D arrays.""" - assert_raises(ValueError, cv.sim_to_dist, np.ones(5), "gravity") - assert_raises(ValueError, cv.sim_to_dist, np.ones(5), "co-occurrence") - - -# Tests for variations on input `metric` for sim_to_dist() - - -def test_sim_2_dist(): - """Test similarity to distance method with specified metric.""" - x = np.array([[1, 0.2, 0.5], [0.2, 1, 0.25], [0.5, 0.25, 1]]) - expected = np.array([[0.20, 1, 0.70], [1, 0.20, 0.95], [0.70, 0.95, 0.20]]) - actual = cv.sim_to_dist(x, "reverse") - assert_almost_equal(actual, expected, decimal=10) - - -def test_sim_2_dist_frequency(): - """Test similarity to distance method with a frequency metric.""" - x = np.array([[4, 9, 1], [9, 1, 25], [1, 25, 16]]) - expected = np.array([[(1 / 2), (1 / 3), 1], [(1 / 3), 1, (1 / 5)], [1, (1 / 5), (1 / 4)]]) - actual = cv.sim_to_dist(x, "transition") - assert_almost_equal(actual, expected, decimal=10) - - -def test_sim_2_dist_frequency_error(): - """Test similarity to distance method with a frequency metric and incorrect input.""" - # zeroes in the frequency matrix - x = np.array([[0, 9, 1], [9, 1, 25], [1, 25, 0]]) - assert_raises(ValueError, cv.sim_to_dist, x, "gravity") - # negatives in the frequency matrix - y = np.array([[1, -9, 1], [9, 1, -25], [1, 25, 16]]) - assert_raises(ValueError, cv.sim_to_dist, x, "gravity") - - -def test_sim_2_dist_membership(): - """Test similarity to distance method with the membership metric.""" - # x = np.array([[(1 / 2), (1 / 5)], [(1 / 4), (1 / 3)]]) - x = np.array([[1, 1 / 5, 1 / 3], [1 / 5, 1, 4 / 5], [1 / 3, 4 / 5, 1]]) - expected = np.array([[0, 4 / 5, 2 / 3], [4 / 5, 0, 1 / 5], [2 / 3, 1 / 5, 0]]) - actual = cv.sim_to_dist(x, "membership") - assert_almost_equal(actual, expected, decimal=10) - - -def test_sim_2_dist_membership_error(): - """Test similarity to distance method with the membership metric when there is an input error.""" - x = np.array([[1, 0, -7], [0, 1, 3], [-7, 3, 1]]) - assert_raises(ValueError, cv.sim_to_dist, x, "membership") - - -def test_sim_2_dist_invalid_metric(): - """Test similarity to distance method with an unsupported metric.""" - assert_raises(ValueError, cv.sim_to_dist, np.ones(5), "testing") - - -def test_sim_2_dist_non_symmetric(): - """Test the invalid 2D symmetric matrix error.""" - x = np.array([[1, 2], [4, 5]]) - assert_raises(ValueError, cv.sim_to_dist, x, "reverse") - - -# Tests for individual metrics - - -def test_reverse(): - """Test the reverse function for similarity to distance conversion.""" - x = np.array([[3, 1, 1], [1, 3, 0], [1, 0, 3]]) - expected = np.array([[0, 2, 2], [2, 0, 3], [2, 3, 0]]) - actual = cv.reverse(x) - assert_equal(actual, expected) - - -def test_reciprocal(): - """Test the reverse function for similarity to distance conversion.""" - x = np.array([[1, 0.25, 0.40], [0.25, 1, 0.625], [0.40, 0.625, 1]]) - expected = np.array([[1, 4, 2.5], [4, 1, 1.6], [2.5, 1.6, 1]]) - actual = cv.reciprocal(x) - assert_equal(actual, expected) - - -def test_reciprocal_error(): - """Test the reverse function with incorrect input values.""" - # zero value for similarity (causes divide by zero issues) - x = np.array([[0, 4], [3, 2]]) - assert_raises(ValueError, cv.reciprocal, x) - # negative value for similarity (distance cannot be negative) - y = np.array([[1, -4], [3, 2]]) - assert_raises(ValueError, cv.reciprocal, y) - - -def test_exponential(): - """Test the exponential function for similarity to distance conversion.""" - x = np.array([[1, 0.25, 0.40], [0.25, 1, 0.625], [0.40, 0.625, 1]]) - expected = np.array( - [ - [0, 1.38629436112, 0.91629073187], - [1.38629436112, 0, 0.47000362924], - [0.91629073187, 0.47000362924, 0], - ] - ) - actual = cv.exponential(x) - assert_almost_equal(actual, expected, decimal=10) - - -def test_exponential_error(): - """Test the exponential function when max similarity is zero.""" - x = np.zeros((4, 4)) - assert_raises(ValueError, cv.exponential, x) - - -def test_gaussian(): - """Test the gaussian function for similarity to distance conversion.""" - x = np.array([[1, 0.25, 0.40], [0.25, 1, 0.625], [0.40, 0.625, 1]]) - expected = np.array( - [ - [0, 1.17741002252, 0.95723076208], - [1.17741002252, 0, 0.68556810693], - [0.95723076208, 0.68556810693, 0], - ] - ) - actual = cv.gaussian(x) - assert_almost_equal(actual, expected, decimal=10) - - -def test_gaussian_error(): - """Test the gaussian function when max similarity is zero.""" - x = np.zeros((4, 4)) - assert_raises(ValueError, cv.gaussian, x) - - -def test_correlation(): - """Test the correlation to distance conversion function.""" - x = np.array([[1, 0.5, 0.2], [0.5, 1, -0.2], [0.2, -0.2, 1]]) - # expected = sqrt(1-x) - expected = np.array( - [ - [0, 0.70710678118, 0.894427191], - [0.70710678118, 0, 1.09544511501], - [0.894427191, 1.09544511501, 0], - ] - ) - actual = cv.correlation(x) - assert_almost_equal(actual, expected, decimal=10) - - -def test_correlation_error(): - """Test the correlation function with an out of bounds array.""" - x = np.array([[1, 0, -7], [0, 1, 3], [-7, 3, 1]]) - assert_raises(ValueError, cv.correlation, x) - - -def test_transition(): - """Test the transition function for frequency to distance conversion.""" - x = np.array([[4, 9, 1], [9, 1, 25], [1, 25, 16]]) - expected = np.array([[(1 / 2), (1 / 3), 1], [(1 / 3), 1, (1 / 5)], [1, (1 / 5), (1 / 4)]]) - - actual = cv.transition(x) - assert_almost_equal(actual, expected, decimal=10) - - -def test_co_occurrence(): - """Test the co-occurrence conversion function.""" - x = np.array([[1, 2, 3], [2, 1, 3], [3, 3, 1]]) - expected = np.array( - [ - [1 / (19 / 121 + 1), 1 / (38 / 121 + 1), 1 / (57 / 121 + 1)], - [1 / (38 / 121 + 1), 1 / (19 / 121 + 1), 1 / (57 / 121 + 1)], - [1 / (57 / 121 + 1), 1 / (57 / 121 + 1), 1 / (19 / 121 + 1)], - ] - ) - actual = cv.co_occurrence(x) - assert_almost_equal(actual, expected, decimal=10) - - -def test_gravity(): - """Test the gravity conversion function.""" - x = np.array([[1, 2, 3], [2, 1, 3], [3, 3, 1]]) - expected = np.array( - [ - [2.5235730726, 1.7844356324, 1.45698559277], - [1.7844356324, 2.5235730726, 1.45698559277], - [1.45698559277, 1.45698559277, 2.5235730726], - ] - ) - actual = cv.gravity(x) - assert_almost_equal(actual, expected, decimal=10) - - -def test_probability(): - """Test the probability to distance conversion function.""" - x = np.array([[0.3, 0.7], [0.5, 0.5]]) - expected = np.array([[1.8116279322, 1.1356324735], [1.3819765979, 1.3819765979]]) - actual = cv.probability(x) - assert_almost_equal(actual, expected, decimal=10) - - -def test_probability_error(): - """Test the correlation function with an out of bounds array.""" - # negative value for probability - x = np.array([[-0.5]]) - assert_raises(ValueError, cv.probability, x) - # too large value for probability - y = np.array([[3]]) - assert_raises(ValueError, cv.probability, y) - # zero value for probability (causes divide by zero issues) - z = np.array([[0]]) - assert_raises(ValueError, cv.probability, z) - - -def test_covariance(): - """Test the covariance to distance conversion function.""" - x = np.array([[4, -4], [-4, 6]]) - expected = np.array([[0, 4.24264068712], [4.24264068712, 0]]) - actual = cv.covariance(x) - assert_almost_equal(actual, expected, decimal=10) - - -def test_covariance_error(): - """Test the covariance function when input contains a negative variance.""" - x = np.array([[-4, 4], [4, 6]]) - assert_raises(ValueError, cv.covariance, x) +# -*- coding: utf-8 -*- +# +# The Selector is a Python library of algorithms for selecting diverse +# subsets of data for machine-learning. +# +# Copyright (C) 2022-2024 The QC-Devs Community +# +# This file is part of Selector. +# +# Selector is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 +# of the License, or (at your option) any later version. +# +# Selector is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see +# +# -- +"""Test Converter Module.""" + +import numpy as np +from numpy.testing import assert_almost_equal, assert_equal, assert_raises + +from selector.measures import converter as cv + +# Tests for variations on input `x` for sim_to_dist() + + +def test_sim_2_dist_float_int(): + """Test similarity to distance input handling when input is a float or int.""" + expected_1 = 0.25 + int_out = cv.sim_to_dist(4, "reciprocal") + assert_equal(int_out, expected_1) + expected_2 = 2 + float_out = cv.sim_to_dist(0.5, "reciprocal") + assert_equal(float_out, expected_2) + + +def test_sim_2_dist_array_dimension_error(): + """Test sim to dist function with incorrect input dimensions for `x`.""" + assert_raises(ValueError, cv.sim_to_dist, np.ones([2, 2, 2]), "reciprocal") + + +def test_sim_2_dist_1d_metric_error(): + """Test sim to dist function with an invalid metric for 1D arrays.""" + assert_raises(ValueError, cv.sim_to_dist, np.ones(5), "gravity") + assert_raises(ValueError, cv.sim_to_dist, np.ones(5), "co-occurrence") + + +# Tests for variations on input `metric` for sim_to_dist() + + +def test_sim_2_dist(): + """Test similarity to distance method with specified metric.""" + x = np.array([[1, 0.2, 0.5], [0.2, 1, 0.25], [0.5, 0.25, 1]]) + expected = np.array([[0.20, 1, 0.70], [1, 0.20, 0.95], [0.70, 0.95, 0.20]]) + actual = cv.sim_to_dist(x, "reverse") + assert_almost_equal(actual, expected, decimal=10) + + +def test_sim_2_dist_frequency(): + """Test similarity to distance method with a frequency metric.""" + x = np.array([[4, 9, 1], [9, 1, 25], [1, 25, 16]]) + expected = np.array([[(1 / 2), (1 / 3), 1], [(1 / 3), 1, (1 / 5)], [1, (1 / 5), (1 / 4)]]) + actual = cv.sim_to_dist(x, "transition") + assert_almost_equal(actual, expected, decimal=10) + + +def test_sim_2_dist_frequency_error(): + """Test similarity to distance method with a frequency metric and incorrect input.""" + # zeroes in the frequency matrix + x = np.array([[0, 9, 1], [9, 1, 25], [1, 25, 0]]) + assert_raises(ValueError, cv.sim_to_dist, x, "gravity") + # negatives in the frequency matrix + y = np.array([[1, -9, 1], [9, 1, -25], [1, 25, 16]]) + assert_raises(ValueError, cv.sim_to_dist, x, "gravity") + + +def test_sim_2_dist_membership(): + """Test similarity to distance method with the membership metric.""" + # x = np.array([[(1 / 2), (1 / 5)], [(1 / 4), (1 / 3)]]) + x = np.array([[1, 1 / 5, 1 / 3], [1 / 5, 1, 4 / 5], [1 / 3, 4 / 5, 1]]) + expected = np.array([[0, 4 / 5, 2 / 3], [4 / 5, 0, 1 / 5], [2 / 3, 1 / 5, 0]]) + actual = cv.sim_to_dist(x, "membership") + assert_almost_equal(actual, expected, decimal=10) + + +def test_sim_2_dist_membership_error(): + """Test similarity to distance method with the membership metric when there is an input error.""" + x = np.array([[1, 0, -7], [0, 1, 3], [-7, 3, 1]]) + assert_raises(ValueError, cv.sim_to_dist, x, "membership") + + +def test_sim_2_dist_invalid_metric(): + """Test similarity to distance method with an unsupported metric.""" + assert_raises(ValueError, cv.sim_to_dist, np.ones(5), "testing") + + +def test_sim_2_dist_non_symmetric(): + """Test the invalid 2D symmetric matrix error.""" + x = np.array([[1, 2], [4, 5]]) + assert_raises(ValueError, cv.sim_to_dist, x, "reverse") + + +# Tests for individual metrics + + +def test_reverse(): + """Test the reverse function for similarity to distance conversion.""" + x = np.array([[3, 1, 1], [1, 3, 0], [1, 0, 3]]) + expected = np.array([[0, 2, 2], [2, 0, 3], [2, 3, 0]]) + actual = cv.reverse(x) + assert_equal(actual, expected) + + +def test_reciprocal(): + """Test the reverse function for similarity to distance conversion.""" + x = np.array([[1, 0.25, 0.40], [0.25, 1, 0.625], [0.40, 0.625, 1]]) + expected = np.array([[1, 4, 2.5], [4, 1, 1.6], [2.5, 1.6, 1]]) + actual = cv.reciprocal(x) + assert_equal(actual, expected) + + +def test_reciprocal_error(): + """Test the reverse function with incorrect input values.""" + # zero value for similarity (causes divide by zero issues) + x = np.array([[0, 4], [3, 2]]) + assert_raises(ValueError, cv.reciprocal, x) + # negative value for similarity (distance cannot be negative) + y = np.array([[1, -4], [3, 2]]) + assert_raises(ValueError, cv.reciprocal, y) + + +def test_exponential(): + """Test the exponential function for similarity to distance conversion.""" + x = np.array([[1, 0.25, 0.40], [0.25, 1, 0.625], [0.40, 0.625, 1]]) + expected = np.array( + [ + [0, 1.38629436112, 0.91629073187], + [1.38629436112, 0, 0.47000362924], + [0.91629073187, 0.47000362924, 0], + ] + ) + actual = cv.exponential(x) + assert_almost_equal(actual, expected, decimal=10) + + +def test_exponential_error(): + """Test the exponential function when max similarity is zero.""" + x = np.zeros((4, 4)) + assert_raises(ValueError, cv.exponential, x) + + +def test_gaussian(): + """Test the gaussian function for similarity to distance conversion.""" + x = np.array([[1, 0.25, 0.40], [0.25, 1, 0.625], [0.40, 0.625, 1]]) + expected = np.array( + [ + [0, 1.17741002252, 0.95723076208], + [1.17741002252, 0, 0.68556810693], + [0.95723076208, 0.68556810693, 0], + ] + ) + actual = cv.gaussian(x) + assert_almost_equal(actual, expected, decimal=10) + + +def test_gaussian_error(): + """Test the gaussian function when max similarity is zero.""" + x = np.zeros((4, 4)) + assert_raises(ValueError, cv.gaussian, x) + + +def test_correlation(): + """Test the correlation to distance conversion function.""" + x = np.array([[1, 0.5, 0.2], [0.5, 1, -0.2], [0.2, -0.2, 1]]) + # expected = sqrt(1-x) + expected = np.array( + [ + [0, 0.70710678118, 0.894427191], + [0.70710678118, 0, 1.09544511501], + [0.894427191, 1.09544511501, 0], + ] + ) + actual = cv.correlation(x) + assert_almost_equal(actual, expected, decimal=10) + + +def test_correlation_error(): + """Test the correlation function with an out of bounds array.""" + x = np.array([[1, 0, -7], [0, 1, 3], [-7, 3, 1]]) + assert_raises(ValueError, cv.correlation, x) + + +def test_transition(): + """Test the transition function for frequency to distance conversion.""" + x = np.array([[4, 9, 1], [9, 1, 25], [1, 25, 16]]) + expected = np.array([[(1 / 2), (1 / 3), 1], [(1 / 3), 1, (1 / 5)], [1, (1 / 5), (1 / 4)]]) + + actual = cv.transition(x) + assert_almost_equal(actual, expected, decimal=10) + + +def test_co_occurrence(): + """Test the co-occurrence conversion function.""" + x = np.array([[1, 2, 3], [2, 1, 3], [3, 3, 1]]) + expected = np.array( + [ + [1 / (19 / 121 + 1), 1 / (38 / 121 + 1), 1 / (57 / 121 + 1)], + [1 / (38 / 121 + 1), 1 / (19 / 121 + 1), 1 / (57 / 121 + 1)], + [1 / (57 / 121 + 1), 1 / (57 / 121 + 1), 1 / (19 / 121 + 1)], + ] + ) + actual = cv.co_occurrence(x) + assert_almost_equal(actual, expected, decimal=10) + + +def test_gravity(): + """Test the gravity conversion function.""" + x = np.array([[1, 2, 3], [2, 1, 3], [3, 3, 1]]) + expected = np.array( + [ + [2.5235730726, 1.7844356324, 1.45698559277], + [1.7844356324, 2.5235730726, 1.45698559277], + [1.45698559277, 1.45698559277, 2.5235730726], + ] + ) + actual = cv.gravity(x) + assert_almost_equal(actual, expected, decimal=10) + + +def test_probability(): + """Test the probability to distance conversion function.""" + x = np.array([[0.3, 0.7], [0.5, 0.5]]) + expected = np.array([[1.8116279322, 1.1356324735], [1.3819765979, 1.3819765979]]) + actual = cv.probability(x) + assert_almost_equal(actual, expected, decimal=10) + + +def test_probability_error(): + """Test the correlation function with an out of bounds array.""" + # negative value for probability + x = np.array([[-0.5]]) + assert_raises(ValueError, cv.probability, x) + # too large value for probability + y = np.array([[3]]) + assert_raises(ValueError, cv.probability, y) + # zero value for probability (causes divide by zero issues) + z = np.array([[0]]) + assert_raises(ValueError, cv.probability, z) + + +def test_covariance(): + """Test the covariance to distance conversion function.""" + x = np.array([[4, -4], [-4, 6]]) + expected = np.array([[0, 4.24264068712], [4.24264068712, 0]]) + actual = cv.covariance(x) + assert_almost_equal(actual, expected, decimal=10) + + +def test_covariance_error(): + """Test the covariance function when input contains a negative variance.""" + x = np.array([[-4, 4], [4, 6]]) + assert_raises(ValueError, cv.covariance, x) diff --git a/selector/measures/tests/test_diversity.py b/selector/measures/tests/test_diversity.py index 1d606526..1f4e23da 100644 --- a/selector/measures/tests/test_diversity.py +++ b/selector/measures/tests/test_diversity.py @@ -1,363 +1,363 @@ -# -*- coding: utf-8 -*- -# -# The Selector is a Python library of algorithms for selecting diverse -# subsets of data for machine-learning. -# -# Copyright (C) 2022-2024 The QC-Devs Community -# -# This file is part of Selector. -# -# Selector is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 -# of the License, or (at your option) any later version. -# -# Selector is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see -# -# -- - -"""Test Diversity Module.""" -import warnings - -import numpy as np -import pytest -from numpy.testing import assert_almost_equal, assert_equal, assert_raises, assert_warns - -from selector.measures.diversity import ( - compute_diversity, - explicit_diversity_index, - gini_coefficient, - hypersphere_overlap_of_subset, - logdet, - nearest_average_tanimoto, - shannon_entropy, - wdud, -) - -# each row is a feature and each column is a molecule -sample1 = np.array([[4, 2, 6], [4, 9, 6], [2, 5, 0], [2, 0, 9], [5, 3, 0]]) - -# each row is a molecule and each column is a feature (scipy) -sample2 = np.array([[1, 1, 0, 0, 0], [0, 1, 1, 0, 0], [0, 0, 0, 1, 0], [0, 0, 0, 0, 1]]) - -sample3 = np.array([[1, 4], [3, 2]]) - -sample4 = np.array([[1, 0, 1], [0, 1, 1]]) - -sample5 = np.array([[0, 2, 4, 0], [1, 2, 4, 0], [2, 2, 4, 0]]) - -sample6 = np.array([[1, 0, 1, 0], [0, 1, 1, 0], [1, 0, 1, 0], [0, 0, 1, 0]]) - -sample7 = np.array([[1, 0, 1, 0] for _ in range(4)]) - -sample8 = np.array([[1, 2, 3], [1, 2, 3], [1, 2, 3]]) - - -def test_compute_diversity_specified(): - """Test compute diversity with a specified div_type.""" - comp_div = compute_diversity(sample6, "shannon_entropy", normalize=False, truncation=False) - expected = 1.81 - assert round(comp_div, 2) == expected - - -def test_compute_diversity_hyperspheres(): - """Test compute diversity with two arguments for hypersphere_overlap method""" - corner_pts = np.array([[0.0, 0.0], [0.0, 1.0], [1.0, 0.0], [1.0, 1.0]]) - centers_pts = np.array([[0.5, 0.5]] * (100 - 4)) - pts = np.vstack((corner_pts, centers_pts)) - - comp_div = compute_diversity(pts, div_type="hypersphere_overlap", features=pts) - # Expected = overlap + edge penalty - expected = (100.0 * 96 * 95 * 0.5) + 2.0 - assert_almost_equal(comp_div, expected) - - -def test_compute_diversity_hypersphere_error(): - """Test compute diversity with hypersphere metric and no molecule library given.""" - assert_raises(ValueError, compute_diversity, sample5, "hypersphere_overlap") - - -def test_compute_diversity_edi(): - """Test compute diversity with explicit diversity index div_type""" - z = np.array([[0, 1, 2], [1, 2, 0], [2, 0, 1]]) - cs = 1 - expected = 56.39551204 - actual = compute_diversity(z, "explicit_diversity_index", cs=cs) - assert_almost_equal(expected, actual) - - -def test_compute_diversity_edi_no_cs_error(): - """Test compute diversity with explicit diversity index and no `cs` value given.""" - assert_raises(ValueError, compute_diversity, sample5, "explicit_diversity_index") - - -def test_compute_diversity_edi_zero_error(): - """Test compute diversity with explicit diversity index and `cs` = 0.""" - assert_raises(ValueError, compute_diversity, sample5, "explicit diversity index", cs=0) - - -def test_compute_diversity_invalid(): - """Test compute diversity with a non-supported div_type.""" - assert_raises(ValueError, compute_diversity, sample1, "diversity_type") - - -def test_logdet(): - """Test the log determinant function with predefined subset matrix.""" - sel = logdet(sample3) - expected = np.log(131) - assert_almost_equal(sel, expected) - - -def test_logdet_non_square_matrix(): - """Test the log determinant function with a rectangular matrix.""" - sel = logdet(sample4) - expected = np.log(8) - assert_almost_equal(sel, expected) - - -def test_shannon_entropy(): - """Test the shannon entropy function with example from the original paper.""" - - # example taken from figure 1 of 10.1021/ci900159f - x1 = np.array([[1, 0, 1, 0], [0, 1, 1, 0], [1, 0, 1, 0], [0, 0, 1, 0]]) - expected = 1.81 - assert round(shannon_entropy(x1, normalize=False, truncation=False), 2) == expected - - x2 = np.vstack((x1, [1, 1, 1, 0])) - expected = 1.94 - assert round(shannon_entropy(x2, normalize=False, truncation=False), 2) == expected - - x3 = np.vstack((x1, [0, 1, 0, 1])) - expected = 3.39 - assert round(shannon_entropy(x3, normalize=False, truncation=False), 2) == expected - - -def test_shannon_entropy_normalize(): - """Test the shannon entropy function with normalization.""" - x1 = np.array([[1, 0, 1, 0], [0, 1, 1, 0], [1, 0, 1, 0], [0, 0, 1, 0]]) - expected = 1.81 / (x1.shape[1] * np.log2(2) / 2) - assert_almost_equal( - actual=shannon_entropy(x1, normalize=True, truncation=False), - desired=expected, - decimal=2, - ) - - -def test_shannon_entropy_warning(): - """Test the shannon entropy function gives warning when normalization is True and truncation is True.""" - x1 = np.array([[1, 0, 1, 0], [0, 1, 1, 0], [1, 0, 1, 0], [0, 0, 1, 0]]) - with pytest.warns(UserWarning): - shannon_entropy(x1, normalize=True, truncation=True) - - -def test_shannon_entropy_binary_error(): - """Test the shannon entropy function raises error with a non binary matrix.""" - assert_raises(ValueError, shannon_entropy, sample5) - - -def test_explicit_diversity_index(): - """Test the explicit diversity index function.""" - z = np.array([[0, 1, 2], [1, 2, 0], [2, 0, 1]]) - cs = 1 - nc = 3 - sdi = 0.75 / 0.7332902012 - cr = -1 * 0.4771212547 - edi = 0.5456661753 * 0.7071067811865476 - edi_scaled = 56.395512045413 - value = explicit_diversity_index(z, cs) - assert_almost_equal(value, edi_scaled, decimal=8) - - -def test_wdud_uniform(): - """Test wdud when a feature has uniform distribution.""" - uni = np.arange(0, 50000)[:, None] - wdud_val = wdud(uni) - expected = 0 - assert_almost_equal(wdud_val, expected, decimal=4) - - -def test_wdud_repeat_yi(): - """Test wdud when a feature has multiple identical values.""" - dist = np.array([[0, 0.5, 0.5, 0.75, 1]]).T - wdud_val = wdud(dist) - # calculated using wolfram alpha: - expected = 0.065 + 0.01625 + 0.02125 - assert_almost_equal(wdud_val, expected, decimal=4) - - -def test_wdud_mult_features(): - """Test wdud when there are multiple features per molecule.""" - dist = np.array( - [ - [0, 0.5, 0.5, 0.75, 1], - [0, 0.5, 0.5, 0.75, 1], - [0, 0.5, 0.5, 0.75, 1], - [0, 0.5, 0.5, 0.75, 1], - ] - ).T - wdud_val = wdud(dist) - # calculated using wolfram alpha: - expected = 0.065 + 0.01625 + 0.02125 - assert_almost_equal(wdud_val, expected, decimal=4) - - -def test_wdud_dimension_error(): - """Test wdud method raises error when input has incorrect dimensions.""" - arr = np.zeros((2, 2, 2)) - assert_raises(ValueError, wdud, arr) - - -def test_wdud_normalization_error(): - """Test wdud method raises error when normalization fails.""" - assert_raises(ValueError, wdud, sample8) - - -def test_wdud_warning_normalization(): - """Test wdud method gives warning when normalization fails.""" - warning_message = ( - "Some of the features are constant which will cause the normalization to fail. " - + "Now removing them." - ) - with pytest.warns() as record: - wdud(sample6) - - # check that the message matches - assert record[0].message.args[0] == warning_message - - -def test_hypersphere_overlap_of_subset_with_only_corners_and_center(): - """Test the hypersphere overlap method with predefined matrix.""" - corner_pts = np.array([[0.0, 0.0], [0.0, 1.0], [1.0, 0.0], [1.0, 1.0]]) - # Many duplicate pts cause r_0 to be much smaller than 1.0, - # which is required due to normalization of the feature space - centers_pts = np.array([[0.5, 0.5]] * (100 - 4)) - pts = np.vstack((corner_pts, centers_pts)) - - # Overlap should be all coming from the centers - expected_overlap = 100.0 * 96 * 95 * 0.5 - # The edge penalty should all be from the corner pts - lam = 1.0 / 2.0 # Default lambda chosen from paper. - expected_edge = lam * 4.0 - expected = expected_overlap + expected_edge - true = hypersphere_overlap_of_subset(pts, pts) - assert_almost_equal(true, expected) - - -def test_hypersphere_normalization_error(): - """Test the hypersphere overlap method raises error when normalization fails.""" - assert_raises(ValueError, hypersphere_overlap_of_subset, sample7, sample7) - - -def test_hypersphere_radius_warning(): - """Test the hypersphere overlap method gives warning when radius is too large.""" - corner_pts = np.array([[0.0, 0.0], [0.0, 2.0], [2.0, 0.0], [2.0, 2.0]]) - assert_warns(Warning, hypersphere_overlap_of_subset, corner_pts, corner_pts) - - -def test_gini_coefficient_of_non_diverse_set(): - """Test Gini coefficient of the least diverse set. Expected return is zero.""" - # Finger-prints where columns are all the same - numb_molecules = 5 - numb_features = 10 - # Transpose so that the columns are all the same, note first made the rows all same - single_fingerprint = list(np.random.choice([0, 1], size=(numb_features,))) - finger_prints = np.array([single_fingerprint] * numb_molecules).T - - result = gini_coefficient(finger_prints) - # Since they are all the same, then gini coefficient should be zero. - assert_almost_equal(result, 0.0, decimal=8) - - -def test_gini_coefficient_non_binary_error(): - """Test Gini coefficient error when input is not binary.""" - assert_raises(ValueError, gini_coefficient, np.array([[7, 0], [2, 1]])) - - -def test_gini_coefficient_dimension_error(): - """Test Gini coefficient error when input has incorrect dimensions.""" - assert_raises(ValueError, gini_coefficient, np.array([1, 0, 0, 0])) - - -def test_gini_coefficient_of_most_diverse_set(): - """Test Gini coefficient of the most diverse set.""" - # Finger-prints where one feature has more `wealth` than all others. - # Note: Transpose is done so one column has all ones. - finger_prints = np.array( - [ - [1, 1, 1, 1, 1, 1, 1], - ] - + [[0, 0, 0, 0, 0, 0, 0]] * 100000 - ).T - result = gini_coefficient(finger_prints) - # Since they are all the same, then gini coefficient should be zero. - assert_almost_equal(result, 1.0, decimal=4) - - -def test_gini_coefficient_with_alternative_definition(): - """Test Gini coefficient with alternative definition.""" - # Finger-prints where they are all different - numb_features = 4 - finger_prints = np.array([[1, 1, 1, 1], [0, 1, 1, 1], [0, 0, 1, 1], [0, 0, 0, 1]]) - result = gini_coefficient(finger_prints) - - # Alternative definition from wikipedia - b = numb_features + 1 - desired = ( - numb_features + 1 - 2 * ((b - 1) + (b - 2) * 2 + (b - 3) * 3 + (b - 4) * 4) / (10) - ) / numb_features - assert_almost_equal(result, desired) - - -def test_nearest_average_tanimoto_bit(): - """Test the nearest_average_tanimoto function with binary input.""" - nat = nearest_average_tanimoto(sample2) - shortest_tani = [0.3333333, 0.3333333, 0, 0] - average = np.average(shortest_tani) - assert_almost_equal(nat, average) - - -def test_nearest_average_tanimoto(): - """Test the nearest_average_tanimoto function with non-binary input.""" - nat = nearest_average_tanimoto(sample3) - shortest_tani = [(11 / 19), (11 / 19)] - average = np.average(shortest_tani) - assert_equal(nat, average) - - -def test_nearest_average_tanimoto_3_x_3(): - """Testpyth the nearest_average_tanimoto function with a 3x3 matrix.""" - # all unequal distances b/w points - x = np.array([[0, 1, 2], [3, 4, 5], [4, 5, 6]]) - nat_x = nearest_average_tanimoto(x) - avg_x = 0.749718574108818 - assert_equal(nat_x, avg_x) - # one point equidistant from the other two - y = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]]) - nat_y = nearest_average_tanimoto(y) - avg_y = 0.4813295920569825 - assert_equal(nat_y, avg_y) - # all points equidistant - z = np.array([[0, 1, 2], [1, 2, 0], [2, 0, 1]]) - nat_z = nearest_average_tanimoto(z) - avg_z = 0.25 - assert_equal(nat_z, avg_z) - - -def test_nearest_average_tanimoto_nonsquare(): - """Test the nearest_average_tanimoto function with non-binary input""" - x = np.array([[3.5, 4.0, 10.5, 0.5], [1.25, 4.0, 7.0, 0.1], [0.0, 0.0, 0.0, 0.0]]) - # nearest neighbor of sample 0, 1, and 2 are sample 1, 0, and 1, respectively. - expected = np.average( - [ - np.sum(x[0] * x[1]) / (np.sum(x[0] ** 2) + np.sum(x[1] ** 2) - np.sum(x[0] * x[1])), - np.sum(x[1] * x[0]) / (np.sum(x[1] ** 2) + np.sum(x[0] ** 2) - np.sum(x[1] * x[0])), - np.sum(x[2] * x[1]) / (np.sum(x[2] ** 2) + np.sum(x[1] ** 2) - np.sum(x[2] * x[1])), - ] - ) - assert_equal(nearest_average_tanimoto(x), expected) +# -*- coding: utf-8 -*- +# +# The Selector is a Python library of algorithms for selecting diverse +# subsets of data for machine-learning. +# +# Copyright (C) 2022-2024 The QC-Devs Community +# +# This file is part of Selector. +# +# Selector is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 +# of the License, or (at your option) any later version. +# +# Selector is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see +# +# -- + +"""Test Diversity Module.""" +import warnings + +import numpy as np +import pytest +from numpy.testing import assert_almost_equal, assert_equal, assert_raises, assert_warns + +from selector.measures.diversity import ( + compute_diversity, + explicit_diversity_index, + gini_coefficient, + hypersphere_overlap_of_subset, + logdet, + nearest_average_tanimoto, + shannon_entropy, + wdud, +) + +# each row is a feature and each column is a molecule +sample1 = np.array([[4, 2, 6], [4, 9, 6], [2, 5, 0], [2, 0, 9], [5, 3, 0]]) + +# each row is a molecule and each column is a feature (scipy) +sample2 = np.array([[1, 1, 0, 0, 0], [0, 1, 1, 0, 0], [0, 0, 0, 1, 0], [0, 0, 0, 0, 1]]) + +sample3 = np.array([[1, 4], [3, 2]]) + +sample4 = np.array([[1, 0, 1], [0, 1, 1]]) + +sample5 = np.array([[0, 2, 4, 0], [1, 2, 4, 0], [2, 2, 4, 0]]) + +sample6 = np.array([[1, 0, 1, 0], [0, 1, 1, 0], [1, 0, 1, 0], [0, 0, 1, 0]]) + +sample7 = np.array([[1, 0, 1, 0] for _ in range(4)]) + +sample8 = np.array([[1, 2, 3], [1, 2, 3], [1, 2, 3]]) + + +def test_compute_diversity_specified(): + """Test compute diversity with a specified div_type.""" + comp_div = compute_diversity(sample6, "shannon_entropy", normalize=False, truncation=False) + expected = 1.81 + assert round(comp_div, 2) == expected + + +def test_compute_diversity_hyperspheres(): + """Test compute diversity with two arguments for hypersphere_overlap method""" + corner_pts = np.array([[0.0, 0.0], [0.0, 1.0], [1.0, 0.0], [1.0, 1.0]]) + centers_pts = np.array([[0.5, 0.5]] * (100 - 4)) + pts = np.vstack((corner_pts, centers_pts)) + + comp_div = compute_diversity(pts, div_type="hypersphere_overlap", features=pts) + # Expected = overlap + edge penalty + expected = (100.0 * 96 * 95 * 0.5) + 2.0 + assert_almost_equal(comp_div, expected) + + +def test_compute_diversity_hypersphere_error(): + """Test compute diversity with hypersphere metric and no molecule library given.""" + assert_raises(ValueError, compute_diversity, sample5, "hypersphere_overlap") + + +def test_compute_diversity_edi(): + """Test compute diversity with explicit diversity index div_type""" + z = np.array([[0, 1, 2], [1, 2, 0], [2, 0, 1]]) + cs = 1 + expected = 56.39551204 + actual = compute_diversity(z, "explicit_diversity_index", cs=cs) + assert_almost_equal(expected, actual) + + +def test_compute_diversity_edi_no_cs_error(): + """Test compute diversity with explicit diversity index and no `cs` value given.""" + assert_raises(ValueError, compute_diversity, sample5, "explicit_diversity_index") + + +def test_compute_diversity_edi_zero_error(): + """Test compute diversity with explicit diversity index and `cs` = 0.""" + assert_raises(ValueError, compute_diversity, sample5, "explicit diversity index", cs=0) + + +def test_compute_diversity_invalid(): + """Test compute diversity with a non-supported div_type.""" + assert_raises(ValueError, compute_diversity, sample1, "diversity_type") + + +def test_logdet(): + """Test the log determinant function with predefined subset matrix.""" + sel = logdet(sample3) + expected = np.log(131) + assert_almost_equal(sel, expected) + + +def test_logdet_non_square_matrix(): + """Test the log determinant function with a rectangular matrix.""" + sel = logdet(sample4) + expected = np.log(8) + assert_almost_equal(sel, expected) + + +def test_shannon_entropy(): + """Test the shannon entropy function with example from the original paper.""" + + # example taken from figure 1 of 10.1021/ci900159f + x1 = np.array([[1, 0, 1, 0], [0, 1, 1, 0], [1, 0, 1, 0], [0, 0, 1, 0]]) + expected = 1.81 + assert round(shannon_entropy(x1, normalize=False, truncation=False), 2) == expected + + x2 = np.vstack((x1, [1, 1, 1, 0])) + expected = 1.94 + assert round(shannon_entropy(x2, normalize=False, truncation=False), 2) == expected + + x3 = np.vstack((x1, [0, 1, 0, 1])) + expected = 3.39 + assert round(shannon_entropy(x3, normalize=False, truncation=False), 2) == expected + + +def test_shannon_entropy_normalize(): + """Test the shannon entropy function with normalization.""" + x1 = np.array([[1, 0, 1, 0], [0, 1, 1, 0], [1, 0, 1, 0], [0, 0, 1, 0]]) + expected = 1.81 / (x1.shape[1] * np.log2(2) / 2) + assert_almost_equal( + actual=shannon_entropy(x1, normalize=True, truncation=False), + desired=expected, + decimal=2, + ) + + +def test_shannon_entropy_warning(): + """Test the shannon entropy function gives warning when normalization is True and truncation is True.""" + x1 = np.array([[1, 0, 1, 0], [0, 1, 1, 0], [1, 0, 1, 0], [0, 0, 1, 0]]) + with pytest.warns(UserWarning): + shannon_entropy(x1, normalize=True, truncation=True) + + +def test_shannon_entropy_binary_error(): + """Test the shannon entropy function raises error with a non binary matrix.""" + assert_raises(ValueError, shannon_entropy, sample5) + + +def test_explicit_diversity_index(): + """Test the explicit diversity index function.""" + z = np.array([[0, 1, 2], [1, 2, 0], [2, 0, 1]]) + cs = 1 + nc = 3 + sdi = 0.75 / 0.7332902012 + cr = -1 * 0.4771212547 + edi = 0.5456661753 * 0.7071067811865476 + edi_scaled = 56.395512045413 + value = explicit_diversity_index(z, cs) + assert_almost_equal(value, edi_scaled, decimal=8) + + +def test_wdud_uniform(): + """Test wdud when a feature has uniform distribution.""" + uni = np.arange(0, 50000)[:, None] + wdud_val = wdud(uni) + expected = 0 + assert_almost_equal(wdud_val, expected, decimal=4) + + +def test_wdud_repeat_yi(): + """Test wdud when a feature has multiple identical values.""" + dist = np.array([[0, 0.5, 0.5, 0.75, 1]]).T + wdud_val = wdud(dist) + # calculated using wolfram alpha: + expected = 0.065 + 0.01625 + 0.02125 + assert_almost_equal(wdud_val, expected, decimal=4) + + +def test_wdud_mult_features(): + """Test wdud when there are multiple features per molecule.""" + dist = np.array( + [ + [0, 0.5, 0.5, 0.75, 1], + [0, 0.5, 0.5, 0.75, 1], + [0, 0.5, 0.5, 0.75, 1], + [0, 0.5, 0.5, 0.75, 1], + ] + ).T + wdud_val = wdud(dist) + # calculated using wolfram alpha: + expected = 0.065 + 0.01625 + 0.02125 + assert_almost_equal(wdud_val, expected, decimal=4) + + +def test_wdud_dimension_error(): + """Test wdud method raises error when input has incorrect dimensions.""" + arr = np.zeros((2, 2, 2)) + assert_raises(ValueError, wdud, arr) + + +def test_wdud_normalization_error(): + """Test wdud method raises error when normalization fails.""" + assert_raises(ValueError, wdud, sample8) + + +def test_wdud_warning_normalization(): + """Test wdud method gives warning when normalization fails.""" + warning_message = ( + "Some of the features are constant which will cause the normalization to fail. " + + "Now removing them." + ) + with pytest.warns() as record: + wdud(sample6) + + # check that the message matches + assert record[0].message.args[0] == warning_message + + +def test_hypersphere_overlap_of_subset_with_only_corners_and_center(): + """Test the hypersphere overlap method with predefined matrix.""" + corner_pts = np.array([[0.0, 0.0], [0.0, 1.0], [1.0, 0.0], [1.0, 1.0]]) + # Many duplicate pts cause r_0 to be much smaller than 1.0, + # which is required due to normalization of the feature space + centers_pts = np.array([[0.5, 0.5]] * (100 - 4)) + pts = np.vstack((corner_pts, centers_pts)) + + # Overlap should be all coming from the centers + expected_overlap = 100.0 * 96 * 95 * 0.5 + # The edge penalty should all be from the corner pts + lam = 1.0 / 2.0 # Default lambda chosen from paper. + expected_edge = lam * 4.0 + expected = expected_overlap + expected_edge + true = hypersphere_overlap_of_subset(pts, pts) + assert_almost_equal(true, expected) + + +def test_hypersphere_normalization_error(): + """Test the hypersphere overlap method raises error when normalization fails.""" + assert_raises(ValueError, hypersphere_overlap_of_subset, sample7, sample7) + + +def test_hypersphere_radius_warning(): + """Test the hypersphere overlap method gives warning when radius is too large.""" + corner_pts = np.array([[0.0, 0.0], [0.0, 2.0], [2.0, 0.0], [2.0, 2.0]]) + assert_warns(Warning, hypersphere_overlap_of_subset, corner_pts, corner_pts) + + +def test_gini_coefficient_of_non_diverse_set(): + """Test Gini coefficient of the least diverse set. Expected return is zero.""" + # Finger-prints where columns are all the same + numb_molecules = 5 + numb_features = 10 + # Transpose so that the columns are all the same, note first made the rows all same + single_fingerprint = list(np.random.choice([0, 1], size=(numb_features,))) + finger_prints = np.array([single_fingerprint] * numb_molecules).T + + result = gini_coefficient(finger_prints) + # Since they are all the same, then gini coefficient should be zero. + assert_almost_equal(result, 0.0, decimal=8) + + +def test_gini_coefficient_non_binary_error(): + """Test Gini coefficient error when input is not binary.""" + assert_raises(ValueError, gini_coefficient, np.array([[7, 0], [2, 1]])) + + +def test_gini_coefficient_dimension_error(): + """Test Gini coefficient error when input has incorrect dimensions.""" + assert_raises(ValueError, gini_coefficient, np.array([1, 0, 0, 0])) + + +def test_gini_coefficient_of_most_diverse_set(): + """Test Gini coefficient of the most diverse set.""" + # Finger-prints where one feature has more `wealth` than all others. + # Note: Transpose is done so one column has all ones. + finger_prints = np.array( + [ + [1, 1, 1, 1, 1, 1, 1], + ] + + [[0, 0, 0, 0, 0, 0, 0]] * 100000 + ).T + result = gini_coefficient(finger_prints) + # Since they are all the same, then gini coefficient should be zero. + assert_almost_equal(result, 1.0, decimal=4) + + +def test_gini_coefficient_with_alternative_definition(): + """Test Gini coefficient with alternative definition.""" + # Finger-prints where they are all different + numb_features = 4 + finger_prints = np.array([[1, 1, 1, 1], [0, 1, 1, 1], [0, 0, 1, 1], [0, 0, 0, 1]]) + result = gini_coefficient(finger_prints) + + # Alternative definition from wikipedia + b = numb_features + 1 + desired = ( + numb_features + 1 - 2 * ((b - 1) + (b - 2) * 2 + (b - 3) * 3 + (b - 4) * 4) / (10) + ) / numb_features + assert_almost_equal(result, desired) + + +def test_nearest_average_tanimoto_bit(): + """Test the nearest_average_tanimoto function with binary input.""" + nat = nearest_average_tanimoto(sample2) + shortest_tani = [0.3333333, 0.3333333, 0, 0] + average = np.average(shortest_tani) + assert_almost_equal(nat, average) + + +def test_nearest_average_tanimoto(): + """Test the nearest_average_tanimoto function with non-binary input.""" + nat = nearest_average_tanimoto(sample3) + shortest_tani = [(11 / 19), (11 / 19)] + average = np.average(shortest_tani) + assert_equal(nat, average) + + +def test_nearest_average_tanimoto_3_x_3(): + """Testpyth the nearest_average_tanimoto function with a 3x3 matrix.""" + # all unequal distances b/w points + x = np.array([[0, 1, 2], [3, 4, 5], [4, 5, 6]]) + nat_x = nearest_average_tanimoto(x) + avg_x = 0.749718574108818 + assert_equal(nat_x, avg_x) + # one point equidistant from the other two + y = np.array([[0, 1, 2], [3, 4, 5], [6, 7, 8]]) + nat_y = nearest_average_tanimoto(y) + avg_y = 0.4813295920569825 + assert_equal(nat_y, avg_y) + # all points equidistant + z = np.array([[0, 1, 2], [1, 2, 0], [2, 0, 1]]) + nat_z = nearest_average_tanimoto(z) + avg_z = 0.25 + assert_equal(nat_z, avg_z) + + +def test_nearest_average_tanimoto_nonsquare(): + """Test the nearest_average_tanimoto function with non-binary input""" + x = np.array([[3.5, 4.0, 10.5, 0.5], [1.25, 4.0, 7.0, 0.1], [0.0, 0.0, 0.0, 0.0]]) + # nearest neighbor of sample 0, 1, and 2 are sample 1, 0, and 1, respectively. + expected = np.average( + [ + np.sum(x[0] * x[1]) / (np.sum(x[0] ** 2) + np.sum(x[1] ** 2) - np.sum(x[0] * x[1])), + np.sum(x[1] * x[0]) / (np.sum(x[1] ** 2) + np.sum(x[0] ** 2) - np.sum(x[1] * x[0])), + np.sum(x[2] * x[1]) / (np.sum(x[2] ** 2) + np.sum(x[1] ** 2) - np.sum(x[2] * x[1])), + ] + ) + assert_equal(nearest_average_tanimoto(x), expected) diff --git a/selector/methods/__init__.py b/selector/methods/__init__.py index 14e39e5d..7a7a99eb 100644 --- a/selector/methods/__init__.py +++ b/selector/methods/__init__.py @@ -1,27 +1,27 @@ -# -*- coding: utf-8 -*- -# -# The Selector is a Python library of algorithms for selecting diverse -# subsets of data for machine-learning. -# -# Copyright (C) 2022-2024 The QC-Devs Community -# -# This file is part of Selector. -# -# Selector is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 -# of the License, or (at your option) any later version. -# -# Selector is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see -# -# -- - -from selector.methods.distance import * -from selector.methods.partition import * -from selector.methods.similarity import * +# -*- coding: utf-8 -*- +# +# The Selector is a Python library of algorithms for selecting diverse +# subsets of data for machine-learning. +# +# Copyright (C) 2022-2024 The QC-Devs Community +# +# This file is part of Selector. +# +# Selector is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 +# of the License, or (at your option) any later version. +# +# Selector is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see +# +# -- + +from selector.methods.distance import * +from selector.methods.partition import * +from selector.methods.similarity import * diff --git a/selector/methods/base.py b/selector/methods/base.py index e49c2663..1dbeaec1 100644 --- a/selector/methods/base.py +++ b/selector/methods/base.py @@ -1,189 +1,189 @@ -# -*- coding: utf-8 -*- -# -# The Selector is a Python library of algorithms for selecting diverse -# subsets of data for machine-learning. -# -# Copyright (C) 2022-2024 The QC-Devs Community -# -# This file is part of Selector. -# -# Selector is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 -# of the License, or (at your option) any later version. -# -# Selector is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see -# -# -- -"""Base class for diversity based subset selection.""" - -import warnings -from abc import ABC, abstractmethod -from typing import List, Iterable, Union - -import numpy as np - -__all__ = ["SelectionBase"] - - -class SelectionBase(ABC): - """Base class for selecting subset of sample points.""" - - def select( - self, - x: np.ndarray, - size: int, - labels: np.ndarray = None, - proportional_selection: bool = True, - ) -> Union[List, Iterable]: - """Return indices representing subset of sample points. - - Parameters - ---------- - x: ndarray of shape (n_samples, n_features) or (n_samples, n_samples) - Feature matrix of `n_samples` samples in `n_features` dimensional feature space. - If fun_distance is `None`, this x is treated as a square pairwise distance matrix. - size: int - Number of sample points to select (i.e. size of the subset). - labels: np.ndarray, optional - Array of integers or strings representing the labels of the clusters that - each sample belongs to. If `None`, the samples are treated as one cluster. - If labels are provided, selection is made from each cluster. - proportional_selection: bool, optional - If True, the number of samples to be selected from each cluster is proportional. - Otherwise, the number of samples to be selected from each cluster is equal. - Default is True. - - Returns - ------- - selected: list - Indices of the selected sample points. - """ - # check size - if size > len(x): - raise ValueError( - f"Size of subset {size} cannot be larger than number of samples {len(x)}." - ) - - # if labels are not provided, indices selected from one cluster is returned - if labels is None: - return self.select_from_cluster(x, size) - - # check labels are consistent with number of samples - if len(labels) != len(x): - raise ValueError( - f"Number of labels {len(labels)} does not match number of samples {len(x)}." - ) - - selected_ids = [] - - # compute the number of samples (i.e. population or pop) in each cluster - unique_labels, unique_label_counts = np.unique(labels, return_counts=True) - num_clusters = len(unique_labels) - pop_clusters = dict(zip(unique_labels, unique_label_counts)) - # compute number of samples to be selected from each cluster - if proportional_selection: - # make sure that tht total number of samples selected is equal to size - size_each_cluster = size * unique_label_counts / len(labels) - # using np.round to get to the nearest integer - # not using int function directly to avoid truncation of decimal values - size_each_cluster = np.round(size_each_cluster).astype(int) - # make sure each cluster has at least one sample - size_each_cluster[size_each_cluster < 1] = 1 - - # the total number of samples selected from all clusters at this point - size_each_cluster_total = np.sum(size_each_cluster) - # when the total of data points in each class is less than the required number - # add one sample to the smallest cluster iteratively until the total is equal to the - # required number - if size_each_cluster_total < size: - while size_each_cluster_total < size: - # the number of remaining data points in each cluster - size_each_cluster_remaining = unique_label_counts - size_each_cluster_total - # skip the clusters with no data points left - size_each_cluster_remaining[size_each_cluster_remaining == 0] = np.inf - smallest_cluster_index = np.argmin(size_each_cluster_remaining) - size_each_cluster[smallest_cluster_index] += 1 - size_each_cluster_total += 1 - # when the total of data points in each class is more than the required number - # we need to remove samples from the largest clusters - elif size_each_cluster_total > size: - while size_each_cluster_total > size: - largest_cluster_index = np.argmax(size_each_cluster) - size_each_cluster[largest_cluster_index] -= 1 - size_each_cluster_total -= 1 - # perfect case where the total is equal to the required number - else: - pass - else: - size_each_cluster = size // num_clusters - - # update number of samples to select from each cluster based on the cluster population. - # this is needed when some clusters do not have enough samples in them - # (pop < size_each_cluster) and needs to be done iteratively until all remaining clusters - # have at least size_each_cluster samples - while np.any( - [value <= size_each_cluster for value in pop_clusters.values() if value != 0] - ): - for unique_label in unique_labels: - if pop_clusters[unique_label] != 0: - # get index of sample labelled with unique_label - cluster_ids = np.where(labels == unique_label)[0] - if len(cluster_ids) <= size_each_cluster: - # all samples in the cluster are selected & population becomes zero - selected_ids.append(cluster_ids) - pop_clusters[unique_label] = 0 - # update number of samples to be selected from each cluster - totally_used_clusters = list(pop_clusters.values()).count(0) - size_each_cluster = (size - len(np.hstack(selected_ids))) // ( - num_clusters - totally_used_clusters - ) - - warnings.warn( - f"Number of molecules in one cluster is less than" - f" {size}/{num_clusters}.\nNumber of selected " - f"molecules might be less than desired.\nIn order to avoid this " - f"problem. Try to use less number of clusters." - ) - # save the number of samples to be selected from each cluster in an array - size_each_cluster = np.full(num_clusters, size_each_cluster) - - for unique_label, size_sub in zip(unique_labels, size_each_cluster): - if pop_clusters[unique_label] != 0: - # sample size_each_cluster ids from cluster labeled unique_label - cluster_ids = np.where(labels == unique_label)[0] - selected = self.select_from_cluster(x, size_sub, cluster_ids) - selected_ids.append(cluster_ids[selected]) - - return np.hstack(selected_ids).flatten().tolist() - - @abstractmethod - def select_from_cluster( - self, x: np.ndarray, size: int, labels: np.ndarray = None - ) -> np.ndarray: # pragma: no cover - """Return indices representing subset of sample points from one cluster. - - Parameters - ---------- - x: ndarray of shape (n_samples, n_features) or (n_samples, n_samples) - Feature matrix of `n_samples` samples in `n_features` dimensional feature space. - If fun_distance is `None`, this x is treated as a square pairwise distance matrix. - size: int - Number of sample points to select (i.e. size of the subset). - labels: np.ndarray, optional - Array of integers or strings representing the labels of the clusters that - each sample belongs to. If `None`, the samples are treated as one cluster. - If labels are provided, selection is made from each cluster. - - Returns - ------- - selected: list - Indices of the selected sample points. - """ - raise NotImplementedError +# -*- coding: utf-8 -*- +# +# The Selector is a Python library of algorithms for selecting diverse +# subsets of data for machine-learning. +# +# Copyright (C) 2022-2024 The QC-Devs Community +# +# This file is part of Selector. +# +# Selector is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 +# of the License, or (at your option) any later version. +# +# Selector is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see +# +# -- +"""Base class for diversity based subset selection.""" + +import warnings +from abc import ABC, abstractmethod +from typing import List, Iterable, Union + +import numpy as np + +__all__ = ["SelectionBase"] + + +class SelectionBase(ABC): + """Base class for selecting subset of sample points.""" + + def select( + self, + x: np.ndarray, + size: int, + labels: np.ndarray = None, + proportional_selection: bool = True, + ) -> Union[List, Iterable]: + """Return indices representing subset of sample points. + + Parameters + ---------- + x: ndarray of shape (n_samples, n_features) or (n_samples, n_samples) + Feature matrix of `n_samples` samples in `n_features` dimensional feature space. + If fun_distance is `None`, this x is treated as a square pairwise distance matrix. + size: int + Number of sample points to select (i.e. size of the subset). + labels: np.ndarray, optional + Array of integers or strings representing the labels of the clusters that + each sample belongs to. If `None`, the samples are treated as one cluster. + If labels are provided, selection is made from each cluster. + proportional_selection: bool, optional + If True, the number of samples to be selected from each cluster is proportional. + Otherwise, the number of samples to be selected from each cluster is equal. + Default is True. + + Returns + ------- + selected: list + Indices of the selected sample points. + """ + # check size + if size > len(x): + raise ValueError( + f"Size of subset {size} cannot be larger than number of samples {len(x)}." + ) + + # if labels are not provided, indices selected from one cluster is returned + if labels is None: + return self.select_from_cluster(x, size) + + # check labels are consistent with number of samples + if len(labels) != len(x): + raise ValueError( + f"Number of labels {len(labels)} does not match number of samples {len(x)}." + ) + + selected_ids = [] + + # compute the number of samples (i.e. population or pop) in each cluster + unique_labels, unique_label_counts = np.unique(labels, return_counts=True) + num_clusters = len(unique_labels) + pop_clusters = dict(zip(unique_labels, unique_label_counts)) + # compute number of samples to be selected from each cluster + if proportional_selection: + # make sure that tht total number of samples selected is equal to size + size_each_cluster = size * unique_label_counts / len(labels) + # using np.round to get to the nearest integer + # not using int function directly to avoid truncation of decimal values + size_each_cluster = np.round(size_each_cluster).astype(int) + # make sure each cluster has at least one sample + size_each_cluster[size_each_cluster < 1] = 1 + + # the total number of samples selected from all clusters at this point + size_each_cluster_total = np.sum(size_each_cluster) + # when the total of data points in each class is less than the required number + # add one sample to the smallest cluster iteratively until the total is equal to the + # required number + if size_each_cluster_total < size: + while size_each_cluster_total < size: + # the number of remaining data points in each cluster + size_each_cluster_remaining = unique_label_counts - size_each_cluster_total + # skip the clusters with no data points left + size_each_cluster_remaining[size_each_cluster_remaining == 0] = np.inf + smallest_cluster_index = np.argmin(size_each_cluster_remaining) + size_each_cluster[smallest_cluster_index] += 1 + size_each_cluster_total += 1 + # when the total of data points in each class is more than the required number + # we need to remove samples from the largest clusters + elif size_each_cluster_total > size: + while size_each_cluster_total > size: + largest_cluster_index = np.argmax(size_each_cluster) + size_each_cluster[largest_cluster_index] -= 1 + size_each_cluster_total -= 1 + # perfect case where the total is equal to the required number + else: + pass + else: + size_each_cluster = size // num_clusters + + # update number of samples to select from each cluster based on the cluster population. + # this is needed when some clusters do not have enough samples in them + # (pop < size_each_cluster) and needs to be done iteratively until all remaining clusters + # have at least size_each_cluster samples + while np.any( + [value <= size_each_cluster for value in pop_clusters.values() if value != 0] + ): + for unique_label in unique_labels: + if pop_clusters[unique_label] != 0: + # get index of sample labelled with unique_label + cluster_ids = np.where(labels == unique_label)[0] + if len(cluster_ids) <= size_each_cluster: + # all samples in the cluster are selected & population becomes zero + selected_ids.append(cluster_ids) + pop_clusters[unique_label] = 0 + # update number of samples to be selected from each cluster + totally_used_clusters = list(pop_clusters.values()).count(0) + size_each_cluster = (size - len(np.hstack(selected_ids))) // ( + num_clusters - totally_used_clusters + ) + + warnings.warn( + f"Number of molecules in one cluster is less than" + f" {size}/{num_clusters}.\nNumber of selected " + f"molecules might be less than desired.\nIn order to avoid this " + f"problem. Try to use less number of clusters." + ) + # save the number of samples to be selected from each cluster in an array + size_each_cluster = np.full(num_clusters, size_each_cluster) + + for unique_label, size_sub in zip(unique_labels, size_each_cluster): + if pop_clusters[unique_label] != 0: + # sample size_each_cluster ids from cluster labeled unique_label + cluster_ids = np.where(labels == unique_label)[0] + selected = self.select_from_cluster(x, size_sub, cluster_ids) + selected_ids.append(cluster_ids[selected]) + + return np.hstack(selected_ids).flatten().tolist() + + @abstractmethod + def select_from_cluster( + self, x: np.ndarray, size: int, labels: np.ndarray = None + ) -> np.ndarray: # pragma: no cover + """Return indices representing subset of sample points from one cluster. + + Parameters + ---------- + x: ndarray of shape (n_samples, n_features) or (n_samples, n_samples) + Feature matrix of `n_samples` samples in `n_features` dimensional feature space. + If fun_distance is `None`, this x is treated as a square pairwise distance matrix. + size: int + Number of sample points to select (i.e. size of the subset). + labels: np.ndarray, optional + Array of integers or strings representing the labels of the clusters that + each sample belongs to. If `None`, the samples are treated as one cluster. + If labels are provided, selection is made from each cluster. + + Returns + ------- + selected: list + Indices of the selected sample points. + """ + raise NotImplementedError diff --git a/selector/methods/distance.py b/selector/methods/distance.py index 3bc44520..000c7f05 100644 --- a/selector/methods/distance.py +++ b/selector/methods/distance.py @@ -1,701 +1,701 @@ -# -*- coding: utf-8 -*- -# -# The Selector is a Python library of algorithms for selecting diverse -# subsets of data for machine-learning. -# -# Copyright (C) 2022-2024 The QC-Devs Community -# -# This file is part of Selector. -# -# Selector is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 -# of the License, or (at your option) any later version. -# -# Selector is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see -# -# -- -"""Module for Distance-Based Selection Methods.""" - -import bitarray -import numpy as np -from scipy import spatial -from typing import List, Iterable, Union - -from selector.methods.base import SelectionBase -from selector.methods.utils import optimize_radius - -__all__ = [ - "MaxMin", - "MaxSum", - "OptiSim", - "DISE", -] - - -class MaxMin(SelectionBase): - """Select samples using MaxMin algorithm. - - MaxMin is possibly the most widely used method for dissimilarity-based - compound selection. When presented with a dataset of samples, the - initial point is chosen as the dataset's medoid center. Next, the second - point is chosen to be that which is furthest from this initial point. - Subsequently, all following points are selected via the following - logic: - - 1. Find the minimum distance from every point to the already-selected ones. - 2. Select the point which has the maximum distance among those calculated - in the previous step. - - In the current implementation, this method requires or computes the full pairwise-distance - matrix, so it is not recommended for large datasets. - - References - ---------- - [1] Ashton, Mark, et al., Identification of diverse database subsets using - property‐based and fragment‐based molecular descriptions, Quantitative - Structure‐Activity Relationships 21.6 (2002): 598-604. - """ - - def __init__(self, fun_dist=None, ref_index=None): - """ - Initializing class. - - Parameters - ---------- - fun_distance : callable - Function for calculating the pairwise distance between sample points. - `fun_dist(x) -> x_dist` takes a 2D feature array of shape (n_samples, n_features) - and returns a 2D distance array of shape (n_samples, n_samples). - ref_index: int, list, optional - Index of the reference sample to start the selection algorithm from. - It can be an integer, or a list of integers or None. When None, the medoid center is chosen as the reference - sample. - When the `ref_index` is a list for multiple classes, it will be shared among all clusters. - If we want to use different reference indices for each class, we can perform the subset - selection for each class separately where different `ref_index` parameters can be used. - For example, if we have two classes, we can pass `ref_index=[0, 1]` to select samples - from class 0 and `ref_index=[3, 6]` class 1 respectively. - - """ - self.fun_dist = fun_dist - self.ref_index = ref_index - - def select_from_cluster(self, x, size, labels=None) -> Union[List, Iterable]: - """Return selected samples from a cluster based on MaxMin algorithm. - - Parameters - ---------- - x: ndarray of shape (n_samples, n_features) or (n_samples, n_samples) - Feature matrix of `n_samples` samples in `n_features` dimensional feature space, - or the pairwise distance matrix between `n_samples` samples. - If `fun_dist` is `None`, the `x` is assumed to be a square pairwise distance matrix. - size: int - Number of sample points to select (i.e. size of the subset). - labels: np.ndarray - Indices of samples that form a cluster. - - Returns - ------- - selected : Union[List, Iterable] - List of indices of selected samples. - """ - # calculate pairwise distance between points - x_dist = x - if self.fun_dist is not None: - x_dist = self.fun_dist(x) - # check x_dist is a square symmetric matrix - if x_dist.shape[0] != x_dist.shape[1]: - raise ValueError(f"The pairwise distance matrix must be square, got {x_dist.shape}.") - if np.max(abs(x_dist - x_dist.T)) > 1e-8: - raise ValueError("The pairwise distance matrix must be symmetric.") - - if labels is not None: - # extract pairwise distances from full pairwise distance matrix to obtain a new matrix - # that only contains pairwise distances between samples within a given cluster - x_dist = x_dist[labels][:, labels] - - # choosing initial point - selected = get_initial_selection( - x=None, x_dist=x_dist, ref_index=self.ref_index, fun_dist=None - ) - - # select following points until desired number of points have been obtained - while len(selected) < size: - # determine the min pairwise distances between the selected points and all other points - min_distances = np.min(x_dist[selected], axis=0) - # determine which point affords the maximum distance among the minimum distances - # captured in min_distances - new_id = np.argmax(min_distances) - selected.append(new_id) - - selected = [int(i) for i in selected] - - return selected - - -class MaxSum(SelectionBase): - """Select samples using MaxSum algorithm. - - Whereas the goal of the MaxMin algorithm is to maximize the minimum distance - between any pair of distinct elements in the selected subset of a dataset, - the MaxSum algorithm aims to maximize the sum of distances between all - pairs of elements in the selected subset. When presented with a dataset of - samples, the initial point is chosen as the dataset's medoid center. Next, - the second point is chosen to be that which is furthest from this initial - point. Subsequently, all following points are selected via the following - logic: - - 1. Determine the sum of distances from every point to the already-selected ones. - 2. Select the point which has the maximum sum of distances among those calculated - in the previous step. - - References - ---------- - [1] Borodin, Allan, Hyun Chul Lee, and Yuli Ye, Max-sum diversification, monotone - submodular functions and dynamic updates, Proceedings of the 31st ACM SIGMOD-SIGACT-SIGAI - symposium on Principles of Database Systems. 2012. - """ - - def __init__(self, fun_dist=None, ref_index=None): - """ - Initializing class. - - Parameters - ---------- - fun_dist : callable - Function for calculating the pairwise distance between sample points. - `fun_dist(x) -> x_dist` takes a 2D feature array of shape (n_samples, n_features) - and returns a 2D distance array of shape (n_samples, n_samples). - ref_index: int, list, optional - Index of the reference sample to start the selection algorithm from. - It can be an integer, or a list of integers or None. When None, the medoid center is chosen as the reference - sample. - When the `ref_index` is a list for multiple classes, it will be shared among all clusters. - If we want to use different reference indices for each class, we can perform the subset - selection for each class separately where different `ref_index` parameters can be used. - For example, if we have two classes, we can pass `ref_index=[0, 1]` to select samples - from class 0 and `ref_index=[3, 6]` class 1 respectively. - - """ - self.fun_dist = fun_dist - self.ref_index = ref_index - - def select_from_cluster(self, x, size, labels=None) -> Union[List, Iterable]: - """Return selected samples from a cluster based on MaxSum algorithm. - - Parameters - ---------- - x: ndarray of shape (n_samples, n_features) or (n_samples, n_samples) - Feature matrix of `n_samples` samples in `n_features` dimensional feature space, - or the pairwise distance matrix between `n_samples` samples. - If `fun_dist` is `None`, the `x` is assumed to be a square pairwise distance matrix. - size: int - Number of sample points to select (i.e. size of the subset). - labels: np.ndarray - Indices of samples that form a cluster. - - Returns - ------- - selected : Union[List, Iterable] - List of indices of selected samples. - - """ - # calculate pairwise distance between points - x_dist = x - if self.fun_dist is not None: - x_dist = self.fun_dist(x) - # check x_dist is a square symmetric matrix - if x_dist.shape[0] != x_dist.shape[1]: - raise ValueError(f"The pairwise distance matrix must be square, got {x_dist.shape}.") - if np.max(abs(x_dist - x_dist.T)) > 1e-8: - raise ValueError("The pairwise distance matrix must be symmetric.") - - if labels is not None: - # extract pairwise distances from full pairwise distance matrix to obtain a new matrix - # that only contains pairwise distances between samples within a given cluster. - x_dist = x_dist[labels][:, labels] - - # setting up initial point - selected = get_initial_selection( - x=None, x_dist=x_dist, ref_index=self.ref_index, fun_dist=None - ) - # select following points until desired number of points have been obtained - while len(selected) < size: - # determine sum of pairwise distances between selected points and all other points - sum_distances = np.sum(x_dist[selected], axis=0) - # determine which point has the max sum of pairwise distances to already-selected points - new_id = np.argmax(sum_distances) - # make sure that new_id corresponds to a new point - while new_id in selected: - # set the sum of distances for the current point corresponding to new_id to 0 - sum_distances[new_id] = 0 - # find a different point with the maximum sum of pairwise distances to - # already-selected points - new_id = np.argmax(sum_distances) - selected.append(new_id) - - selected = [int(i) for i in selected] - return selected - - -class OptiSim(SelectionBase): - """Selecting samples using OptiSim algorithm. - - The OptiSim algorithm selects samples from a dataset by first choosing the medoid center as the - initial point. Next, points are randomly chosen and added to a subsample if they exist - outside of radius r from all previously selected points (otherwise, they are discarded). Once k - number of points have been added to the subsample, the point with the greatest minimum distance - to the previously selected points is chosen. Then, the subsample is cleared and the process is - repeated. - - Notes - ----- - When the `ref_index` is a list for multiple classes, it will be shared among all clusters. - If we want to use different reference indices for each class, we can perform the subset - selection for each class separately where different `ref_index` parameters can be used. - For example, if we have two classes, we can pass `ref_index=[0, 1]` to select samples from - class 0 and `ref_index=[3, 6]` class 1 respectively. - - References - ---------- - [1] J. Chem. Inf. Comput. Sci. 1997, 37, 6, 1181–1188. https://doi.org/10.1021/ci970282v - - """ - - def __init__( - self, - r0=None, - k=10, - tol=0.01, - n_iter=10, - eps=0, - p=2, - random_seed=42, - ref_index=0, - fun_dist=None, - ): - """ - Initialize class. - - Parameters - ---------- - r0 : float, optional - Initial guess of radius for OptiSim algorithm. No points within this distance of an - already selected point can be selected. If `None`, the maximum range of features and - the size of subset are used to calculate the initial radius. This radius is optimized - to result in the desired number of samples selected, if possible. - k : int, optional - Amount of points to add to subsample before selecting one of the points with the - greatest minimum distance to the previously selected points. - tol : float, optional - Percentage error of number of samples actually selected from number of samples - requested. - n_iter : int, optional - Number of iterations to execute when optimizing the size of exclusion radius. - p : float, optional - This is `p` argument of scipy.spatial.KDTree.query_ball_point method denoting - which Minkowski p-norm to use. Should be in the range [1, inf]. A finite large p may - cause a ValueError if overflow can occur. - eps : nonnegative float, optional - This is `eps` argument of scipy.spatial.KDTree.query_ball_point method denoting - approximate nearest neighbor search for eliminating close points. Branches of the tree - are not explored if their nearest points are further than r / (1 + eps), and branches - are added in bulk if their furthest points are nearer than r * (1 + eps). - random_seed : int, optional - Seed for random selection of points be evaluated. - ref_index: int, list, optional - Index of the reference sample to start the selection algorithm from. - It can be an integer, or a list of integers. - When the `ref_index` is a list for multiple classes, it will be shared among all - clusters. If we want to use different reference indices for each class, we can perform - the subset selection for each class separately where different `ref_index` parameters - can be used. For example, if we have two classes, we can pass `ref_index=[0, 1]` to - select samples from class 0 and `ref_index=[3, 6]` class 1 respectively. - Default is [0]. - fun_dist : callable, optional - Function for calculating the pairwise distance between sample points to be used in - calculating the medoid. `fun_dist(x) -> x_dist` takes a 2D feature array of shape - (n_samples, n_features) and returns a 2D distance array of shape (n_samples, n_samples). - - """ - self.r0 = r0 - self.r = r0 - self.ref_index = ref_index - self.n_iter = n_iter - self.k = k - self.tol = tol - self.eps = eps - self.p = p - self.random_seed = random_seed - self.fun_dist = fun_dist - - def algorithm(self, x, max_size) -> Union[List, Iterable]: - """Return selected sample indices based on OptiSim algorithm. - - Parameters - ---------- - x: ndarray of shape (n_samples, n_features) - Feature matrix of `n_samples` samples in `n_features` dimensional feature space. - max_size : int - Maximum number of samples to select. - - Returns - ------- - selected : Union[List, Iterable] - List of indices of selected sample indices. - - """ - # set up reference index - selected = get_initial_selection(x=x, x_dist=None, ref_index=self.ref_index, fun_dist=None) - count = len(selected) - - # establish a kd-tree for nearest-neighbor lookup - tree = spatial.KDTree(x) - # use a random number generator that will be used to randomly select points - rng = np.random.default_rng(seed=self.random_seed) - - n_samples = len(x) - # bv will serve as a mask to discard points within radius r of previously selected points - bv = np.zeros(n_samples) - candidates = list(range(n_samples)) - # determine which points are within radius r of initial point - # note: workers=-1 uses all available processors/CPUs - index_remove = tree.query_ball_point( - x[self.ref_index], self.r, eps=self.eps, p=self.p, workers=-1 - ) - # exclude points within radius r of initial point from list of candidates using bv mask - for idx in index_remove: - bv[idx] = 1 - candidates = np.ma.array(candidates, mask=bv) - - # while there are still remaining candidates to be selected - # compressed returns all the non-masked data as a 1-D array - while len(candidates.compressed()) > 0: - # randomly select samples from list of candidates - try: - sublist = rng.choice(candidates.compressed(), size=self.k, replace=False) - except ValueError: - sublist = candidates.compressed() - - # create a new kd-tree for nearest neighbor lookup with candidates - new_tree = spatial.KDTree(x[selected]) - # query the kd-tree for nearest neighbors to selected samples - # note: workers=-1 uses all available processors/CPUs - search, _ = new_tree.query(x[sublist], eps=self.eps, p=self.p, workers=-1) - # identify the nearest neighbor with the largest distance from previously selected samples - best_idx = sublist[np.argmax(search)] - selected.append(best_idx) - - count += 1 - if count > max_size: - # do this if you have reached the maximum number of points selected - return selected - - # eliminate all samples within radius r of the selected sample - index_remove = tree.query_ball_point( - x[best_idx], self.r, eps=self.eps, p=self.p, workers=-1 - ) - for idx in index_remove: - bv[idx] = 1 - candidates = np.ma.array(candidates, mask=bv) - - return selected - - def select_from_cluster(self, x, size, labels=None) -> Union[List, Iterable]: - """Return selected samples from a cluster based on OptiSim algorithm. - - Parameters - ---------- - x: ndarray of shape (n_samples, n_features) - Feature matrix of `n_samples` samples in `n_features` dimensional feature space. - size : int - Number of samples to be selected. - labels: np.ndarray - Indices of samples that form a cluster. - - Returns - ------- - selected : Union[List, Iterable] - List of indices of selected samples. - - """ - if self.ref_index is not None and self.ref_index >= len(x): - raise ValueError( - f"ref_index is not less than the number of samples; {self.ref_index} >= {len(x)}." - ) - # pass subset of x to optimize_radius if labels is not None - if labels is not None: - x = x[labels] - # reset radius to initial value (this is important when sampling multiple clusters) - self.r = self.r0 - return optimize_radius(self, x, size, labels) - - -class DISE(SelectionBase): - """ - Select samples using Directed Sphere Exclusion (DISE) algorithm. - - In a nutshell, this algorithm iteratively excludes any sample within a given radius from - any already selected sample. The radius of the exclusion sphere is an adjustable parameter. - Compared to Sphere Exclusion algorithm, the Directed Sphere Exclusion algorithm achieves a - more evenly distributed subset selection by abandoning the random selection approach and - instead imposing a directed selection. - - Reference sample is chosen based on the `ref_index`, which is excluded from the selected - subset. All samples are sorted (ascending order) based on their Minkowski p-norm distance - from the reference sample. Looping through sorted samples, the sample is selected if it is - not already excluded. If selected, all its neighboring samples within a sphere of radius r - (i.e., exclusion sphere) are excluded from being selected. When the selected number of points - is greater than specified subset `size`, the selection process terminates. The `r0` is used - as the initial radius of exclusion sphere, however, it is optimized to select the desired - number of samples. - - References - ---------- - Gobbi, A., and Lee, M.-L. (2002). DISE: directed sphere exclusion. - Journal of Chemical Information and Computer Sciences, - 43(1), 317–323. https://doi.org/10.1021/ci025554v - - """ - - def __init__(self, r0=None, ref_index=None, tol=0.05, n_iter=10, p=2.0, eps=0.0, fun_dist=None): - """ - Initialize class. - - Parameters - ---------- - r0: float, optional - Initial guess for radius of the exclusion sphere. - ref_index: int, list, optional - Index of the reference sample to start the selection algorithm from. - It can be an integer, or a list of integers or None. When None, the medoid center is - chosen as the reference sample. - When the `ref_index` is a list for multiple classes, - it will be shared among all clusters. - If we want to use different reference indices for each class, we can perform the subset - selection for each class separately where different `ref_index` parameters can be used. - For example, if we have two classes, we can pass `ref_index=[0, 1]` to select samples - from class 0 and `ref_index=[3, 6]` class 1 respectively. - tol: float, optional - Percentage tolerance of sample size error. Given a subset size, the selected size - will be within size * (1 - tol) and size * (1 + tol). - n_iter: int, optional - Number of iterations for optimizing the radius of exclusion sphere. - p: float, optional - This is `p` argument of scipy.spatial.KDTree.query_ball_point method denoting - which Minkowski p-norm to use. The values of `p` should be within [1, inf]. - A finite large p may cause a ValueError if overflow can occur. Default is 2.0. - eps: nonnegative float, optional - This is `eps` argument of scipy.spatial.KDTree.query_ball_point method denoting - approximate nearest neighbor search for eliminating close points. Branches of the tree - are not explored if their nearest points are further than r / (1 + eps), and branches - are added in bulk if their furthest points are nearer than r * (1 + eps). - fun_dist: callable, optional - Function for calculating the distances between sample points. When `fun_dist` is `None`, - the Minkowski p-norm distance is used. Default is None. - - """ - self.r0 = r0 - self.r = r0 - self.ref_index = ref_index - self.tol = tol - self.n_iter = n_iter - self.p = p - self.eps = eps - - # if fun_dist is None: - # self.fun_dist = spatial.distance.pdist - # else: - # self.fun_dist = fun_dist - self.fun_dist = fun_dist - - def algorithm(self, x, max_size) -> Union[List, Iterable]: - """Return selected samples based on directed sphere exclusion algorithm. - - Parameters - ---------- - x: ndarray of shape (n_samples, n_features) - Feature matrix of `n_samples` samples in `n_features` dimensional space. - max_size: int - Maximum number of samples to select. - - Returns - ------- - selected: Union[List, Iterable] - List of indices of selected samples. - - """ - if self.fun_dist is None: - distances = spatial.distance.squareform( - spatial.distance.pdist(x, metric="minkowski", p=self.p) - ) - else: - distances = self.fun_dist(x) - - # set up the ref_index as when is None - if self.ref_index is None: - self.ref_index = get_initial_selection( - x=None, - x_dist=distances, - ref_index=self.ref_index, - fun_dist=None, - ) - # set up the ref_index for integer and list of integers - elif isinstance(self.ref_index, (int, list)): - self.ref_index = get_initial_selection( - x=x, - x_dist=distances, - ref_index=self.ref_index, - fun_dist=None, - ) - # not supported ref_index - else: - raise ValueError( - "The provided reference indices are not supported in the current implementation." - ) - - # # calculate distance of all samples from reference sample; distance is a (n_samples,) array - # # this includes the distance of reference sample from itself, which is 0 - # distances = spatial.minkowski_distance(x[self.ref_index], x, p=self.p) - distances_ref = distances[self.ref_index[0], :] - - # get sorted index of samples based on their distance from reference (closest to farthest) - # the first index will be the ref_index which has distance of zero - index_sorted = np.argsort(distances_ref) - assert index_sorted[0] == self.ref_index - # construct KDTree for quick nearest-neighbor lookup - kdtree = spatial.KDTree(x) - - # construct bitarray to track selected samples (1 means exclude) - bv = bitarray.bitarray(list(np.zeros(len(x), dtype=int))) - - # the neighbours of the ref_index are going to be excluded in the first iteration - # and ref_index is going to be added to the selected list - selected = [] - for idx in index_sorted: - # select sample if it is not already excluded from consideration - # indexing a single item of a bitarray will always return an integer - if bv[idx] == 0: - selected.append(idx) - # return indices of selected samples, if desired number is selected - if len(selected) > max_size: - return selected - # find index of all samples within radius of sample idx (this includes the sample index itself) - index_exclude = kdtree.query_ball_point( - x[idx], self.r, eps=self.eps, p=self.p, workers=-1 - ) - # exclude samples within radius r of sample idx (measure by Minkowski p-norm) from - # future consideration by setting their bitarray value to 1 - for index in index_exclude: - bv[index] = 1 - - return selected - - def select_from_cluster(self, x, size, labels=None) -> Union[List, Iterable]: - """Return selected samples from a cluster based on directed sphere exclusion algorithm - - Parameters - ---------- - x: ndarray of shape (n_samples, n_features) - Feature matrix of `n_samples` samples in `n_features` dimensional space. - size: int - Number of samples to be selected. - labels: np.ndarray, optional - Indices of samples that form a cluster. - - Returns - ------- - selected: Union[List, Iterable] - List of indices of selected samples. - - """ - # pass subset of x to optimize_radius if labels is not None - if labels is not None: - x = x[labels] - - if x.shape[0] < size: - raise RuntimeError( - f"Number of samples is less than the requested " - f"sample size: {x.shape[0]} < {size}." - ) - # reset radius to initial value (this is important when sampling multiple clusters) - self.r = self.r0 - return optimize_radius(self, x, size, labels) - - -def get_initial_selection(x=None, x_dist=None, ref_index=None, fun_dist=None) -> List: - """Set up the reference index for selecting. - - Parameters - ---------- - x: ndarray of shape (n_samples, n_features), optional - Feature matrix of `n_samples` samples in `n_features` dimensional feature space. - x_dist: ndarray of shape (n_samples, n_samples), optional - Pairwise distance matrix between `n_samples` samples. - ref_index: int, list, optional - Index of the reference sample to start the selection algorithm from. - It can be an integer, or a list of integers or None. When None, the medoid center is chosen as the reference - sample. - When the `ref_index` is a list for multiple classes, it will be shared among all clusters. - If we want to use different reference indices for each class, we can perform the subset - selection for each class separately where different `ref_index` parameters can be used. - For example, if we have two classes, we can pass `ref_index=[0, 1]` to select samples - from class 0 and `ref_index=[3, 6]` class 1 respectively. - fun_dist: callable, optional - Function for calculating the pairwise distance between sample points to be used in - calculating the medoid. `fun_dist(x) -> x_dist` takes a 2D feature array of shape - (n_samples, n_features) and returns a 2D distance array of shape (n_samples, n_samples). - - Returns - ------- - initial_selections: List - List of indices of the initial selected data points. - - """ - # use the medoid center as the reference sample if ref_index is None - if ref_index is None: - if x_dist is None: - x_dist = fun_dist(x) - # calculate the medoid center - initial_selections = [int(np.argmin(np.sum(x_dist, axis=0)))] - - # the length of the distance matrix is the number of samples - if x_dist is not None: - len_x = len(x_dist) - else: - len_x = len(x) - - # when ref_index is an integer, it cannot be negative or greater than the number of samples - if isinstance(ref_index, int): - # check if ref_index is a valid index - if ref_index < 0 or ref_index >= len_x: - raise ValueError( - f"The ref_index must be a non-negative integer less than the " - f"number of samples, got {ref_index} >= {len_x}." - ) - initial_selections = [int(ref_index)] - - # when ref_index is a list, just use it - if isinstance(ref_index, list): - # all elements of ref_index must be integers or float - if not all(isinstance(i, (int)) for i in ref_index): - raise ValueError("All elements of ref_index must be integers.") - - # all the elements of ref_index must be greater than or equal to 0 and less than the - # number of samples - if np.any(np.array(ref_index) < 0) or np.any(np.array(ref_index) >= len_x): - raise ValueError( - f"All elements of ref_index must be greater than or equal to 0 and less than " - f"the number of samples, got {ref_index}." - ) - - initial_selections = [int(i) for i in ref_index] - - return initial_selections +# -*- coding: utf-8 -*- +# +# The Selector is a Python library of algorithms for selecting diverse +# subsets of data for machine-learning. +# +# Copyright (C) 2022-2024 The QC-Devs Community +# +# This file is part of Selector. +# +# Selector is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 +# of the License, or (at your option) any later version. +# +# Selector is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see +# +# -- +"""Module for Distance-Based Selection Methods.""" + +import bitarray +import numpy as np +from scipy import spatial +from typing import List, Iterable, Union + +from selector.methods.base import SelectionBase +from selector.methods.utils import optimize_radius + +__all__ = [ + "MaxMin", + "MaxSum", + "OptiSim", + "DISE", +] + + +class MaxMin(SelectionBase): + """Select samples using MaxMin algorithm. + + MaxMin is possibly the most widely used method for dissimilarity-based + compound selection. When presented with a dataset of samples, the + initial point is chosen as the dataset's medoid center. Next, the second + point is chosen to be that which is furthest from this initial point. + Subsequently, all following points are selected via the following + logic: + + 1. Find the minimum distance from every point to the already-selected ones. + 2. Select the point which has the maximum distance among those calculated + in the previous step. + + In the current implementation, this method requires or computes the full pairwise-distance + matrix, so it is not recommended for large datasets. + + References + ---------- + [1] Ashton, Mark, et al., Identification of diverse database subsets using + property‐based and fragment‐based molecular descriptions, Quantitative + Structure‐Activity Relationships 21.6 (2002): 598-604. + """ + + def __init__(self, fun_dist=None, ref_index=None): + """ + Initializing class. + + Parameters + ---------- + fun_distance : callable + Function for calculating the pairwise distance between sample points. + `fun_dist(x) -> x_dist` takes a 2D feature array of shape (n_samples, n_features) + and returns a 2D distance array of shape (n_samples, n_samples). + ref_index: int, list, optional + Index of the reference sample to start the selection algorithm from. + It can be an integer, or a list of integers or None. When None, the medoid center is chosen as the reference + sample. + When the `ref_index` is a list for multiple classes, it will be shared among all clusters. + If we want to use different reference indices for each class, we can perform the subset + selection for each class separately where different `ref_index` parameters can be used. + For example, if we have two classes, we can pass `ref_index=[0, 1]` to select samples + from class 0 and `ref_index=[3, 6]` class 1 respectively. + + """ + self.fun_dist = fun_dist + self.ref_index = ref_index + + def select_from_cluster(self, x, size, labels=None) -> Union[List, Iterable]: + """Return selected samples from a cluster based on MaxMin algorithm. + + Parameters + ---------- + x: ndarray of shape (n_samples, n_features) or (n_samples, n_samples) + Feature matrix of `n_samples` samples in `n_features` dimensional feature space, + or the pairwise distance matrix between `n_samples` samples. + If `fun_dist` is `None`, the `x` is assumed to be a square pairwise distance matrix. + size: int + Number of sample points to select (i.e. size of the subset). + labels: np.ndarray + Indices of samples that form a cluster. + + Returns + ------- + selected : Union[List, Iterable] + List of indices of selected samples. + """ + # calculate pairwise distance between points + x_dist = x + if self.fun_dist is not None: + x_dist = self.fun_dist(x) + # check x_dist is a square symmetric matrix + if x_dist.shape[0] != x_dist.shape[1]: + raise ValueError(f"The pairwise distance matrix must be square, got {x_dist.shape}.") + if np.max(abs(x_dist - x_dist.T)) > 1e-8: + raise ValueError("The pairwise distance matrix must be symmetric.") + + if labels is not None: + # extract pairwise distances from full pairwise distance matrix to obtain a new matrix + # that only contains pairwise distances between samples within a given cluster + x_dist = x_dist[labels][:, labels] + + # choosing initial point + selected = get_initial_selection( + x=None, x_dist=x_dist, ref_index=self.ref_index, fun_dist=None + ) + + # select following points until desired number of points have been obtained + while len(selected) < size: + # determine the min pairwise distances between the selected points and all other points + min_distances = np.min(x_dist[selected], axis=0) + # determine which point affords the maximum distance among the minimum distances + # captured in min_distances + new_id = np.argmax(min_distances) + selected.append(new_id) + + selected = [int(i) for i in selected] + + return selected + + +class MaxSum(SelectionBase): + """Select samples using MaxSum algorithm. + + Whereas the goal of the MaxMin algorithm is to maximize the minimum distance + between any pair of distinct elements in the selected subset of a dataset, + the MaxSum algorithm aims to maximize the sum of distances between all + pairs of elements in the selected subset. When presented with a dataset of + samples, the initial point is chosen as the dataset's medoid center. Next, + the second point is chosen to be that which is furthest from this initial + point. Subsequently, all following points are selected via the following + logic: + + 1. Determine the sum of distances from every point to the already-selected ones. + 2. Select the point which has the maximum sum of distances among those calculated + in the previous step. + + References + ---------- + [1] Borodin, Allan, Hyun Chul Lee, and Yuli Ye, Max-sum diversification, monotone + submodular functions and dynamic updates, Proceedings of the 31st ACM SIGMOD-SIGACT-SIGAI + symposium on Principles of Database Systems. 2012. + """ + + def __init__(self, fun_dist=None, ref_index=None): + """ + Initializing class. + + Parameters + ---------- + fun_dist : callable + Function for calculating the pairwise distance between sample points. + `fun_dist(x) -> x_dist` takes a 2D feature array of shape (n_samples, n_features) + and returns a 2D distance array of shape (n_samples, n_samples). + ref_index: int, list, optional + Index of the reference sample to start the selection algorithm from. + It can be an integer, or a list of integers or None. When None, the medoid center is chosen as the reference + sample. + When the `ref_index` is a list for multiple classes, it will be shared among all clusters. + If we want to use different reference indices for each class, we can perform the subset + selection for each class separately where different `ref_index` parameters can be used. + For example, if we have two classes, we can pass `ref_index=[0, 1]` to select samples + from class 0 and `ref_index=[3, 6]` class 1 respectively. + + """ + self.fun_dist = fun_dist + self.ref_index = ref_index + + def select_from_cluster(self, x, size, labels=None) -> Union[List, Iterable]: + """Return selected samples from a cluster based on MaxSum algorithm. + + Parameters + ---------- + x: ndarray of shape (n_samples, n_features) or (n_samples, n_samples) + Feature matrix of `n_samples` samples in `n_features` dimensional feature space, + or the pairwise distance matrix between `n_samples` samples. + If `fun_dist` is `None`, the `x` is assumed to be a square pairwise distance matrix. + size: int + Number of sample points to select (i.e. size of the subset). + labels: np.ndarray + Indices of samples that form a cluster. + + Returns + ------- + selected : Union[List, Iterable] + List of indices of selected samples. + + """ + # calculate pairwise distance between points + x_dist = x + if self.fun_dist is not None: + x_dist = self.fun_dist(x) + # check x_dist is a square symmetric matrix + if x_dist.shape[0] != x_dist.shape[1]: + raise ValueError(f"The pairwise distance matrix must be square, got {x_dist.shape}.") + if np.max(abs(x_dist - x_dist.T)) > 1e-8: + raise ValueError("The pairwise distance matrix must be symmetric.") + + if labels is not None: + # extract pairwise distances from full pairwise distance matrix to obtain a new matrix + # that only contains pairwise distances between samples within a given cluster. + x_dist = x_dist[labels][:, labels] + + # setting up initial point + selected = get_initial_selection( + x=None, x_dist=x_dist, ref_index=self.ref_index, fun_dist=None + ) + # select following points until desired number of points have been obtained + while len(selected) < size: + # determine sum of pairwise distances between selected points and all other points + sum_distances = np.sum(x_dist[selected], axis=0) + # determine which point has the max sum of pairwise distances to already-selected points + new_id = np.argmax(sum_distances) + # make sure that new_id corresponds to a new point + while new_id in selected: + # set the sum of distances for the current point corresponding to new_id to 0 + sum_distances[new_id] = 0 + # find a different point with the maximum sum of pairwise distances to + # already-selected points + new_id = np.argmax(sum_distances) + selected.append(new_id) + + selected = [int(i) for i in selected] + return selected + + +class OptiSim(SelectionBase): + """Selecting samples using OptiSim algorithm. + + The OptiSim algorithm selects samples from a dataset by first choosing the medoid center as the + initial point. Next, points are randomly chosen and added to a subsample if they exist + outside of radius r from all previously selected points (otherwise, they are discarded). Once k + number of points have been added to the subsample, the point with the greatest minimum distance + to the previously selected points is chosen. Then, the subsample is cleared and the process is + repeated. + + Notes + ----- + When the `ref_index` is a list for multiple classes, it will be shared among all clusters. + If we want to use different reference indices for each class, we can perform the subset + selection for each class separately where different `ref_index` parameters can be used. + For example, if we have two classes, we can pass `ref_index=[0, 1]` to select samples from + class 0 and `ref_index=[3, 6]` class 1 respectively. + + References + ---------- + [1] J. Chem. Inf. Comput. Sci. 1997, 37, 6, 1181–1188. https://doi.org/10.1021/ci970282v + + """ + + def __init__( + self, + r0=None, + k=10, + tol=0.01, + n_iter=10, + eps=0, + p=2, + random_seed=42, + ref_index=0, + fun_dist=None, + ): + """ + Initialize class. + + Parameters + ---------- + r0 : float, optional + Initial guess of radius for OptiSim algorithm. No points within this distance of an + already selected point can be selected. If `None`, the maximum range of features and + the size of subset are used to calculate the initial radius. This radius is optimized + to result in the desired number of samples selected, if possible. + k : int, optional + Amount of points to add to subsample before selecting one of the points with the + greatest minimum distance to the previously selected points. + tol : float, optional + Percentage error of number of samples actually selected from number of samples + requested. + n_iter : int, optional + Number of iterations to execute when optimizing the size of exclusion radius. + p : float, optional + This is `p` argument of scipy.spatial.KDTree.query_ball_point method denoting + which Minkowski p-norm to use. Should be in the range [1, inf]. A finite large p may + cause a ValueError if overflow can occur. + eps : nonnegative float, optional + This is `eps` argument of scipy.spatial.KDTree.query_ball_point method denoting + approximate nearest neighbor search for eliminating close points. Branches of the tree + are not explored if their nearest points are further than r / (1 + eps), and branches + are added in bulk if their furthest points are nearer than r * (1 + eps). + random_seed : int, optional + Seed for random selection of points be evaluated. + ref_index: int, list, optional + Index of the reference sample to start the selection algorithm from. + It can be an integer, or a list of integers. + When the `ref_index` is a list for multiple classes, it will be shared among all + clusters. If we want to use different reference indices for each class, we can perform + the subset selection for each class separately where different `ref_index` parameters + can be used. For example, if we have two classes, we can pass `ref_index=[0, 1]` to + select samples from class 0 and `ref_index=[3, 6]` class 1 respectively. + Default is [0]. + fun_dist : callable, optional + Function for calculating the pairwise distance between sample points to be used in + calculating the medoid. `fun_dist(x) -> x_dist` takes a 2D feature array of shape + (n_samples, n_features) and returns a 2D distance array of shape (n_samples, n_samples). + + """ + self.r0 = r0 + self.r = r0 + self.ref_index = ref_index + self.n_iter = n_iter + self.k = k + self.tol = tol + self.eps = eps + self.p = p + self.random_seed = random_seed + self.fun_dist = fun_dist + + def algorithm(self, x, max_size) -> Union[List, Iterable]: + """Return selected sample indices based on OptiSim algorithm. + + Parameters + ---------- + x: ndarray of shape (n_samples, n_features) + Feature matrix of `n_samples` samples in `n_features` dimensional feature space. + max_size : int + Maximum number of samples to select. + + Returns + ------- + selected : Union[List, Iterable] + List of indices of selected sample indices. + + """ + # set up reference index + selected = get_initial_selection(x=x, x_dist=None, ref_index=self.ref_index, fun_dist=None) + count = len(selected) + + # establish a kd-tree for nearest-neighbor lookup + tree = spatial.KDTree(x) + # use a random number generator that will be used to randomly select points + rng = np.random.default_rng(seed=self.random_seed) + + n_samples = len(x) + # bv will serve as a mask to discard points within radius r of previously selected points + bv = np.zeros(n_samples) + candidates = list(range(n_samples)) + # determine which points are within radius r of initial point + # note: workers=-1 uses all available processors/CPUs + index_remove = tree.query_ball_point( + x[self.ref_index], self.r, eps=self.eps, p=self.p, workers=-1 + ) + # exclude points within radius r of initial point from list of candidates using bv mask + for idx in index_remove: + bv[idx] = 1 + candidates = np.ma.array(candidates, mask=bv) + + # while there are still remaining candidates to be selected + # compressed returns all the non-masked data as a 1-D array + while len(candidates.compressed()) > 0: + # randomly select samples from list of candidates + try: + sublist = rng.choice(candidates.compressed(), size=self.k, replace=False) + except ValueError: + sublist = candidates.compressed() + + # create a new kd-tree for nearest neighbor lookup with candidates + new_tree = spatial.KDTree(x[selected]) + # query the kd-tree for nearest neighbors to selected samples + # note: workers=-1 uses all available processors/CPUs + search, _ = new_tree.query(x[sublist], eps=self.eps, p=self.p, workers=-1) + # identify the nearest neighbor with the largest distance from previously selected samples + best_idx = sublist[np.argmax(search)] + selected.append(best_idx) + + count += 1 + if count > max_size: + # do this if you have reached the maximum number of points selected + return selected + + # eliminate all samples within radius r of the selected sample + index_remove = tree.query_ball_point( + x[best_idx], self.r, eps=self.eps, p=self.p, workers=-1 + ) + for idx in index_remove: + bv[idx] = 1 + candidates = np.ma.array(candidates, mask=bv) + + return selected + + def select_from_cluster(self, x, size, labels=None) -> Union[List, Iterable]: + """Return selected samples from a cluster based on OptiSim algorithm. + + Parameters + ---------- + x: ndarray of shape (n_samples, n_features) + Feature matrix of `n_samples` samples in `n_features` dimensional feature space. + size : int + Number of samples to be selected. + labels: np.ndarray + Indices of samples that form a cluster. + + Returns + ------- + selected : Union[List, Iterable] + List of indices of selected samples. + + """ + if self.ref_index is not None and self.ref_index >= len(x): + raise ValueError( + f"ref_index is not less than the number of samples; {self.ref_index} >= {len(x)}." + ) + # pass subset of x to optimize_radius if labels is not None + if labels is not None: + x = x[labels] + # reset radius to initial value (this is important when sampling multiple clusters) + self.r = self.r0 + return optimize_radius(self, x, size, labels) + + +class DISE(SelectionBase): + """ + Select samples using Directed Sphere Exclusion (DISE) algorithm. + + In a nutshell, this algorithm iteratively excludes any sample within a given radius from + any already selected sample. The radius of the exclusion sphere is an adjustable parameter. + Compared to Sphere Exclusion algorithm, the Directed Sphere Exclusion algorithm achieves a + more evenly distributed subset selection by abandoning the random selection approach and + instead imposing a directed selection. + + Reference sample is chosen based on the `ref_index`, which is excluded from the selected + subset. All samples are sorted (ascending order) based on their Minkowski p-norm distance + from the reference sample. Looping through sorted samples, the sample is selected if it is + not already excluded. If selected, all its neighboring samples within a sphere of radius r + (i.e., exclusion sphere) are excluded from being selected. When the selected number of points + is greater than specified subset `size`, the selection process terminates. The `r0` is used + as the initial radius of exclusion sphere, however, it is optimized to select the desired + number of samples. + + References + ---------- + Gobbi, A., and Lee, M.-L. (2002). DISE: directed sphere exclusion. + Journal of Chemical Information and Computer Sciences, + 43(1), 317–323. https://doi.org/10.1021/ci025554v + + """ + + def __init__(self, r0=None, ref_index=None, tol=0.05, n_iter=10, p=2.0, eps=0.0, fun_dist=None): + """ + Initialize class. + + Parameters + ---------- + r0: float, optional + Initial guess for radius of the exclusion sphere. + ref_index: int, list, optional + Index of the reference sample to start the selection algorithm from. + It can be an integer, or a list of integers or None. When None, the medoid center is + chosen as the reference sample. + When the `ref_index` is a list for multiple classes, + it will be shared among all clusters. + If we want to use different reference indices for each class, we can perform the subset + selection for each class separately where different `ref_index` parameters can be used. + For example, if we have two classes, we can pass `ref_index=[0, 1]` to select samples + from class 0 and `ref_index=[3, 6]` class 1 respectively. + tol: float, optional + Percentage tolerance of sample size error. Given a subset size, the selected size + will be within size * (1 - tol) and size * (1 + tol). + n_iter: int, optional + Number of iterations for optimizing the radius of exclusion sphere. + p: float, optional + This is `p` argument of scipy.spatial.KDTree.query_ball_point method denoting + which Minkowski p-norm to use. The values of `p` should be within [1, inf]. + A finite large p may cause a ValueError if overflow can occur. Default is 2.0. + eps: nonnegative float, optional + This is `eps` argument of scipy.spatial.KDTree.query_ball_point method denoting + approximate nearest neighbor search for eliminating close points. Branches of the tree + are not explored if their nearest points are further than r / (1 + eps), and branches + are added in bulk if their furthest points are nearer than r * (1 + eps). + fun_dist: callable, optional + Function for calculating the distances between sample points. When `fun_dist` is `None`, + the Minkowski p-norm distance is used. Default is None. + + """ + self.r0 = r0 + self.r = r0 + self.ref_index = ref_index + self.tol = tol + self.n_iter = n_iter + self.p = p + self.eps = eps + + # if fun_dist is None: + # self.fun_dist = spatial.distance.pdist + # else: + # self.fun_dist = fun_dist + self.fun_dist = fun_dist + + def algorithm(self, x, max_size) -> Union[List, Iterable]: + """Return selected samples based on directed sphere exclusion algorithm. + + Parameters + ---------- + x: ndarray of shape (n_samples, n_features) + Feature matrix of `n_samples` samples in `n_features` dimensional space. + max_size: int + Maximum number of samples to select. + + Returns + ------- + selected: Union[List, Iterable] + List of indices of selected samples. + + """ + if self.fun_dist is None: + distances = spatial.distance.squareform( + spatial.distance.pdist(x, metric="minkowski", p=self.p) + ) + else: + distances = self.fun_dist(x) + + # set up the ref_index as when is None + if self.ref_index is None: + self.ref_index = get_initial_selection( + x=None, + x_dist=distances, + ref_index=self.ref_index, + fun_dist=None, + ) + # set up the ref_index for integer and list of integers + elif isinstance(self.ref_index, (int, list)): + self.ref_index = get_initial_selection( + x=x, + x_dist=distances, + ref_index=self.ref_index, + fun_dist=None, + ) + # not supported ref_index + else: + raise ValueError( + "The provided reference indices are not supported in the current implementation." + ) + + # # calculate distance of all samples from reference sample; distance is a (n_samples,) array + # # this includes the distance of reference sample from itself, which is 0 + # distances = spatial.minkowski_distance(x[self.ref_index], x, p=self.p) + distances_ref = distances[self.ref_index[0], :] + + # get sorted index of samples based on their distance from reference (closest to farthest) + # the first index will be the ref_index which has distance of zero + index_sorted = np.argsort(distances_ref) + assert index_sorted[0] == self.ref_index + # construct KDTree for quick nearest-neighbor lookup + kdtree = spatial.KDTree(x) + + # construct bitarray to track selected samples (1 means exclude) + bv = bitarray.bitarray(list(np.zeros(len(x), dtype=int))) + + # the neighbours of the ref_index are going to be excluded in the first iteration + # and ref_index is going to be added to the selected list + selected = [] + for idx in index_sorted: + # select sample if it is not already excluded from consideration + # indexing a single item of a bitarray will always return an integer + if bv[idx] == 0: + selected.append(idx) + # return indices of selected samples, if desired number is selected + if len(selected) > max_size: + return selected + # find index of all samples within radius of sample idx (this includes the sample index itself) + index_exclude = kdtree.query_ball_point( + x[idx], self.r, eps=self.eps, p=self.p, workers=-1 + ) + # exclude samples within radius r of sample idx (measure by Minkowski p-norm) from + # future consideration by setting their bitarray value to 1 + for index in index_exclude: + bv[index] = 1 + + return selected + + def select_from_cluster(self, x, size, labels=None) -> Union[List, Iterable]: + """Return selected samples from a cluster based on directed sphere exclusion algorithm + + Parameters + ---------- + x: ndarray of shape (n_samples, n_features) + Feature matrix of `n_samples` samples in `n_features` dimensional space. + size: int + Number of samples to be selected. + labels: np.ndarray, optional + Indices of samples that form a cluster. + + Returns + ------- + selected: Union[List, Iterable] + List of indices of selected samples. + + """ + # pass subset of x to optimize_radius if labels is not None + if labels is not None: + x = x[labels] + + if x.shape[0] < size: + raise RuntimeError( + f"Number of samples is less than the requested " + f"sample size: {x.shape[0]} < {size}." + ) + # reset radius to initial value (this is important when sampling multiple clusters) + self.r = self.r0 + return optimize_radius(self, x, size, labels) + + +def get_initial_selection(x=None, x_dist=None, ref_index=None, fun_dist=None) -> List: + """Set up the reference index for selecting. + + Parameters + ---------- + x: ndarray of shape (n_samples, n_features), optional + Feature matrix of `n_samples` samples in `n_features` dimensional feature space. + x_dist: ndarray of shape (n_samples, n_samples), optional + Pairwise distance matrix between `n_samples` samples. + ref_index: int, list, optional + Index of the reference sample to start the selection algorithm from. + It can be an integer, or a list of integers or None. When None, the medoid center is chosen as the reference + sample. + When the `ref_index` is a list for multiple classes, it will be shared among all clusters. + If we want to use different reference indices for each class, we can perform the subset + selection for each class separately where different `ref_index` parameters can be used. + For example, if we have two classes, we can pass `ref_index=[0, 1]` to select samples + from class 0 and `ref_index=[3, 6]` class 1 respectively. + fun_dist: callable, optional + Function for calculating the pairwise distance between sample points to be used in + calculating the medoid. `fun_dist(x) -> x_dist` takes a 2D feature array of shape + (n_samples, n_features) and returns a 2D distance array of shape (n_samples, n_samples). + + Returns + ------- + initial_selections: List + List of indices of the initial selected data points. + + """ + # use the medoid center as the reference sample if ref_index is None + if ref_index is None: + if x_dist is None: + x_dist = fun_dist(x) + # calculate the medoid center + initial_selections = [int(np.argmin(np.sum(x_dist, axis=0)))] + + # the length of the distance matrix is the number of samples + if x_dist is not None: + len_x = len(x_dist) + else: + len_x = len(x) + + # when ref_index is an integer, it cannot be negative or greater than the number of samples + if isinstance(ref_index, int): + # check if ref_index is a valid index + if ref_index < 0 or ref_index >= len_x: + raise ValueError( + f"The ref_index must be a non-negative integer less than the " + f"number of samples, got {ref_index} >= {len_x}." + ) + initial_selections = [int(ref_index)] + + # when ref_index is a list, just use it + if isinstance(ref_index, list): + # all elements of ref_index must be integers or float + if not all(isinstance(i, (int)) for i in ref_index): + raise ValueError("All elements of ref_index must be integers.") + + # all the elements of ref_index must be greater than or equal to 0 and less than the + # number of samples + if np.any(np.array(ref_index) < 0) or np.any(np.array(ref_index) >= len_x): + raise ValueError( + f"All elements of ref_index must be greater than or equal to 0 and less than " + f"the number of samples, got {ref_index}." + ) + + initial_selections = [int(i) for i in ref_index] + + return initial_selections diff --git a/selector/methods/partition.py b/selector/methods/partition.py index 39dc6cae..407a726f 100644 --- a/selector/methods/partition.py +++ b/selector/methods/partition.py @@ -1,668 +1,668 @@ -# -*- coding: utf-8 -*- -# -# The Selector is a Python library of algorithms for selecting diverse -# subsets of data for machine-learning. -# -# Copyright (C) 2022-2024 The QC-Devs Community -# -# This file is part of Selector. -# -# Selector is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 -# of the License, or (at your option) any later version. -# -# Selector is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see -# -# -- -"""Module for Partition-Based Selection Methods.""" - -import collections -import math - -import bitarray -import numpy as np -import scipy - -from selector.measures.diversity import compute_diversity -from selector.methods.base import SelectionBase - -__all__ = [ - "GridPartition", - "Medoid", -] - - -class GridPartition(SelectionBase): - r"""Select subset of sample points using the grid partitioning algorithms. - - Given the number of bins along each axis, samples are partitioned using various methods [1]_: - - - The `equisized_independent` partitions the feature space into bins of equal size along - each dimension. - - - The `equisized_dependent` partitions the space where the bins can have different length - in each dimension. I.e., the `l-`th dimension bins depend on the previous dimensions. - So, the order of features affects the outcome. - - - The `equifrequent_independent` divides the space into bins with approximately equal - number of sample points in each bin. - - - The `equifrequent_dependent` is similar to `equisized_dependent` where the partition in - each dimension will depend on the previous dimensions. - - References - ---------- - .. [1] Bayley, Martin J., and Peter Willett. "Binning schemes for partition-based - compound selection." Journal of Molecular Graphics and Modelling 17.1 (1999): 10-18. - """ - - def __init__( - self, nbins_axis: int, bin_method: str = "equisized_independent", random_seed: int = 42 - ): - """Initialize class. - - Parameters - ---------- - nbins_axis: int - Number of bins to partition each axis into. The total number of resulting bins is - `numb_bins_axis` raised to the power of the dimensionality of the feature space. - bin_method: str, optional - Method used to partition the sample points into bins. Options include: - "equisized_independent", "equisized_dependent", "equifrequent_independent" and - "equifrequent_dependent". - random_seed: int, optional - Seed for random selection of sample points from each bin. - """ - if not isinstance(nbins_axis, int): - raise TypeError(f"Number of bins should be integer, got {type(nbins_axis)}.") - if not isinstance(random_seed, int): - raise TypeError(f"The random seed should be integer, got {type(random_seed)}.") - if not isinstance(bin_method, str): - raise TypeError(f"The bin_method should be a string, got {type(bin_method)}.") - self.random_seed = random_seed - self.nbins_axis = nbins_axis - self.bin_method = bin_method - - @staticmethod - def partition_points_to_bins_equisized(X, nbins_axis): - r""" - Find all bins ids that has points in them and assign each point to each of those bins. - - For each `n_features` dimensions, get the minimum and maximum of feature to and use - `nbins_axis` to compute length of the bin. Then assign sample points to bins along - each axis/dimension of feature space. - - Parameters - ---------- - X: ndarray of shape (n_samples, n_features) - Feature matrix of `n_samples` samples in `n_features` dimensional space. - nbins_axis: int - Number of bins along each axis/dimension of feature space. - - Returns - ------- - unique_bin_indices: ndarray(int,) - Unique (without duplication) bin indices that have at least one sample point. - These are integer tuples :math:`(i_1, \cdot, i_\text{n_features})` with elements - corresponding to the bin index along each axis/dimension of feature space. - `inverse_ids` contains indices of `unique_bins_ids` for each of the :math:`N` points that - it is assigned to. - inverse_indices: ndarray(int,) - Indices of the unique bins (along specified axis) that can be used to reconstruct bin - index of each sample (`unique_bin_indices[inverse_indices]` gives bin index array). - """ - # find the minimum and maximum of features along axis/dimension - axis_minimum = np.min(X, axis=0) - axis_maximum = np.max(X, axis=0) - bin_length = (axis_maximum - axis_minimum) / nbins_axis - # assign each sample to a bin along each dimension (floor_divide returns array of integers) - bin_index = np.floor_divide(X - axis_minimum, bin_length) - # get unique bin indices (occupied by samples) and indices of the unique array - # (along specified axis) that can be used to reconstruct bin_index - # in other words, unique_bin_index[inverse_index] gives back bin_index array - unique_bin_index, inverse_index = np.unique(bin_index, return_inverse=True, axis=0) - return unique_bin_index, inverse_index - - @staticmethod - def partition_points_to_bins_equifrequent(X, nbins_axis): - r""" - Find all bins ids that contains points using the equifrequent method. - - The equifrequent method partitions each bin to have equal number of points. - This is done by doing a linear interpolation from integer indices and points, where - it is then evaluated on a uniform grid with number of bins as the spacing in each axis. - - Parameters - ---------- - X: ndarray of shape (n_samples, n_features) - Feature matrix of `n_samples` samples in `n_features` dimensional space. - nbins_axis: int - Number of bins along each axis or feature dimension. - - Returns - ------- - unique_bin_indices: ndarray(int,) - Unique (without duplication) bin indices that have at least one sample point. - These are integer tuples :math:`(i_1, \cdot, i_\text{n_features})` with elements - corresponding to the bin index along each axis/dimension of feature space. - `inverse_ids` contains indices of `unique_bins_ids` for each of the :math:`N` points that - it is assigned to. - inverse_indices: ndarray(int,) - Indices of the unique bins (along specified axis) that can be used to reconstruct bin - index of each sample (`unique_bin_indices[inverse_indices]` gives bin index array). - """ - n_samples = len(X) - # to obtain the lower and upper range of bins so that each bin has equal number of points, - # we interpolate the feature value for indices delineating the range of bins. - # I.e., sorting the features values along one axis, the (xp, fp) pairs are formed where - # xp denote the integer index of `n_samples points and fp the corresponding feature values. - # now, the value of feature is interpolated for the indices corresponding to lower and - # upper ranges of bins denoted by x. The x indices are obtained by evenly dividing the - # (0, n_samples) into nbins_axis bins (hence nbins_axis + 1 for number of samples indices). - # Obviously, in this way, the bins have roughly `n_samples` points. - # Note that the starting and ending indices of the bins are always 0 and n_samples, - # corresponding to the minimum and maximum of the feature values. - # The resulting bins_edge defines a monotonically increasing array of bin edges, including - # the rightmost edge, allowing for non-uniform bin widths. - # The bins_edge[0] and bins_edge[-1] correspond to the min and max of the feature values. - bins_edge = np.interp( - x=np.linspace(0, n_samples, nbins_axis + 1), xp=np.arange(n_samples), fp=np.sort(X) - ) - # Note: alternatively, one can use x=np.linspace(0, n_samples - 1, nbins_axis + 1) so - # that the ending index corresponds to the index of the last sample point. This would not - # be an issue, because the numpy interpolate function np.interp has two attributes called - # right/left, so if the value x is outside the interpolating domain, then it returns the - # closest data point fp[-1]/fp[0], respectively. This causes the partition into bins to - # always include the endpoints. - - # To assign samples into bins, sample features are subtracted from the bins_edge, and - # the index of the bins_edge where the difference switches from negative to positive is - # the bin index that the sample is assigned to. The switch from negative to positive is - # identified by the argmax function after setting all the non-negative values to -inf. - pt_to_bind = bins_edge - X[:, None] - pt_to_bind[pt_to_bind >= 0.0] = -np.inf - bin_index = np.argmax(pt_to_bind, axis=1) - unique_bin_ids, inverse_ids = np.unique(bin_index, return_inverse=True) - return unique_bin_ids, inverse_ids - - def get_bins_from_method(self, X): - r"""Assign sample points to bins based on the partitioning method. - - Parameters - ---------- - X: ndarray of shape (n_samples, n_features) - Feature matrix of `n_samples` samples in `n_features` dimensional space. - - Returns - ------- - bins: dict[Tuple(int), List[int]] - Dictionary of bins where keys are the unique bin indices (that contain at least one - sample point) and the values are the list of sample indices in that bin. - """ - - # dictionary of bins where the keys are the unique bin indices (that contain at least one - # sample) and the values are the list of sample indices in that bin. - bins = {} - - if self.bin_method == "equisized_independent": - # partition each dimension/feature independently into `num_bins_axis` bins - unique_bin_index, inverse_index = self.partition_points_to_bins_equisized( - X, self.nbins_axis - ) - # populate bins dictionary - for i, key in enumerate(unique_bin_index): - bins[tuple(key)] = list(np.where(inverse_index == i)[0]) - - elif self.bin_method == "equisized_dependent": - # partition the first dimension (1st feature axis) into `num_bins_axis` bins - unique_bin_index, inverse_index = self.partition_points_to_bins_equisized( - X[:, 0], self.nbins_axis - ) - # populate bins dictionary based on the 1st feature - for i, key in enumerate(unique_bin_index): - bins[tuple([key])] = list(np.where(inverse_index == i)[0]) - - # loop over the remaining dimensions (2nd to last feature axis), and for each axis - # partition the points in each bin of the previous axes into `num_bins_axis` bins - # as a result, each iteration adds a new dimension to the bins dictionary - for index_feature in range(1, X.shape[1]): - # make a dictionary to store the bins for the current axis - bins_axis = {} - # divide points in each bin into `num_bins_axis` bins based on the i-th feature - for bin, index_samples in bins.items(): - # equisized partition of points in bin along i-th feature - unique_bin_index, inverse_index = self.partition_points_to_bins_equisized( - X[index_samples, index_feature], self.nbins_axis - ) - # update the bins_axis to include the new dimension/feature for the current bin - for i, bin_index in enumerate(unique_bin_index): - # form a new bin_index by appending current bin_index to the previous bin - key = tuple(list(bin) + [bin_index]) - bins_axis.update( - {key: list(np.array(index_samples)[np.where(inverse_index == i)[0]])} - ) - bins = bins_axis - - elif self.bin_method == "equifrequent_independent": - # partition each dimension of feature space independently into `num_bins_axis` bins - bins_features = np.zeros(X.shape, dtype=int) - for index_feature in range(0, X.shape[1]): - unique_bin_index, inverse_index = self.partition_points_to_bins_equifrequent( - X[:, index_feature], self.nbins_axis - ) - bins_features[:, index_feature] = unique_bin_index[inverse_index] - unique_bin_index, inverse_index = np.unique(bins_features, return_inverse=True, axis=0) - - # populate bins dictionary - for i, key in enumerate(unique_bin_index): - bins[tuple(key)] = list(np.where(inverse_index == i)[0]) - - elif self.bin_method == "equifrequent_dependent": - # partition the first dimension (1st feature axis) into `num_bins_axis` bins - unique_bin_index, inverse_index = self.partition_points_to_bins_equifrequent( - X[:, 0], self.nbins_axis - ) - # populate bins dictionary based on the 1st feature - for i, key in enumerate(unique_bin_index): - bins[tuple([key])] = list(np.where(inverse_index == i)[0]) - - # loop over the remaining dimensions (2nd to last feature axis), and for each axis - # partition the points in each bin of the previous axes into `num_bins_axis` bins - for index_feature in range(1, X.shape[1]): - # make a dictionary to store the bins for the current axis - bins_axis = {} - # divide points in each bin, based on the i-th feature, into `num_bins_axis` bins - for bin, index_samples in bins.items(): - # equifrequent partition of points in bin along i-th feature - unique_bin_index, inverse_index = self.partition_points_to_bins_equifrequent( - X[index_samples, index_feature], self.nbins_axis - ) - # update the bins_axis to include the new dimension/feature for the current bin - for i, key in enumerate(unique_bin_index): - # form a new bin_index by appending current bin_index to the previous bin - key = tuple(list(bin) + [key]) - bins_axis.update( - {key: list(np.array(index_samples)[np.where(inverse_index == i)[0]])} - ) - bins = bins_axis - else: - raise ValueError(f"{self.bin_method} not a valid bin_method") - - return bins - - def select_from_bins( - self, - X, - bins, - num_selected, - diversity_type="hypersphere_overlap", - cs=None, - ): - r""" - From the bins, select a certain number of points of the bins. - - Points are selected in an iterative manner. If the number of points needed to be selected - is greater than number of bins left then randomly select points from each of the bins. If - any of the bins are empty then remove the bins. If it is less than the number of bins left, - then calculate the diversity of each bin and choose points of bins with the highest diversity. - - Parameters - ---------- - X: ndarray of shape (n_samples, n_features) - Feature matrix of `n_samples` samples in `n_features` dimensional space. - bins: dict(tuple(int), list[int]) - The bins that map to the id the bin (as a tuple of integers) and returns - the indices of the points that are contained in that bin. - num_selected: int - Number of points to select from the bins. - diversity_type: str, optional - Type of diversity to use. Default="hypersphere_overlap". - cs : int, optional - Number of common substructures in molecular compound dataset. Used only if calculating - `explicit_diversity_index`. Default is "None". - - Returns - ------- - List[int]: - Indices of the points that were selected. - """ - old_len = 0 - to_delete = [] - selected = [] - rng = np.random.default_rng(seed=self.random_seed) - while len(selected) < num_selected: - num_needed = num_selected - len(selected) - # if the number of samples that should be selected is greater than number of bins, - # randomly select points from the bins. - if len(bins) <= num_needed: - # Go through each bin and select a point at random from it and delete it later - for bin_idx, bin_list in bins.items(): - random_int = rng.integers(low=0, high=len(bin_list), size=1)[0] - sample_index = bin_list.pop(random_int) - selected.append(sample_index) - if len(bin_list) == 0: - to_delete.append(bin_idx) - for idx in to_delete: - del bins[idx] - to_delete = [] - else: - # If number of samples that should be selected is less than the number of bins, - # calculate the diversity of each bin and select samples from bins with highest - # diversity. - diversity = [ - ( - compute_diversity( - features=X, - feature_subset=X[bin_list, :], - div_type=diversity_type, - cs=cs, - ), - bin_idx, - ) - for bin_idx, bin_list in bins.items() - ] - diversity.sort(reverse=True) - for _, bin_idx in diversity[:num_needed]: - random_int = rng.integers(low=0, high=len(bins[bin_idx]), size=1)[0] - sample_index = bins[bin_idx].pop(random_int) - selected.append(sample_index) - if len(selected) == old_len: - break - old_len = len(selected) - return selected - - def select_from_cluster(self, X: np.ndarray, num_selected: int, cluster_ids: np.ndarray = None): - """ - Grid partitioning algorithm for selecting points from cluster. - - Parameters - ---------- - X: ndarray of shape (n_samples, n_features) - Feature matrix of `n_samples` samples in `n_features` dimensional space. - num_selected: int - Number of molecules that need to be selected. - cluster_ids: ndarray - Indices of molecules that form a cluster - - Returns - ------- - selected: list[int] - List of ids of selected molecules with size `num_selected`. - """ - if not isinstance(X, np.ndarray): - raise TypeError(f"X {type(X)} should of type numpy array.") - if not isinstance(num_selected, int): - raise TypeError(f"num_selected {type(num_selected)} should be of type int.") - if cluster_ids is not None and not isinstance(cluster_ids, np.ndarray): - raise TypeError( - f"cluster_ids {type(cluster_ids)} should be either None or numpy " f"array." - ) - - if cluster_ids is not None: - X = X[cluster_ids] - bins = self.get_bins_from_method(X) - selected = self.select_from_bins(X, bins, num_selected) - return selected - - -class Medoid(SelectionBase): - """Selecting points using an algorithm adapted from KDTree. - - Points are initially used to construct a KDTree. Euclidean distances are used for this - algorithm. The first point selected is based on the ref_index provided and becomes the first - query point. An approximation of the furthest point to the query point is found using - find_furthest_neighbor and is selected. find_nearest_neighbor is then done to eliminate close - neighbors to the new selected point. Medoid is then calculated from previously selected points - and is used as the new query point for find_furthest_neighbor, repeating the process. Terminates - upon selecting requested number of points or if all available points exhausted. - - Adapted from: https://en.wikipedia.org/wiki/K-d_tree#Construction - """ - - def __init__( - self, - func_distance=lambda x, y: scipy.spatial.minkowski_distance(x, y) ** 2, - ref_index=0, - scaling=10, - ): - """ - Initializing class. - - Parameters - ---------- - fun_distance : callable - Function for calculating the pairwise distance between sample points. - `fun_dist(X) -> X_dist` takes a 2D feature array of shape (n_samples, n_features) - and returns a 2D distance array of shape (n_samples, n_samples). - ref_index : int, optional - Index for the sample to start selection from; this index is the first sample selected. - scaling: float - Percent of average maximum distance to use when eliminating the closest points. - - Notes - ----- - The `Mediod` implementation is based on the KDTree algorithm and therefore can give - different results for cases with duplicated points or the same features for different - objects in the original feature space. This is dicussed in - https://github.com/theochem/Selector/issues/238. - This is because the same features lead to the same distances in the tree, and this is a - known issue of sorting the points and indices in the KDTree algorithm, as discussed - in https://github.com/scipy/scipy/issues/19029. Therefore, precautions should be taken if - duplicated points are present in the dataset. - - """ - - self.starting_idx = ref_index - self.func_distance = func_distance - self.BT = collections.namedtuple("BT", ["value", "index", "left", "right"]) - self.FNRecord = collections.namedtuple("FNRecord", ["point", "index", "distance"]) - self.scaling = scaling / 100 - self.ratio = None - - def _kdtree(self, arr): - """Construct a k-d tree from an iterable of points. - - Parameters - ---------- - arr: list or np.ndarray - Coordinate array of points. - - Returns - ------- - kdtree: collections.namedtuple - KDTree organizing coordinates. - """ - - k = len(arr[0]) - - def build(points, depth, old_indices=None): - """Build a k-d tree from a set of points at a given depth.""" - if len(points) == 0: - return None - middle = len(points) // 2 - - # sort the points and indices - # indices, points = zip(*sorted(enumerate(points), key=lambda x: x[1][depth % k])) - indices = np.argsort(np.array(points)[:, depth % k], kind="stable") - points = np.array(points)[indices] - - if old_indices is not None: - indices = [old_indices[i] for i in indices] - return self.BT( - value=points[middle], - index=indices[middle], - left=build( - points=points[:middle], - depth=depth + 1, - old_indices=indices[:middle], - ), - right=build( - points=points[middle + 1 :], - depth=depth + 1, - old_indices=indices[middle + 1 :], - ), - ) - - kdtree = build(points=arr, depth=0) - return kdtree - - def _eliminate(self, tree, point, threshold, num_eliminate, bv): - """Eliminates points from being selected in future rounds. - - Parameters - ---------- - tree: scipy.spatial.KDTree - KDTree organizing coordinates. - point: list - Point where close neighbors should be eliminated. - threshold: float - An average of all the furthest distances found using find_furthest_neighbor - num_eliminate: int - Maximum number of points permitted to be eliminated. - bv: bitarray - Bitvector marking picked/eliminated points. - - Returns - ------- - num_eliminate: int - Maximum number of points permitted to be eliminated. - """ - _, elim_candidates = tree.query( - point, k=self.ratio, distance_upper_bound=np.sqrt(threshold), workers=-1 - ) - # elim_candidates can be integer or array of integers - # https://github.com/scipy/scipy/blob/a2a287d1f7c81154256ba742b4b8bb108a612166/scipy/spatial/_kdtree.py#L476 - if isinstance(elim_candidates, np.intp): - elim_candidates = [elim_candidates] - - if num_eliminate < 0: - elim_candidates = elim_candidates[:num_eliminate] - for index in elim_candidates: - try: - bv[index] = 1 - num_eliminate -= 1 - except IndexError: - break - return num_eliminate - - def _find_furthest_neighbor(self, kdtree, point, selected_bitvector): - """Find approximately the furthest neighbor in a k-d tree for a given point. - - Parameters - ---------- - kdtree: collections.namedtuple - KDTree organizing coordinates. - point: list - Query point for search. - selected_bitvector: bitarray - Bitvector to keep track of previously selected points from array. - - Returns - ------- - best: collections.namedtuple - The furthest point found in search. - """ - - k = len(point) - best = None - - def search(tree, depth): - # Recursively search through the k-d tree to find the - # furthest neighbor. - - nonlocal selected_bitvector - nonlocal best - - if tree is None: - return - - if not selected_bitvector[tree.index]: - distance = self.func_distance(tree.value, point) - if best is None or distance > best.distance: - best = self.FNRecord(point=tree.value, index=tree.index, distance=distance) - - axis = depth % k - diff = point[axis] - tree.value[axis] - if diff <= 0: - close, away = tree.left, tree.right - else: - close, away = tree.right, tree.left - - search(tree=away, depth=depth + 1) - if best is None or ( - close is not None and diff**2 <= 1.1 * ((point[axis] - close.value[axis]) ** 2) - ): - search(tree=close, depth=depth + 1) - - search(tree=kdtree, depth=0) - return best - - def select_from_cluster(self, arr, num_selected, cluster_ids=None): - """Main function for selecting points using the KDTree algorithm. - - Parameters - ---------- - arr: np.ndarray - Coordinate array of points - num_selected: int - Number of molecules that need to be selected. - cluster_ids: np.ndarray - Indices of molecules that form a cluster - - Returns - ------- - selected: list - List of ids of selected molecules - """ - if cluster_ids is not None: - arr = arr[cluster_ids] - - if isinstance(arr, np.ndarray): - arr = arr.tolist() - arr_len = len(arr) - fartree = self._kdtree(arr) - neartree = scipy.spatial.KDTree(arr) - - bv = bitarray.bitarray(arr_len) - bv[:] = 0 - selected = [self.starting_idx] - query_point = arr[self.starting_idx] - bv[self.starting_idx] = 1 - count = 1 - num_eliminate = arr_len - num_selected - self.ratio = math.ceil(num_eliminate / num_selected) - best_distance_av = 0 - while len(selected) < num_selected: - new_point = self._find_furthest_neighbor(fartree, query_point, bv) - if new_point is None: - return selected - selected.append(new_point.index) - bv[new_point.index] = 1 - query_point = (count * np.array(query_point) + np.array(new_point.point)) / (count + 1) - query_point = query_point.tolist() - if count == 1: - best_distance_av = new_point.distance - else: - best_distance_av = (count * best_distance_av + new_point.distance) / (count + 1) - if count == 1: - if num_eliminate > 0 and self.scaling != 0: - num_eliminate = self._eliminate( - neartree, - arr[self.starting_idx], - best_distance_av * self.scaling, - num_eliminate, - bv, - ) - if num_eliminate > 0 and self.scaling != 0: - num_eliminate = self._eliminate( - neartree, new_point.point, best_distance_av * self.scaling, num_eliminate, bv - ) - count += 1 - return selected +# -*- coding: utf-8 -*- +# +# The Selector is a Python library of algorithms for selecting diverse +# subsets of data for machine-learning. +# +# Copyright (C) 2022-2024 The QC-Devs Community +# +# This file is part of Selector. +# +# Selector is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 +# of the License, or (at your option) any later version. +# +# Selector is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see +# +# -- +"""Module for Partition-Based Selection Methods.""" + +import collections +import math + +import bitarray +import numpy as np +import scipy + +from selector.measures.diversity import compute_diversity +from selector.methods.base import SelectionBase + +__all__ = [ + "GridPartition", + "Medoid", +] + + +class GridPartition(SelectionBase): + r"""Select subset of sample points using the grid partitioning algorithms. + + Given the number of bins along each axis, samples are partitioned using various methods [1]_: + + - The `equisized_independent` partitions the feature space into bins of equal size along + each dimension. + + - The `equisized_dependent` partitions the space where the bins can have different length + in each dimension. I.e., the `l-`th dimension bins depend on the previous dimensions. + So, the order of features affects the outcome. + + - The `equifrequent_independent` divides the space into bins with approximately equal + number of sample points in each bin. + + - The `equifrequent_dependent` is similar to `equisized_dependent` where the partition in + each dimension will depend on the previous dimensions. + + References + ---------- + .. [1] Bayley, Martin J., and Peter Willett. "Binning schemes for partition-based + compound selection." Journal of Molecular Graphics and Modelling 17.1 (1999): 10-18. + """ + + def __init__( + self, nbins_axis: int, bin_method: str = "equisized_independent", random_seed: int = 42 + ): + """Initialize class. + + Parameters + ---------- + nbins_axis: int + Number of bins to partition each axis into. The total number of resulting bins is + `numb_bins_axis` raised to the power of the dimensionality of the feature space. + bin_method: str, optional + Method used to partition the sample points into bins. Options include: + "equisized_independent", "equisized_dependent", "equifrequent_independent" and + "equifrequent_dependent". + random_seed: int, optional + Seed for random selection of sample points from each bin. + """ + if not isinstance(nbins_axis, int): + raise TypeError(f"Number of bins should be integer, got {type(nbins_axis)}.") + if not isinstance(random_seed, int): + raise TypeError(f"The random seed should be integer, got {type(random_seed)}.") + if not isinstance(bin_method, str): + raise TypeError(f"The bin_method should be a string, got {type(bin_method)}.") + self.random_seed = random_seed + self.nbins_axis = nbins_axis + self.bin_method = bin_method + + @staticmethod + def partition_points_to_bins_equisized(X, nbins_axis): + r""" + Find all bins ids that has points in them and assign each point to each of those bins. + + For each `n_features` dimensions, get the minimum and maximum of feature to and use + `nbins_axis` to compute length of the bin. Then assign sample points to bins along + each axis/dimension of feature space. + + Parameters + ---------- + X: ndarray of shape (n_samples, n_features) + Feature matrix of `n_samples` samples in `n_features` dimensional space. + nbins_axis: int + Number of bins along each axis/dimension of feature space. + + Returns + ------- + unique_bin_indices: ndarray(int,) + Unique (without duplication) bin indices that have at least one sample point. + These are integer tuples :math:`(i_1, \cdot, i_\text{n_features})` with elements + corresponding to the bin index along each axis/dimension of feature space. + `inverse_ids` contains indices of `unique_bins_ids` for each of the :math:`N` points that + it is assigned to. + inverse_indices: ndarray(int,) + Indices of the unique bins (along specified axis) that can be used to reconstruct bin + index of each sample (`unique_bin_indices[inverse_indices]` gives bin index array). + """ + # find the minimum and maximum of features along axis/dimension + axis_minimum = np.min(X, axis=0) + axis_maximum = np.max(X, axis=0) + bin_length = (axis_maximum - axis_minimum) / nbins_axis + # assign each sample to a bin along each dimension (floor_divide returns array of integers) + bin_index = np.floor_divide(X - axis_minimum, bin_length) + # get unique bin indices (occupied by samples) and indices of the unique array + # (along specified axis) that can be used to reconstruct bin_index + # in other words, unique_bin_index[inverse_index] gives back bin_index array + unique_bin_index, inverse_index = np.unique(bin_index, return_inverse=True, axis=0) + return unique_bin_index, inverse_index + + @staticmethod + def partition_points_to_bins_equifrequent(X, nbins_axis): + r""" + Find all bins ids that contains points using the equifrequent method. + + The equifrequent method partitions each bin to have equal number of points. + This is done by doing a linear interpolation from integer indices and points, where + it is then evaluated on a uniform grid with number of bins as the spacing in each axis. + + Parameters + ---------- + X: ndarray of shape (n_samples, n_features) + Feature matrix of `n_samples` samples in `n_features` dimensional space. + nbins_axis: int + Number of bins along each axis or feature dimension. + + Returns + ------- + unique_bin_indices: ndarray(int,) + Unique (without duplication) bin indices that have at least one sample point. + These are integer tuples :math:`(i_1, \cdot, i_\text{n_features})` with elements + corresponding to the bin index along each axis/dimension of feature space. + `inverse_ids` contains indices of `unique_bins_ids` for each of the :math:`N` points that + it is assigned to. + inverse_indices: ndarray(int,) + Indices of the unique bins (along specified axis) that can be used to reconstruct bin + index of each sample (`unique_bin_indices[inverse_indices]` gives bin index array). + """ + n_samples = len(X) + # to obtain the lower and upper range of bins so that each bin has equal number of points, + # we interpolate the feature value for indices delineating the range of bins. + # I.e., sorting the features values along one axis, the (xp, fp) pairs are formed where + # xp denote the integer index of `n_samples points and fp the corresponding feature values. + # now, the value of feature is interpolated for the indices corresponding to lower and + # upper ranges of bins denoted by x. The x indices are obtained by evenly dividing the + # (0, n_samples) into nbins_axis bins (hence nbins_axis + 1 for number of samples indices). + # Obviously, in this way, the bins have roughly `n_samples` points. + # Note that the starting and ending indices of the bins are always 0 and n_samples, + # corresponding to the minimum and maximum of the feature values. + # The resulting bins_edge defines a monotonically increasing array of bin edges, including + # the rightmost edge, allowing for non-uniform bin widths. + # The bins_edge[0] and bins_edge[-1] correspond to the min and max of the feature values. + bins_edge = np.interp( + x=np.linspace(0, n_samples, nbins_axis + 1), xp=np.arange(n_samples), fp=np.sort(X) + ) + # Note: alternatively, one can use x=np.linspace(0, n_samples - 1, nbins_axis + 1) so + # that the ending index corresponds to the index of the last sample point. This would not + # be an issue, because the numpy interpolate function np.interp has two attributes called + # right/left, so if the value x is outside the interpolating domain, then it returns the + # closest data point fp[-1]/fp[0], respectively. This causes the partition into bins to + # always include the endpoints. + + # To assign samples into bins, sample features are subtracted from the bins_edge, and + # the index of the bins_edge where the difference switches from negative to positive is + # the bin index that the sample is assigned to. The switch from negative to positive is + # identified by the argmax function after setting all the non-negative values to -inf. + pt_to_bind = bins_edge - X[:, None] + pt_to_bind[pt_to_bind >= 0.0] = -np.inf + bin_index = np.argmax(pt_to_bind, axis=1) + unique_bin_ids, inverse_ids = np.unique(bin_index, return_inverse=True) + return unique_bin_ids, inverse_ids + + def get_bins_from_method(self, X): + r"""Assign sample points to bins based on the partitioning method. + + Parameters + ---------- + X: ndarray of shape (n_samples, n_features) + Feature matrix of `n_samples` samples in `n_features` dimensional space. + + Returns + ------- + bins: dict[Tuple(int), List[int]] + Dictionary of bins where keys are the unique bin indices (that contain at least one + sample point) and the values are the list of sample indices in that bin. + """ + + # dictionary of bins where the keys are the unique bin indices (that contain at least one + # sample) and the values are the list of sample indices in that bin. + bins = {} + + if self.bin_method == "equisized_independent": + # partition each dimension/feature independently into `num_bins_axis` bins + unique_bin_index, inverse_index = self.partition_points_to_bins_equisized( + X, self.nbins_axis + ) + # populate bins dictionary + for i, key in enumerate(unique_bin_index): + bins[tuple(key)] = list(np.where(inverse_index == i)[0]) + + elif self.bin_method == "equisized_dependent": + # partition the first dimension (1st feature axis) into `num_bins_axis` bins + unique_bin_index, inverse_index = self.partition_points_to_bins_equisized( + X[:, 0], self.nbins_axis + ) + # populate bins dictionary based on the 1st feature + for i, key in enumerate(unique_bin_index): + bins[tuple([key])] = list(np.where(inverse_index == i)[0]) + + # loop over the remaining dimensions (2nd to last feature axis), and for each axis + # partition the points in each bin of the previous axes into `num_bins_axis` bins + # as a result, each iteration adds a new dimension to the bins dictionary + for index_feature in range(1, X.shape[1]): + # make a dictionary to store the bins for the current axis + bins_axis = {} + # divide points in each bin into `num_bins_axis` bins based on the i-th feature + for bin, index_samples in bins.items(): + # equisized partition of points in bin along i-th feature + unique_bin_index, inverse_index = self.partition_points_to_bins_equisized( + X[index_samples, index_feature], self.nbins_axis + ) + # update the bins_axis to include the new dimension/feature for the current bin + for i, bin_index in enumerate(unique_bin_index): + # form a new bin_index by appending current bin_index to the previous bin + key = tuple(list(bin) + [bin_index]) + bins_axis.update( + {key: list(np.array(index_samples)[np.where(inverse_index == i)[0]])} + ) + bins = bins_axis + + elif self.bin_method == "equifrequent_independent": + # partition each dimension of feature space independently into `num_bins_axis` bins + bins_features = np.zeros(X.shape, dtype=int) + for index_feature in range(0, X.shape[1]): + unique_bin_index, inverse_index = self.partition_points_to_bins_equifrequent( + X[:, index_feature], self.nbins_axis + ) + bins_features[:, index_feature] = unique_bin_index[inverse_index] + unique_bin_index, inverse_index = np.unique(bins_features, return_inverse=True, axis=0) + + # populate bins dictionary + for i, key in enumerate(unique_bin_index): + bins[tuple(key)] = list(np.where(inverse_index == i)[0]) + + elif self.bin_method == "equifrequent_dependent": + # partition the first dimension (1st feature axis) into `num_bins_axis` bins + unique_bin_index, inverse_index = self.partition_points_to_bins_equifrequent( + X[:, 0], self.nbins_axis + ) + # populate bins dictionary based on the 1st feature + for i, key in enumerate(unique_bin_index): + bins[tuple([key])] = list(np.where(inverse_index == i)[0]) + + # loop over the remaining dimensions (2nd to last feature axis), and for each axis + # partition the points in each bin of the previous axes into `num_bins_axis` bins + for index_feature in range(1, X.shape[1]): + # make a dictionary to store the bins for the current axis + bins_axis = {} + # divide points in each bin, based on the i-th feature, into `num_bins_axis` bins + for bin, index_samples in bins.items(): + # equifrequent partition of points in bin along i-th feature + unique_bin_index, inverse_index = self.partition_points_to_bins_equifrequent( + X[index_samples, index_feature], self.nbins_axis + ) + # update the bins_axis to include the new dimension/feature for the current bin + for i, key in enumerate(unique_bin_index): + # form a new bin_index by appending current bin_index to the previous bin + key = tuple(list(bin) + [key]) + bins_axis.update( + {key: list(np.array(index_samples)[np.where(inverse_index == i)[0]])} + ) + bins = bins_axis + else: + raise ValueError(f"{self.bin_method} not a valid bin_method") + + return bins + + def select_from_bins( + self, + X, + bins, + num_selected, + diversity_type="hypersphere_overlap", + cs=None, + ): + r""" + From the bins, select a certain number of points of the bins. + + Points are selected in an iterative manner. If the number of points needed to be selected + is greater than number of bins left then randomly select points from each of the bins. If + any of the bins are empty then remove the bins. If it is less than the number of bins left, + then calculate the diversity of each bin and choose points of bins with the highest diversity. + + Parameters + ---------- + X: ndarray of shape (n_samples, n_features) + Feature matrix of `n_samples` samples in `n_features` dimensional space. + bins: dict(tuple(int), list[int]) + The bins that map to the id the bin (as a tuple of integers) and returns + the indices of the points that are contained in that bin. + num_selected: int + Number of points to select from the bins. + diversity_type: str, optional + Type of diversity to use. Default="hypersphere_overlap". + cs : int, optional + Number of common substructures in molecular compound dataset. Used only if calculating + `explicit_diversity_index`. Default is "None". + + Returns + ------- + List[int]: + Indices of the points that were selected. + """ + old_len = 0 + to_delete = [] + selected = [] + rng = np.random.default_rng(seed=self.random_seed) + while len(selected) < num_selected: + num_needed = num_selected - len(selected) + # if the number of samples that should be selected is greater than number of bins, + # randomly select points from the bins. + if len(bins) <= num_needed: + # Go through each bin and select a point at random from it and delete it later + for bin_idx, bin_list in bins.items(): + random_int = rng.integers(low=0, high=len(bin_list), size=1)[0] + sample_index = bin_list.pop(random_int) + selected.append(sample_index) + if len(bin_list) == 0: + to_delete.append(bin_idx) + for idx in to_delete: + del bins[idx] + to_delete = [] + else: + # If number of samples that should be selected is less than the number of bins, + # calculate the diversity of each bin and select samples from bins with highest + # diversity. + diversity = [ + ( + compute_diversity( + features=X, + feature_subset=X[bin_list, :], + div_type=diversity_type, + cs=cs, + ), + bin_idx, + ) + for bin_idx, bin_list in bins.items() + ] + diversity.sort(reverse=True) + for _, bin_idx in diversity[:num_needed]: + random_int = rng.integers(low=0, high=len(bins[bin_idx]), size=1)[0] + sample_index = bins[bin_idx].pop(random_int) + selected.append(sample_index) + if len(selected) == old_len: + break + old_len = len(selected) + return selected + + def select_from_cluster(self, X: np.ndarray, num_selected: int, cluster_ids: np.ndarray = None): + """ + Grid partitioning algorithm for selecting points from cluster. + + Parameters + ---------- + X: ndarray of shape (n_samples, n_features) + Feature matrix of `n_samples` samples in `n_features` dimensional space. + num_selected: int + Number of molecules that need to be selected. + cluster_ids: ndarray + Indices of molecules that form a cluster + + Returns + ------- + selected: list[int] + List of ids of selected molecules with size `num_selected`. + """ + if not isinstance(X, np.ndarray): + raise TypeError(f"X {type(X)} should of type numpy array.") + if not isinstance(num_selected, int): + raise TypeError(f"num_selected {type(num_selected)} should be of type int.") + if cluster_ids is not None and not isinstance(cluster_ids, np.ndarray): + raise TypeError( + f"cluster_ids {type(cluster_ids)} should be either None or numpy " f"array." + ) + + if cluster_ids is not None: + X = X[cluster_ids] + bins = self.get_bins_from_method(X) + selected = self.select_from_bins(X, bins, num_selected) + return selected + + +class Medoid(SelectionBase): + """Selecting points using an algorithm adapted from KDTree. + + Points are initially used to construct a KDTree. Euclidean distances are used for this + algorithm. The first point selected is based on the ref_index provided and becomes the first + query point. An approximation of the furthest point to the query point is found using + find_furthest_neighbor and is selected. find_nearest_neighbor is then done to eliminate close + neighbors to the new selected point. Medoid is then calculated from previously selected points + and is used as the new query point for find_furthest_neighbor, repeating the process. Terminates + upon selecting requested number of points or if all available points exhausted. + + Adapted from: https://en.wikipedia.org/wiki/K-d_tree#Construction + """ + + def __init__( + self, + func_distance=lambda x, y: scipy.spatial.minkowski_distance(x, y) ** 2, + ref_index=0, + scaling=10, + ): + """ + Initializing class. + + Parameters + ---------- + fun_distance : callable + Function for calculating the pairwise distance between sample points. + `fun_dist(X) -> X_dist` takes a 2D feature array of shape (n_samples, n_features) + and returns a 2D distance array of shape (n_samples, n_samples). + ref_index : int, optional + Index for the sample to start selection from; this index is the first sample selected. + scaling: float + Percent of average maximum distance to use when eliminating the closest points. + + Notes + ----- + The `Mediod` implementation is based on the KDTree algorithm and therefore can give + different results for cases with duplicated points or the same features for different + objects in the original feature space. This is dicussed in + https://github.com/theochem/Selector/issues/238. + This is because the same features lead to the same distances in the tree, and this is a + known issue of sorting the points and indices in the KDTree algorithm, as discussed + in https://github.com/scipy/scipy/issues/19029. Therefore, precautions should be taken if + duplicated points are present in the dataset. + + """ + + self.starting_idx = ref_index + self.func_distance = func_distance + self.BT = collections.namedtuple("BT", ["value", "index", "left", "right"]) + self.FNRecord = collections.namedtuple("FNRecord", ["point", "index", "distance"]) + self.scaling = scaling / 100 + self.ratio = None + + def _kdtree(self, arr): + """Construct a k-d tree from an iterable of points. + + Parameters + ---------- + arr: list or np.ndarray + Coordinate array of points. + + Returns + ------- + kdtree: collections.namedtuple + KDTree organizing coordinates. + """ + + k = len(arr[0]) + + def build(points, depth, old_indices=None): + """Build a k-d tree from a set of points at a given depth.""" + if len(points) == 0: + return None + middle = len(points) // 2 + + # sort the points and indices + # indices, points = zip(*sorted(enumerate(points), key=lambda x: x[1][depth % k])) + indices = np.argsort(np.array(points)[:, depth % k], kind="stable") + points = np.array(points)[indices] + + if old_indices is not None: + indices = [old_indices[i] for i in indices] + return self.BT( + value=points[middle], + index=indices[middle], + left=build( + points=points[:middle], + depth=depth + 1, + old_indices=indices[:middle], + ), + right=build( + points=points[middle + 1 :], + depth=depth + 1, + old_indices=indices[middle + 1 :], + ), + ) + + kdtree = build(points=arr, depth=0) + return kdtree + + def _eliminate(self, tree, point, threshold, num_eliminate, bv): + """Eliminates points from being selected in future rounds. + + Parameters + ---------- + tree: scipy.spatial.KDTree + KDTree organizing coordinates. + point: list + Point where close neighbors should be eliminated. + threshold: float + An average of all the furthest distances found using find_furthest_neighbor + num_eliminate: int + Maximum number of points permitted to be eliminated. + bv: bitarray + Bitvector marking picked/eliminated points. + + Returns + ------- + num_eliminate: int + Maximum number of points permitted to be eliminated. + """ + _, elim_candidates = tree.query( + point, k=self.ratio, distance_upper_bound=np.sqrt(threshold), workers=-1 + ) + # elim_candidates can be integer or array of integers + # https://github.com/scipy/scipy/blob/a2a287d1f7c81154256ba742b4b8bb108a612166/scipy/spatial/_kdtree.py#L476 + if isinstance(elim_candidates, np.intp): + elim_candidates = [elim_candidates] + + if num_eliminate < 0: + elim_candidates = elim_candidates[:num_eliminate] + for index in elim_candidates: + try: + bv[index] = 1 + num_eliminate -= 1 + except IndexError: + break + return num_eliminate + + def _find_furthest_neighbor(self, kdtree, point, selected_bitvector): + """Find approximately the furthest neighbor in a k-d tree for a given point. + + Parameters + ---------- + kdtree: collections.namedtuple + KDTree organizing coordinates. + point: list + Query point for search. + selected_bitvector: bitarray + Bitvector to keep track of previously selected points from array. + + Returns + ------- + best: collections.namedtuple + The furthest point found in search. + """ + + k = len(point) + best = None + + def search(tree, depth): + # Recursively search through the k-d tree to find the + # furthest neighbor. + + nonlocal selected_bitvector + nonlocal best + + if tree is None: + return + + if not selected_bitvector[tree.index]: + distance = self.func_distance(tree.value, point) + if best is None or distance > best.distance: + best = self.FNRecord(point=tree.value, index=tree.index, distance=distance) + + axis = depth % k + diff = point[axis] - tree.value[axis] + if diff <= 0: + close, away = tree.left, tree.right + else: + close, away = tree.right, tree.left + + search(tree=away, depth=depth + 1) + if best is None or ( + close is not None and diff**2 <= 1.1 * ((point[axis] - close.value[axis]) ** 2) + ): + search(tree=close, depth=depth + 1) + + search(tree=kdtree, depth=0) + return best + + def select_from_cluster(self, arr, num_selected, cluster_ids=None): + """Main function for selecting points using the KDTree algorithm. + + Parameters + ---------- + arr: np.ndarray + Coordinate array of points + num_selected: int + Number of molecules that need to be selected. + cluster_ids: np.ndarray + Indices of molecules that form a cluster + + Returns + ------- + selected: list + List of ids of selected molecules + """ + if cluster_ids is not None: + arr = arr[cluster_ids] + + if isinstance(arr, np.ndarray): + arr = arr.tolist() + arr_len = len(arr) + fartree = self._kdtree(arr) + neartree = scipy.spatial.KDTree(arr) + + bv = bitarray.bitarray(arr_len) + bv[:] = 0 + selected = [self.starting_idx] + query_point = arr[self.starting_idx] + bv[self.starting_idx] = 1 + count = 1 + num_eliminate = arr_len - num_selected + self.ratio = math.ceil(num_eliminate / num_selected) + best_distance_av = 0 + while len(selected) < num_selected: + new_point = self._find_furthest_neighbor(fartree, query_point, bv) + if new_point is None: + return selected + selected.append(new_point.index) + bv[new_point.index] = 1 + query_point = (count * np.array(query_point) + np.array(new_point.point)) / (count + 1) + query_point = query_point.tolist() + if count == 1: + best_distance_av = new_point.distance + else: + best_distance_av = (count * best_distance_av + new_point.distance) / (count + 1) + if count == 1: + if num_eliminate > 0 and self.scaling != 0: + num_eliminate = self._eliminate( + neartree, + arr[self.starting_idx], + best_distance_av * self.scaling, + num_eliminate, + bv, + ) + if num_eliminate > 0 and self.scaling != 0: + num_eliminate = self._eliminate( + neartree, new_point.point, best_distance_av * self.scaling, num_eliminate, bv + ) + count += 1 + return selected diff --git a/selector/methods/similarity.py b/selector/methods/similarity.py index d3ea8c58..3fa5b581 100644 --- a/selector/methods/similarity.py +++ b/selector/methods/similarity.py @@ -1,1048 +1,1048 @@ -# -*- coding: utf-8 -*- -# -# The Selector is a Python library of algorithms for selecting diverse -# subsets of data for machine-learning. -# -# Copyright (C) 2022-2024 The QC-Devs Community -# -# This file is part of Selector. -# -# Selector is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 -# of the License, or (at your option) any later version. -# -# Selector is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see -# -# -- -"""Module for Similarity-Based Selection Methods. - -This module contains the classes and functions for the similarity-based selection methods. To select -a diverse subset of molecules the similarity-based selection methods select the molecules such that -the similarity between the molecules in the subset is minimized. The similarity of a set of -molecules is calculated using an n-array similarity index. These indexes compare n molecules at a -time and return a value between 0 and 1, where 0 means that all the molecules in the set are -completely different and 1 means that the molecules are identical. - -The ideas behind the similarity-based selection methods are described in the following papers: - (esim) - https://jcheminf.biomedcentral.com/articles/10.1186/s13321-021-00505-3 - https://jcheminf.biomedcentral.com/articles/10.1186/s13321-021-00504-4 - (isim) - TODO: Add paper - -""" - -import math -import random -from math import log -from typing import List, Optional, Union -import warnings - -import numpy as np - -from selector.methods.base import SelectionBase - -__all__ = [ - "NSimilarity", - "SimilarityIndex", -] - - -class NSimilarity(SelectionBase): - r"""Select samples of vectors using n-ary similarity indexes between vectors. - - The algorithms in this class select a diverse subset of vectors such that the similarity - between the vectors in the subset is minimized. The similarity of a set of vectors is - calculated using an n-ary similarity index. These indexes compare n vectors (e.g. molecular - fingerprints) at a time and return a value between 0 and 1, where 0 means that all the vectors - in the set are completely different and 1 means that the vectors are identical. - - The algorithm starts by selecting a starting reference data point. Then, the next data point is - selected such as the similarity value of the group of selected data points is minimized. The - process is repeated until the desired number of data points is selected. - - Notes - ----- - The ideas behind the similarity-based selection methods are described in the following papers: - - """ - - def __init__( - self, - method: str = "isim", - inv_order: int = 1, - similarity_index: str = "RR", - w_factor: str = "fraction", - c_threshold: Union[None, str, int] = None, - preprocess_data: bool = True, - ): - """Initialize class. - - Parameters - ---------- - method: {"isim", "esim"} - Method used for calculating the similarity indices. The methods are: - - "isim": Instant Similarity - The instant similarity index calculates the average similarity of a set of - objects without the need to calculate the similarity of all the possible pairs. - This method is easier to use than the ``esim`` (extended similarity index) as it - does not require the use of weight factors or coincidence thresholds. - - "esim": Extended Similarity - The extended similarity index calculates the similarity of a set of objects - without the need to calculate the similarity of all the possible pairs. This - method requires the use of weight factors and coincidence thresholds. - inv_order: int - Integer indicating the 1/inv_order power used to approximate the average of the - similarity values elevated to 1/inv_order. - similarity_index: str - Key with the abbreviation of the similarity index that will be used to perform the - selection. - Possible values are: - AC: Austin-Colwell - BUB: Baroni-Urbani-Buser - CTn: Consoni-Todschini - Fai: Faith - Gle: Gleason - Ja: Jaccard - Ja0: Jaccard 0-variant - JT: Jaccard-Tanimoto - RT: Rogers-Tanimoto - RR: Russel-Rao - SM: Sokal-Michener - SSn: Sokal-Sneath n - w_factor: {"fraction", "power_n"} - Type of weight function that will be used for calculating the counters. - 'fraction' : similarity = d[k]/n - dissimilarity = 1 - (d[k] - n_objects % 2)/n_objects - 'power_n' : similarity = n**-(n_objects - d[k]) - dissimilarity = n**-(d[k] - n_objects % 2) - other values : similarity = dissimilarity = 1 - Only used for the 'esim' method. Default is 'fraction'. - c_threshold: {None, 'dissimilar', int} - Coincidence threshold used for calculating the similarity counters. A column of the - elements is considered to be a coincidence among the elements if the number of elements - that have the same value in that position is greater than the coincidence threshold. - None : Default, c_threshold = n_objects % 2 - 'dissimilar' : c_threshold = ceil(n_objects / 2) - int : Integer number < n_objects - Only used for the 'esim' method. Default is None. - preprocess_data: bool - Every data element must be between 0 and 1 for the similarity indexes to work. If - preprocess_data is True, the data is scaled between 0 and 1 using a strategy that is - compatible with the similarity indexes. If preprocess_data is False, the data is not - scaled and it is assumed that the data is already between 0 and 1. - - """ - # check if the method is valid - if method not in ["isim", "esim"]: - raise ValueError(f'Method "{method}" is not available please select "isim" or "esim".') - # check if the similarity index is valid - if similarity_index not in _similarity_index_dict: - raise ValueError( - f'Similarity index "{similarity_index}" is not available. ' - f"See the documentation for the available similarity indexes." - ) - # for the esim method, check if the w_factor is valid - if method == "esim": - # check if the w_factor and c_threshold are valid - if w_factor != "fraction": - if w_factor.split("_")[0] != "power" or not w_factor.split("_")[-1].isdigit(): - print( - f'Invalid weight factor "{w_factor}" given. Using default value ' - '"similarity = dissimilarity = 1".' - ) - w_factor = False - # check if the c_threshold is valid - if c_threshold not in ["dissimilar", None]: - if not isinstance(c_threshold, int): - raise ValueError( - f'Invalid c_threshold. It must be an integer or "dissimilar" or None. ' - f"Given c_threshold = {c_threshold}" - ) - - self.method = method - self.inv_order = inv_order - self.similarity_index = similarity_index - self.w_factor = w_factor - self.c_threshold = c_threshold - self.preprocess_data = preprocess_data - # create an instance of the SimilarityIndex class. It is used to calculate the similarity - # index of the sets of selected objects. - self.si = SimilarityIndex( - method=self.method, - inv_order=self.inv_order, - sim_index=self.similarity_index, - c_threshold=self.c_threshold, - w_factor=self.w_factor, - ) - - def _scale_data(self, X: np.ndarray): - r"""Scales the data between so it can be used with the similarity indexes. - - First each data point is normalized to be between 0 and 1. - - .. math:: - x_{ij} = \frac{x_{ij} - min(x_j)}{max(x_j) - min(x_j)} - - Then, the average of each column is calculated. Finally, each element of the final working - array will be defined as - - .. math:: - w_{ij} = 1 - | x_{ij} - a_j | - - where :math:`x_{ij}` is the element of the normalized array, - and :math:`a_j` is the average of the j-th - column of the normalized array. - - Parameters - ---------- - X: np.ndarray - Array of features (columns) for each sample (rows). - """ - min_value = np.min(X) - max_value = np.max(X) - # normalize the data to be between 0 and 1 for working with the similarity indexes - normalized_data = (X - min_value) / (max_value - min_value) - # calculate the average of the columns - col_average = np.average(normalized_data, axis=0) - - # each element of the final working array will be defined as w_ij = 1 - | x_ij - a_j | - # where x_ij is the element of the normalized array, and a_j is the average of the j-th - # column of the normalized array. - data = 1 - np.abs(normalized_data - col_average) - return data - - def _get_new_index( - self, - X: np.ndarray, - selected_condensed: np.ndarray, - num_selected: int, - select_from: np.ndarray, - ) -> int: - r"""Select a new diverse sample from the data. - - The function selects a new sample such that the similarity of the new set of selected - samples is minimized. - - Parameters - ---------- - X: np.ndarray - Array of features (columns) for each sample (rows). - selected_condensed: np.ndarray - Columnwise sum of all the samples selected so far. - num_selected: int - Number of samples selected so far. - select_from: np.ndarray - Array of integers representing the indices of the samples that have not been selected - yet. - - Returns - ------- - selected: int - Index of the new selected sample. - - """ - # check if the data was previously scaled - if np.max(X) > 1 or np.min(X) < 0: - raise ValueError( - "The data was not scaled between 0 and 1. " - "Use the _scale_data function to scale the data." - ) - - # Number of total vectors used to calculate th similarity. It is the number of samples - # selected so far + 1, because the similarities are computed for the sets of samples after - # a new selection is made. - n_total = num_selected + 1 - - # min value that is guaranteed to be higher than all the comparisons, this value should be a - # warranty that a exist a set of samples with similarity lower than min_value. The max - # possible similarity value for set of samples is 1.00. - min_value = 1.01 - - # placeholder index, initiating variable with a number outside the possible index values - index = X.shape[0] + 1 - - # for all indices that have not been selected - for sample_idx in select_from: - # column sum - c_total = selected_condensed + X[sample_idx] - - # calculating similarity - sim_index = self.si(c_total, nsamples=n_total) - - # if the sim of the set is less than the similarity of the previous diverse set, - # update min_value and index - if sim_index < min_value: - index = sample_idx - min_value = sim_index - - return index - - def calculate_medoid(self, X: np.ndarray, c_total=None) -> int: - """Calculate the medoid of a set of real-valued vectors or binary objects. - - Parameters - ---------- - X: np.array - np.array of all the real-valued vectors or binary objects. - c_total: - np.array with the columnwise sums of the data, not necessary to provide. - """ - # Check if the data is a np.ndarray of a list - if not isinstance(X, np.ndarray): - raise TypeError("Input data is not a np.ndarray, please input the right data type") - # Check if the data is one dimensional - if X.ndim != 2: - raise ValueError( - "Data must be a two dimensional np.ndarray for calculating the medoid." - ) - # Check if the data has at least 3 rows - if X.shape[0] < 3: - raise ValueError("Input data must have at least 3 rows to calculate the medoid.") - - # check if c_total is provided and if not, calculate it - if c_total is None: - c_total = np.sum(X, axis=0) - # if c_total is provided, check if it has the same number of columns as the data - elif c_total is not None and len(X[0]) != len(c_total): - raise ValueError("Dimensions of objects and columnwise sum differ") - - # get the total number of objects - nsamples = X.shape[0] - - # Initialize the selected index with a number outside the possible index values - index = nsamples + 1 - - # minimum similarity value that is guaranteed to be higher than all the comparisons, this - # value should be a warranty that a exist a sample with similarity lower than min_sim. The - # max possible similarity value for set of samples is 1.00. - min_sim = 1.01 - - # For each sample in the set, calculate the column-wise sum of the data without the sample - comp_sums = c_total - X - - # The medoid is calculated using an instance of the SimilarityIndex class with the same - # parameters as the current class, but with the inv_order = 1 - si = SimilarityIndex( - method=self.method, - inv_order=1, - sim_index=self.similarity_index, - c_threshold=self.c_threshold, - w_factor=self.w_factor, - ) - - # for each sample calculate the similarity index of the complete set without the sample - for idx, row in enumerate(comp_sums): - # calculate the similarity index of the set of objects without the current object - sim_index = si(row, nsamples=nsamples - 1) - # if the similarity is lower than the previous minimum similarity, update the minimum - # similarity and the index - if sim_index < min_sim: - min_sim, index = sim_index, idx - # the index of the object that increases more the similarity of the set when added is - # returned (the medoid) - return index - - def calculate_outlier(self, X: np.ndarray = None, c_total=None) -> int: - r"""Calculate the outlier of a set of real-valued vectors or binary objects. - - Calculates the outlier of a set of real-valued vectors or binary objects. Using the - similarity index provided in the class initialization. - - Parameters - ---------- - X: np.array - np.array of all the real-valued vectors or binary objects. - c_total: np.array, optional - np.array with the column-wise sums of the data. - """ - # Check if the data is a np.ndarray of a list - if not isinstance(X, np.ndarray): - raise TypeError("Input data is not a np.ndarray, please input the right data type") - # Check if the data is one dimensional - if X.ndim != 2: - raise ValueError( - "Data must be a two dimensional np.ndarray for calculating the outlier." - ) - # Check if the data has at least 3 rows - if X.shape[0] < 3: - raise ValueError("Input data must have at least 3 rows to calculate the outlier.") - - # check if c_total is provided and if not, calculate it - if c_total is None: - c_total = np.sum(X, axis=0) - # if c_total is provided, check if it has the same number of columns as the data - elif c_total is not None and len(X[0]) != len(c_total): - raise ValueError("Dimensions of objects and columnwise sum differ") - - nsamples = X.shape[0] - - # Initialize the selected index with a number outside the possible index values - index = nsamples + 1 - - # maximum similarity value that is guaranteed to be lower than all the comparisons, this - # value should be a warranty that a exist a sample with similarity lower than min_sim. The - # min possible similarity value for set of samples is 0.00. - max_sim = -0.01 - - # For each sample in the set, calculate the columnwise sum of the data without the sample - comp_sums = c_total - X - - # The outlier is calculated using an instance of the SimilarityIndex class with the same - # parameters as the current class, but with the inv_order = 1 - - # for each sample calculate the similarity index of the complete set without the sample - for idx, obj in enumerate(comp_sums): - # calculate the similarity index of the set of objects without the current object - sim_index = self.si(X=obj, nsamples=nsamples - 1) - # if the similarity is bigger than the previous minimum similarity, update the minimum - # similarity and the index - if sim_index > max_sim: - max_sim, index = sim_index, idx - # the index of the object that decreases more the similarity of the set when added is - # returned (the outlier) - return index - - def select_from_cluster( - self, - X: np.ndarray, - size: int, - labels: Optional[np.ndarray] = None, - start: Union[str, List[int]] = "medoid", - ) -> List[int]: - r"""Algorithm of nary similarity selection for selecting points from cluster. - - Parameters - ---------- - X: np.ndarray - Array of features (columns) for each sample (rows). - size: int - Number of sample points to select (i.e. size of the subset). - labels: np.ndarray, optional - Array of integers or strings representing the points ids of the data that belong to the - current cluster. If `None`, all the samples in the data are treated as one cluster. - start: str or list - srt: key on what is used to start the selection {'medoid', 'random', 'outlier'}. - list: indices of points that are included in the selection since the beginning. - - Returns - ------- - selected: list - Indices of the selected sample points. - - """ - # check for valid start value and raise an error if it is not - if start not in ["medoid", "random", "outlier"]: - if not isinstance(start, list) or not all(isinstance(i, int) for i in start): - raise ValueError( - "Select a correct starting point: medoid, random, outlier or a list of indices." - ) - # check if cluster_ids are provided - if labels is not None: - # extract the data corresponding to the cluster_ids - X = np.take(X, labels, axis=0) - - # total number of objects in the current cluster - nsamples = X.shape[0] - # ids of the data points in the current cluster (0, 1, 2, ..., samples-1) - data_ids = np.array(range(nsamples)) - - # check if the number of selected objects is less than the total number of objects - if size > nsamples: - raise ValueError( - f"Number of samples is less than the requested sample size: {nsamples} < {size}." - ) - - # The data is marked to be preprocessed scale the data between 0 and 1 using a strategy - # that is compatible with the similarity indexes - if self.preprocess_data: - X = self._scale_data(X) - else: - # check if the data is between 0 and 1 and raise an error if it is not - if np.max(X) > 1 or np.min(X) < 0: - raise ValueError( - "The data was not scaled between 0 and 1. " - "Use the _scale_data function to scale the data." - ) - - # select the index (of the working data) corresponding to the medoid of the data using the - # similarity index - if start == "medoid": - seed = self.calculate_medoid(X) - selected = [seed] - # select the index (of the working data) corresponding to a random data point - elif start == "random": - seed = random.randint(0, nsamples - 1) - selected = [seed] - # select the index (of the working data) corresponding to the outlier of the data using the - # similarity index - elif start == "outlier": - seed = self.calculate_outlier(X) - selected = [seed] - # if a list of cluster_ids is provided, select the data_ids corresponding indices - elif isinstance(start, list): - if labels is not None: - # check if all starting indices are in this cluster - if not all(label in labels for label in start): - raise ValueError( - "Some of the provided initial indexes are not in the cluster data." - ) - # select the indices of the data_ids that correspond to the provided starting points - # provided from cluster_ids - selected = [i for i, j in enumerate(labels) if j in start] - else: - # check if all starting indices are in the data - if not all(label in data_ids for label in start): - raise ValueError("Some of the provided initial indexes are not in the data.") - # select the indices of the data_ids that correspond to the provided starting points - selected = start[:] - # Number of initial objects - num_selected = len(selected) - - # get selected samples form the working data array - selected_objects = np.take(X, selected, axis=0) - # Calculate the columnwise sum of the selected samples - selected_condensed = np.sum(selected_objects, axis=0) - - # until the desired number of objects is selected a new object is selected. - while num_selected < size: - # indices from which to select the new data points - select_from = np.delete(data_ids, selected) - - # Select new index. The new object is selected such that from all possible objects the - # similarity of the set of (selected_objects + new_object) is a minimum. - new_index = self._get_new_index(X, selected_condensed, num_selected, select_from) - - # updating column sum vector - selected_condensed += X[new_index] - - # updating selected indices - selected.append(new_index) - num_selected += 1 - - return selected - - -class SimilarityIndex: - r"""Calculate the n-ary similarity index of a set of vectors. - - This class provides methods for calculating the similarity index of a set of vectors represented - as a matrix. Each vector is a row in the matrix, and each column represents a feature of the - vector. The features in the vectors must be binary or real numbers between 0 and 1. - """ - - def __init__( - self, - method: str = "isim", - inv_order: int = 1, - sim_index: str = "RR", - c_threshold: Union[None, str, int] = None, - w_factor: str = "fraction", - ): - """Initialize the class. - - Parameters - ---------- - method : {"isim", "esim"}, optional - Method used for calculating the similarity indexes. The methods are: - - "isim": Instant Similarity - The instant similarity index calculates the average similarity of a set of - objects without the need to calculate the similarity of all the possible pairs. - This method is easier to use than the ``esim`` (extended similarity index) as it - does not require the use of weight factors or coincidence thresholds. - - "esim": Extended Similarity - The extended similarity index calculates the similarity of a set of objects - without the need to calculate the similarity of all the possible pairs. This - method requires the use of weight factors and coincidence thresholds. - Default is "isim". - - inv_order : int, optional - Integer indicating the 1/inv_order power used to approximate the average of the - similarity values elevated to 1/inv_order. This is not used for calculating the - medoid or the outlier. Default is 1. - - sim_index : str, optional - The key with the abbreviation of the similarity index to be used for calculations. - Possible values are: - - 'AC': Austin-Colwell - - 'BUB': Baroni-Urbani-Buser - - 'CTn': Consoni-Todschini n - - 'Fai': Faith - - 'Gle': Gleason - - 'Ja': Jaccard - - 'Ja0': Jaccard 0-variant - - 'JT': Jaccard-Tanimoto - - 'RT': Rogers-Tanimoto - - 'RR': Russel-Rao - - 'SM': Sokal-Michener - - 'SSn': Sokal-Sneath n - Default is 'RR'. - - c_threshold : {None, 'dissimilar', int}, optional - The coincidence threshold used for calculating similarity counters. A position in the - elements is considered a coincidence (coincides among all the elements considered) if - the number of elements that have the same value in that position is greater than the - coincidence threshold. - - None : Default, c_threshold = n_objects % 2 - - 'dissimilar' : c_threshold = ceil(n_objects / 2) - - int : Integer number < n_objects - It is only used for the 'esim' method. - - w_factor : {"fraction", "power_n"}, optional - The type of weight function to be used. - - 'fraction' : - similarity = d[k] / n, dissimilarity = 1 - (d[k] - n_objects % 2) / n_objects - - 'power_n' : - similarity = n ** -(n_objects - d[k]), dissimilarity = n ** -(d[k] - n_objects % 2) - - other values : - similarity = dissimilarity = 1 - Default is 'fraction'. - other values : similarity = dissimilarity = 1 - It is only used for the 'esim' method. Default is 'fraction'. - """ - # check if the method is valid - if method not in ["isim", "esim"]: - raise ValueError(f'Method "{method}" is not available please select "isim" or "esim".') - - # check if the similarity index is valid - if sim_index not in _similarity_index_dict: - raise ValueError( - f'Similarity index "{sim_index}" is not available. ' - f"See the documentation for the available similarity indexes." - ) - # for the esim method, check if the w_factor and c_threshold are valid - if method == "esim": - # check if the c_threshold is valid - if c_threshold not in ["dissimilar", None]: - if not isinstance(c_threshold, int): - raise ValueError( - f'Invalid c_threshold. It must be an integer or "dissimilar" or None. ' - f"Given c_threshold = {c_threshold}" - ) - # check if the w_factor is valid - if w_factor != "fraction": - if w_factor.split("_")[0] != "power" or not w_factor.split("_")[-1].isdigit(): - print( - f'Invalid weight factor "{w_factor}" given. Using default value ' - '"similarity = dissimilarity = 1".' - ) - w_factor = False - self.method = method - self.inv_order = inv_order - self.similarity_index = sim_index - self.w_factor = w_factor - self.c_threshold = c_threshold - - def _calculate_counters(self, X: np.ndarray, nsamples: Optional[int] = None) -> dict: - """Calculate 1-similarity, 0-similarity, and dissimilarity counters. - - Arguments - --------- - X : np.ndarray - Array of arrays, each sub-array contains the binary or real valued vector. The values - must be between 0 and 1. If the number of rows ==1, the data is treated as the - columnwise sum of the objects. If the number of rows > 1, the data is treated as the - objects. - nsamples: int - Number of objects, only necessary if the columnwise sum of the objects is provided - instead of the data (num rows== 1). If the data is provided, the number of objects is - calculated as the length of the data. - - Returns - ------- - counters : dict - Dictionary with the weighted and non-weighted counters. - """ - # Check if the data is a np.ndarray of a list - if not isinstance(X, np.ndarray): - raise TypeError("Argument X is not a np.ndarray, please input the right data type!") - # Check if data is a columnwise sum or the objects - if X.ndim == 1: - c_total = X - # If data is a columnwise sum, check if n_objects is provided - if nsamples is None: - raise ValueError("Argument X is the columnwise sum, please specify nsamples") - else: - c_total = np.sum(X, axis=0) - if nsamples is not None and nsamples != len(X): - warnings.warn( - f"Warning, specified number of objects {nsamples} is different from the number" - " of objects in data {len_arr}\n" - "Doing calculations with", - nsamples, - "objects.", - ) - nsamples = len(X) - - # if method is isim, calculate the counters using the instant similarity index - if self.method == "isim": - # calculate number of instances with common on bits (common 1s) for each column - a_array = c_total * (c_total - 1) / 2 - # calculate number of instances with common off bits (common 0s) for each column - off_coincidences = nsamples - c_total - d_array = off_coincidences * (off_coincidences - 1) / 2 - # calculate number of instances with dissimilar bits for each column - dis_array = off_coincidences * c_total - - # calculate total a, d, b + c counters - a = np.sum(np.power(a_array, 1.0 / self.inv_order)) - d = np.sum(np.power(d_array, 1.0 / self.inv_order)) - total_dis = np.sum(np.power(dis_array, 1 / self.inv_order)) - - # calculate total similarity, and total similarity + dissimilarity - total_sim = a + d - p = total_sim + total_dis - - # in the isim method, the counters are not weighted, so the weighted counters are equal - # to the non-weighted counters - w_a = a - w_d = d - total_w_sim = total_sim - total_w_dis = total_dis - w_p = p - - elif self.method == "esim": - # Assign c_threshold - if self.c_threshold is None: - tmp_c_threshold = nsamples % 2 - elif self.c_threshold == "dissimilar": - tmp_c_threshold = math.ceil(nsamples / 2) - elif isinstance(self.c_threshold, int): - if self.c_threshold >= nsamples: - raise ValueError( - "c_threshold cannot be equal or greater than nsamples. \n" - f"c_threshold = {self.c_threshold} nsamples = {nsamples}" - ) - tmp_c_threshold = self.c_threshold - else: - raise ValueError( - "c_threshold must be None, 'dissimilar' or an integer. \n" - f"Given c_threshold = {self.c_threshold}" - ) - - # Calculate a, d, b + c - # Calculate the positions (columns) of common on bits (common 1s) between the objects - a_indices = 2 * c_total - nsamples > tmp_c_threshold - # Calculate the positions (columns) common off bits (common 0s) between the objects - d_indices = nsamples - 2 * c_total > tmp_c_threshold - # Calculate the positions (columns) of dissimilar bits between the objects (b + c) - # the dissimilar bits are the bits that are not common between the objects - dis_indices = np.abs(2 * c_total - nsamples) <= tmp_c_threshold - - # Calculate the number of columns with common on bits (common 1s) between the objects - a = np.sum(np.power(a_indices, 1.0 / self.inv_order)) - # Calculate the number of columns with common off bits (common 0s) between the objects - d = np.sum(np.power(d_indices, 1.0 / self.inv_order)) - # Calculate the number of columns with dissimilar bits between the objects (b + c) - total_dis = np.sum(np.power(dis_indices, 1.0 / self.inv_order)) - - # calculate the weights for each column indexed as with common on bits (common 1s) - a_w_array = self._f_s(2 * c_total[a_indices] - nsamples, nsamples) - # calculate the weights for each column indexed as with common off bits (common 0s) - d_w_array = self._f_s(abs(2 * c_total[d_indices] - nsamples), nsamples) - # calculate the weights for each column indexed as with dissimilar bits - total_w_dis_array = self._f_d(abs(2 * c_total[dis_indices] - nsamples), nsamples) - - # calculate the total weight for each type of counter - w_a = np.sum(np.power(a_w_array, 1.0 / self.inv_order)) - w_d = np.sum(np.power(d_w_array, 1.0 / self.inv_order)) - total_w_dis = np.sum(np.power(total_w_dis_array, 1.0 / self.inv_order)) - - # calculate the counters needed to calculate the similarity indexes - total_sim = a + d - total_w_sim = w_a + w_d - p = total_sim + total_dis - w_p = total_w_sim + total_w_dis - - counters = { - "a": a, - "w_a": w_a, - "d": d, - "w_d": w_d, - "total_sim": total_sim, - "total_w_sim": total_w_sim, - "total_dis": total_dis, - "total_w_dis": total_w_dis, - "p": p, - "w_p": w_p, - } - return counters - - def _f_s(self, d, n) -> float: - """Calculate the similarity weight factor for a given number of similar objects in a set. - - Parameters - ---------- - d : int - Number of similar objects. - n : int - Total number of objects. - - Returns - ------- - w_s : float - Weight factor for the similarity depending on the number of objects that are similar (d) - in a set of (n) objects. - """ - if self.w_factor: - # power_n case - if "power" in self.w_factor: - power = int(self.w_factor.split("_")[-1]) - return power ** -(n - d).astype(float) - # fraction case - elif self.w_factor == "fraction": - return d / n - else: - raise ValueError( - f"w_factor must be 'fraction' or 'power_n'. \n Given w_factor = {self.w_factor}" - ) - # default case, the similarity counters are not weighted - return 1 - - def _f_d(self, d, n) -> float: - """Calculate the dissimilarity weight factor for a given number of similar objects in a set. - - Parameters - ---------- - d : int - Number of similar objects. - n : int - Total number of objects. - - Returns - ------- - w_s : float - Weight factor for the dissimilarity depending on the number of objects that are similar - (d) in a set of (n) objects. - """ - if self.w_factor: - # power_n case - if "power" in self.w_factor: - power = int(self.w_factor.split("_")[-1]) - return power ** -(d - n % 2).astype(float) - # fraction case - elif self.w_factor == "fraction": - return 1 - (d - n % 2) / n - else: - raise ValueError( - f"w_factor must be 'fraction' or 'power_n'. \n Given w_factor = {self.w_factor}" - ) - # default case, the dissimilarity counters are not weighted - return 1 - - def __call__(self, X: np.ndarray, nsamples: int = None) -> float: - """Calculate the similarity index of a set of vectors. - - Parameters - ---------- - X : np.ndarray - Array of arrays, each sub-array contains the binary or real valued vector. The values - must be between 0 and 1. If the number of rows ==1, the data is treated as the - columnwise sum of the objects. If the number of rows > 1, the data is treated as the - objects. - nsamples: int - Number of objects in the data. Is only necessary if the data is a columnwise sum of - the objects. If the data is not the columnwise sum of the objects, the number of objects - is calculated as the length of the data. - Returns - ------- - similarity_index: float - Similarity index of the set of vectors. - """ - # check if arr is a np.ndarray - if not isinstance(X, np.ndarray): - raise TypeError("Input data is not a np.ndarray, please input the right data type") - - # if the data is a columnwise sum of the objects check that n_objects is provided - if X.ndim == 1: - c_total = X - if not nsamples: - raise ValueError("Input data is the columnwise sum, please specify nsamples") - # if the data is not a columnwise sum of the objects, calculate the columnwise sum and the - # number of objects - else: - c_total = np.sum(X, axis=0) - if nsamples is not None and nsamples != len(X): - warnings.warn( - f"Warning, specified number of objects {nsamples} is different from the number" - " of objects in data {len_arr}\n" - "Doing calculations with", - nsamples, - "objects.", - ) - nsamples = X.shape[0] - - # calculate the counters needed to calculate the similarity indexes - counters = self._calculate_counters(X=c_total, nsamples=nsamples) - # calculate the similarity index - similarity_index = _similarity_index_dict[self.similarity_index](counters) - - return similarity_index - - -# Utility functions section -# ------------------------- - -# Functions that calculate the similarity indexes. The functions are named as the similarity -# index they calculate. The _nw suffix indicates that the similarity index is not weighted. -# More information about the similarity indexes can be found in the following paper: - - -def _ac_nw(counters: dict) -> float: - """Calculate the Austin-Colwell (AC) similarity index. - - https://jcheminf.biomedcentral.com/articles/10.1186/s13321-021-00505-3""" - ac_nw = (2 / np.pi) * np.arcsin(np.sqrt(counters["total_w_sim"] / counters["p"])) - return ac_nw - - -def _bub_nw(counters: dict) -> float: - """Calculate the Baroni-Urbani-Buser (BUB) similarity index. - - https://jcheminf.biomedcentral.com/articles/10.1186/s13321-021-00505-3""" - bub_nw = ((counters["w_a"] * counters["w_d"]) ** 0.5 + counters["w_a"]) / ( - (counters["a"] * counters["d"]) ** 0.5 + counters["a"] + counters["total_dis"] - ) - return bub_nw - - -def _ct1_nw(counters: dict) -> float: - """Calculate the Consoni-Todschini 1 (CT1) similarity index. - - https://jcheminf.biomedcentral.com/articles/10.1186/s13321-021-00505-3""" - ct1_nw = (log(1 + counters["w_a"] + counters["w_d"])) / (log(1 + counters["p"])) - return ct1_nw - - -def _ct2_nw(counters: dict) -> float: - """Calculate the Consoni-Todschini 2 (CT2) similarity index. - - https://jcheminf.biomedcentral.com/articles/10.1186/s13321-021-00505-3""" - ct2_nw = (log(1 + counters["w_p"]) - log(1 + counters["total_w_dis"])) / ( - log(1 + counters["p"]) - ) - return ct2_nw - - -def _ct3_nw(counters: dict) -> float: - """Calculate the Consoni-Todschini 3 (CT3) similarity index. - - https://jcheminf.biomedcentral.com/articles/10.1186/s13321-021-00505-3""" - ct3_nw = (log(1 + counters["w_a"])) / (log(1 + counters["p"])) - return ct3_nw - - -def _ct4_nw(counters: dict) -> float: - """Calculate the Consoni-Todschini 4 (CT4) similarity index. - - https://jcheminf.biomedcentral.com/articles/10.1186/s13321-021-00505-3""" - ct4_nw = (log(1 + counters["w_a"])) / (log(1 + counters["a"] + counters["total_dis"])) - return ct4_nw - - -def _fai_nw(counters: dict) -> float: - """Calculate the Faith (Fai) similarity index. - - https://jcheminf.biomedcentral.com/articles/10.1186/s13321-021-00505-3""" - fai_nw = (counters["w_a"] + 0.5 * counters["w_d"]) / (counters["p"]) - return fai_nw - - -def _gle_nw(counters: dict) -> float: - """Calculate the Gleason (Gle) similarity index. - - https://jcheminf.biomedcentral.com/articles/10.1186/s13321-021-00505-3""" - gle_nw = (2 * counters["w_a"]) / (2 * counters["a"] + counters["total_dis"]) - return gle_nw - - -def _ja_nw(counters: dict) -> float: - """Calculate the Jaccard (Ja) similarity index. - - https://jcheminf.biomedcentral.com/articles/10.1186/s13321-021-00505-3""" - ja_nw = (3 * counters["w_a"]) / (3 * counters["a"] + counters["total_dis"]) - return ja_nw - - -def _ja0_nw(counters: dict) -> float: - """Calculate the Jaccard 0-variant (Ja0) similarity index. - - https://jcheminf.biomedcentral.com/articles/10.1186/s13321-021-00505-3""" - ja0_nw = (3 * counters["total_w_sim"]) / (3 * counters["total_sim"] + counters["total_dis"]) - return ja0_nw - - -def _jt_nw(counters: dict) -> float: - """Calculate the Jaccard-Tanimoto (JT) similarity index. - - https://jcheminf.biomedcentral.com/articles/10.1186/s13321-021-00505-3""" - jt_nw = (counters["w_a"]) / (counters["a"] + counters["total_dis"]) - return jt_nw - - -def _rt_nw(counters: dict) -> float: - """Calculate the Rogers-Tanimoto (RT) similarity index. - - https://jcheminf.biomedcentral.com/articles/10.1186/s13321-021-00505-3""" - rt_nw = (counters["total_w_sim"]) / (counters["p"] + counters["total_dis"]) - return rt_nw - - -def _rr_nw(counters: dict) -> float: - """Calculate the Russel-Rao (RR) similarity index. - - https://jcheminf.biomedcentral.com/articles/10.1186/s13321-021-00505-3""" - rr_nw = (counters["w_a"]) / (counters["p"]) - return rr_nw - - -def _sm_nw(counters: dict) -> float: - """Calculate the Sokal-Michener (SM) similarity index. - - https://jcheminf.biomedcentral.com/articles/10.1186/s13321-021-00505-3""" - sm_nw = (counters["total_w_sim"]) / (counters["p"]) - return sm_nw - - -def _ss1_nw(counters: dict) -> float: - """Calculate the Sokal-Sneath 1 (SS1) similarity index. - - https://jcheminf.biomedcentral.com/articles/10.1186/s13321-021-00505-3""" - ss1_nw = (counters["w_a"]) / (counters["a"] + 2 * counters["total_dis"]) - return ss1_nw - - -def _ss2_nw(counters: dict) -> float: - """Calculate the Sokal-Sneath 2 (SS2) similarity index. - - https://jcheminf.biomedcentral.com/articles/10.1186/s13321-021-00505-3""" - ss2_nw = (2 * counters["total_w_sim"]) / (counters["p"] + counters["total_sim"]) - return ss2_nw - - -# Dictionary with the similarity indexes functions as values and the keys are the abbreviations -_similarity_index_dict = { - "AC": _ac_nw, - "BUB": _bub_nw, - "CT1": _ct1_nw, - "CT2": _ct2_nw, - "CT3": _ct3_nw, - "CT4": _ct4_nw, - "Fai": _fai_nw, - "Gle": _gle_nw, - "Ja": _ja_nw, - "Ja0": _ja0_nw, - "JT": _jt_nw, - "RT": _rt_nw, - "RR": _rr_nw, - "SM": _sm_nw, - "SS1": _ss1_nw, - "SS2": _ss2_nw, -} +# -*- coding: utf-8 -*- +# +# The Selector is a Python library of algorithms for selecting diverse +# subsets of data for machine-learning. +# +# Copyright (C) 2022-2024 The QC-Devs Community +# +# This file is part of Selector. +# +# Selector is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 +# of the License, or (at your option) any later version. +# +# Selector is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see +# +# -- +"""Module for Similarity-Based Selection Methods. + +This module contains the classes and functions for the similarity-based selection methods. To select +a diverse subset of molecules the similarity-based selection methods select the molecules such that +the similarity between the molecules in the subset is minimized. The similarity of a set of +molecules is calculated using an n-array similarity index. These indexes compare n molecules at a +time and return a value between 0 and 1, where 0 means that all the molecules in the set are +completely different and 1 means that the molecules are identical. + +The ideas behind the similarity-based selection methods are described in the following papers: + (esim) + https://jcheminf.biomedcentral.com/articles/10.1186/s13321-021-00505-3 + https://jcheminf.biomedcentral.com/articles/10.1186/s13321-021-00504-4 + (isim) + TODO: Add paper + +""" + +import math +import random +from math import log +from typing import List, Optional, Union +import warnings + +import numpy as np + +from selector.methods.base import SelectionBase + +__all__ = [ + "NSimilarity", + "SimilarityIndex", +] + + +class NSimilarity(SelectionBase): + r"""Select samples of vectors using n-ary similarity indexes between vectors. + + The algorithms in this class select a diverse subset of vectors such that the similarity + between the vectors in the subset is minimized. The similarity of a set of vectors is + calculated using an n-ary similarity index. These indexes compare n vectors (e.g. molecular + fingerprints) at a time and return a value between 0 and 1, where 0 means that all the vectors + in the set are completely different and 1 means that the vectors are identical. + + The algorithm starts by selecting a starting reference data point. Then, the next data point is + selected such as the similarity value of the group of selected data points is minimized. The + process is repeated until the desired number of data points is selected. + + Notes + ----- + The ideas behind the similarity-based selection methods are described in the following papers: + + """ + + def __init__( + self, + method: str = "isim", + inv_order: int = 1, + similarity_index: str = "RR", + w_factor: str = "fraction", + c_threshold: Union[None, str, int] = None, + preprocess_data: bool = True, + ): + """Initialize class. + + Parameters + ---------- + method: {"isim", "esim"} + Method used for calculating the similarity indices. The methods are: + - "isim": Instant Similarity + The instant similarity index calculates the average similarity of a set of + objects without the need to calculate the similarity of all the possible pairs. + This method is easier to use than the ``esim`` (extended similarity index) as it + does not require the use of weight factors or coincidence thresholds. + - "esim": Extended Similarity + The extended similarity index calculates the similarity of a set of objects + without the need to calculate the similarity of all the possible pairs. This + method requires the use of weight factors and coincidence thresholds. + inv_order: int + Integer indicating the 1/inv_order power used to approximate the average of the + similarity values elevated to 1/inv_order. + similarity_index: str + Key with the abbreviation of the similarity index that will be used to perform the + selection. + Possible values are: + AC: Austin-Colwell + BUB: Baroni-Urbani-Buser + CTn: Consoni-Todschini + Fai: Faith + Gle: Gleason + Ja: Jaccard + Ja0: Jaccard 0-variant + JT: Jaccard-Tanimoto + RT: Rogers-Tanimoto + RR: Russel-Rao + SM: Sokal-Michener + SSn: Sokal-Sneath n + w_factor: {"fraction", "power_n"} + Type of weight function that will be used for calculating the counters. + 'fraction' : similarity = d[k]/n + dissimilarity = 1 - (d[k] - n_objects % 2)/n_objects + 'power_n' : similarity = n**-(n_objects - d[k]) + dissimilarity = n**-(d[k] - n_objects % 2) + other values : similarity = dissimilarity = 1 + Only used for the 'esim' method. Default is 'fraction'. + c_threshold: {None, 'dissimilar', int} + Coincidence threshold used for calculating the similarity counters. A column of the + elements is considered to be a coincidence among the elements if the number of elements + that have the same value in that position is greater than the coincidence threshold. + None : Default, c_threshold = n_objects % 2 + 'dissimilar' : c_threshold = ceil(n_objects / 2) + int : Integer number < n_objects + Only used for the 'esim' method. Default is None. + preprocess_data: bool + Every data element must be between 0 and 1 for the similarity indexes to work. If + preprocess_data is True, the data is scaled between 0 and 1 using a strategy that is + compatible with the similarity indexes. If preprocess_data is False, the data is not + scaled and it is assumed that the data is already between 0 and 1. + + """ + # check if the method is valid + if method not in ["isim", "esim"]: + raise ValueError(f'Method "{method}" is not available please select "isim" or "esim".') + # check if the similarity index is valid + if similarity_index not in _similarity_index_dict: + raise ValueError( + f'Similarity index "{similarity_index}" is not available. ' + f"See the documentation for the available similarity indexes." + ) + # for the esim method, check if the w_factor is valid + if method == "esim": + # check if the w_factor and c_threshold are valid + if w_factor != "fraction": + if w_factor.split("_")[0] != "power" or not w_factor.split("_")[-1].isdigit(): + print( + f'Invalid weight factor "{w_factor}" given. Using default value ' + '"similarity = dissimilarity = 1".' + ) + w_factor = False + # check if the c_threshold is valid + if c_threshold not in ["dissimilar", None]: + if not isinstance(c_threshold, int): + raise ValueError( + f'Invalid c_threshold. It must be an integer or "dissimilar" or None. ' + f"Given c_threshold = {c_threshold}" + ) + + self.method = method + self.inv_order = inv_order + self.similarity_index = similarity_index + self.w_factor = w_factor + self.c_threshold = c_threshold + self.preprocess_data = preprocess_data + # create an instance of the SimilarityIndex class. It is used to calculate the similarity + # index of the sets of selected objects. + self.si = SimilarityIndex( + method=self.method, + inv_order=self.inv_order, + sim_index=self.similarity_index, + c_threshold=self.c_threshold, + w_factor=self.w_factor, + ) + + def _scale_data(self, X: np.ndarray): + r"""Scales the data between so it can be used with the similarity indexes. + + First each data point is normalized to be between 0 and 1. + + .. math:: + x_{ij} = \frac{x_{ij} - min(x_j)}{max(x_j) - min(x_j)} + + Then, the average of each column is calculated. Finally, each element of the final working + array will be defined as + + .. math:: + w_{ij} = 1 - | x_{ij} - a_j | + + where :math:`x_{ij}` is the element of the normalized array, + and :math:`a_j` is the average of the j-th + column of the normalized array. + + Parameters + ---------- + X: np.ndarray + Array of features (columns) for each sample (rows). + """ + min_value = np.min(X) + max_value = np.max(X) + # normalize the data to be between 0 and 1 for working with the similarity indexes + normalized_data = (X - min_value) / (max_value - min_value) + # calculate the average of the columns + col_average = np.average(normalized_data, axis=0) + + # each element of the final working array will be defined as w_ij = 1 - | x_ij - a_j | + # where x_ij is the element of the normalized array, and a_j is the average of the j-th + # column of the normalized array. + data = 1 - np.abs(normalized_data - col_average) + return data + + def _get_new_index( + self, + X: np.ndarray, + selected_condensed: np.ndarray, + num_selected: int, + select_from: np.ndarray, + ) -> int: + r"""Select a new diverse sample from the data. + + The function selects a new sample such that the similarity of the new set of selected + samples is minimized. + + Parameters + ---------- + X: np.ndarray + Array of features (columns) for each sample (rows). + selected_condensed: np.ndarray + Columnwise sum of all the samples selected so far. + num_selected: int + Number of samples selected so far. + select_from: np.ndarray + Array of integers representing the indices of the samples that have not been selected + yet. + + Returns + ------- + selected: int + Index of the new selected sample. + + """ + # check if the data was previously scaled + if np.max(X) > 1 or np.min(X) < 0: + raise ValueError( + "The data was not scaled between 0 and 1. " + "Use the _scale_data function to scale the data." + ) + + # Number of total vectors used to calculate th similarity. It is the number of samples + # selected so far + 1, because the similarities are computed for the sets of samples after + # a new selection is made. + n_total = num_selected + 1 + + # min value that is guaranteed to be higher than all the comparisons, this value should be a + # warranty that a exist a set of samples with similarity lower than min_value. The max + # possible similarity value for set of samples is 1.00. + min_value = 1.01 + + # placeholder index, initiating variable with a number outside the possible index values + index = X.shape[0] + 1 + + # for all indices that have not been selected + for sample_idx in select_from: + # column sum + c_total = selected_condensed + X[sample_idx] + + # calculating similarity + sim_index = self.si(c_total, nsamples=n_total) + + # if the sim of the set is less than the similarity of the previous diverse set, + # update min_value and index + if sim_index < min_value: + index = sample_idx + min_value = sim_index + + return index + + def calculate_medoid(self, X: np.ndarray, c_total=None) -> int: + """Calculate the medoid of a set of real-valued vectors or binary objects. + + Parameters + ---------- + X: np.array + np.array of all the real-valued vectors or binary objects. + c_total: + np.array with the columnwise sums of the data, not necessary to provide. + """ + # Check if the data is a np.ndarray of a list + if not isinstance(X, np.ndarray): + raise TypeError("Input data is not a np.ndarray, please input the right data type") + # Check if the data is one dimensional + if X.ndim != 2: + raise ValueError( + "Data must be a two dimensional np.ndarray for calculating the medoid." + ) + # Check if the data has at least 3 rows + if X.shape[0] < 3: + raise ValueError("Input data must have at least 3 rows to calculate the medoid.") + + # check if c_total is provided and if not, calculate it + if c_total is None: + c_total = np.sum(X, axis=0) + # if c_total is provided, check if it has the same number of columns as the data + elif c_total is not None and len(X[0]) != len(c_total): + raise ValueError("Dimensions of objects and columnwise sum differ") + + # get the total number of objects + nsamples = X.shape[0] + + # Initialize the selected index with a number outside the possible index values + index = nsamples + 1 + + # minimum similarity value that is guaranteed to be higher than all the comparisons, this + # value should be a warranty that a exist a sample with similarity lower than min_sim. The + # max possible similarity value for set of samples is 1.00. + min_sim = 1.01 + + # For each sample in the set, calculate the column-wise sum of the data without the sample + comp_sums = c_total - X + + # The medoid is calculated using an instance of the SimilarityIndex class with the same + # parameters as the current class, but with the inv_order = 1 + si = SimilarityIndex( + method=self.method, + inv_order=1, + sim_index=self.similarity_index, + c_threshold=self.c_threshold, + w_factor=self.w_factor, + ) + + # for each sample calculate the similarity index of the complete set without the sample + for idx, row in enumerate(comp_sums): + # calculate the similarity index of the set of objects without the current object + sim_index = si(row, nsamples=nsamples - 1) + # if the similarity is lower than the previous minimum similarity, update the minimum + # similarity and the index + if sim_index < min_sim: + min_sim, index = sim_index, idx + # the index of the object that increases more the similarity of the set when added is + # returned (the medoid) + return index + + def calculate_outlier(self, X: np.ndarray = None, c_total=None) -> int: + r"""Calculate the outlier of a set of real-valued vectors or binary objects. + + Calculates the outlier of a set of real-valued vectors or binary objects. Using the + similarity index provided in the class initialization. + + Parameters + ---------- + X: np.array + np.array of all the real-valued vectors or binary objects. + c_total: np.array, optional + np.array with the column-wise sums of the data. + """ + # Check if the data is a np.ndarray of a list + if not isinstance(X, np.ndarray): + raise TypeError("Input data is not a np.ndarray, please input the right data type") + # Check if the data is one dimensional + if X.ndim != 2: + raise ValueError( + "Data must be a two dimensional np.ndarray for calculating the outlier." + ) + # Check if the data has at least 3 rows + if X.shape[0] < 3: + raise ValueError("Input data must have at least 3 rows to calculate the outlier.") + + # check if c_total is provided and if not, calculate it + if c_total is None: + c_total = np.sum(X, axis=0) + # if c_total is provided, check if it has the same number of columns as the data + elif c_total is not None and len(X[0]) != len(c_total): + raise ValueError("Dimensions of objects and columnwise sum differ") + + nsamples = X.shape[0] + + # Initialize the selected index with a number outside the possible index values + index = nsamples + 1 + + # maximum similarity value that is guaranteed to be lower than all the comparisons, this + # value should be a warranty that a exist a sample with similarity lower than min_sim. The + # min possible similarity value for set of samples is 0.00. + max_sim = -0.01 + + # For each sample in the set, calculate the columnwise sum of the data without the sample + comp_sums = c_total - X + + # The outlier is calculated using an instance of the SimilarityIndex class with the same + # parameters as the current class, but with the inv_order = 1 + + # for each sample calculate the similarity index of the complete set without the sample + for idx, obj in enumerate(comp_sums): + # calculate the similarity index of the set of objects without the current object + sim_index = self.si(X=obj, nsamples=nsamples - 1) + # if the similarity is bigger than the previous minimum similarity, update the minimum + # similarity and the index + if sim_index > max_sim: + max_sim, index = sim_index, idx + # the index of the object that decreases more the similarity of the set when added is + # returned (the outlier) + return index + + def select_from_cluster( + self, + X: np.ndarray, + size: int, + labels: Optional[np.ndarray] = None, + start: Union[str, List[int]] = "medoid", + ) -> List[int]: + r"""Algorithm of nary similarity selection for selecting points from cluster. + + Parameters + ---------- + X: np.ndarray + Array of features (columns) for each sample (rows). + size: int + Number of sample points to select (i.e. size of the subset). + labels: np.ndarray, optional + Array of integers or strings representing the points ids of the data that belong to the + current cluster. If `None`, all the samples in the data are treated as one cluster. + start: str or list + srt: key on what is used to start the selection {'medoid', 'random', 'outlier'}. + list: indices of points that are included in the selection since the beginning. + + Returns + ------- + selected: list + Indices of the selected sample points. + + """ + # check for valid start value and raise an error if it is not + if start not in ["medoid", "random", "outlier"]: + if not isinstance(start, list) or not all(isinstance(i, int) for i in start): + raise ValueError( + "Select a correct starting point: medoid, random, outlier or a list of indices." + ) + # check if cluster_ids are provided + if labels is not None: + # extract the data corresponding to the cluster_ids + X = np.take(X, labels, axis=0) + + # total number of objects in the current cluster + nsamples = X.shape[0] + # ids of the data points in the current cluster (0, 1, 2, ..., samples-1) + data_ids = np.array(range(nsamples)) + + # check if the number of selected objects is less than the total number of objects + if size > nsamples: + raise ValueError( + f"Number of samples is less than the requested sample size: {nsamples} < {size}." + ) + + # The data is marked to be preprocessed scale the data between 0 and 1 using a strategy + # that is compatible with the similarity indexes + if self.preprocess_data: + X = self._scale_data(X) + else: + # check if the data is between 0 and 1 and raise an error if it is not + if np.max(X) > 1 or np.min(X) < 0: + raise ValueError( + "The data was not scaled between 0 and 1. " + "Use the _scale_data function to scale the data." + ) + + # select the index (of the working data) corresponding to the medoid of the data using the + # similarity index + if start == "medoid": + seed = self.calculate_medoid(X) + selected = [seed] + # select the index (of the working data) corresponding to a random data point + elif start == "random": + seed = random.randint(0, nsamples - 1) + selected = [seed] + # select the index (of the working data) corresponding to the outlier of the data using the + # similarity index + elif start == "outlier": + seed = self.calculate_outlier(X) + selected = [seed] + # if a list of cluster_ids is provided, select the data_ids corresponding indices + elif isinstance(start, list): + if labels is not None: + # check if all starting indices are in this cluster + if not all(label in labels for label in start): + raise ValueError( + "Some of the provided initial indexes are not in the cluster data." + ) + # select the indices of the data_ids that correspond to the provided starting points + # provided from cluster_ids + selected = [i for i, j in enumerate(labels) if j in start] + else: + # check if all starting indices are in the data + if not all(label in data_ids for label in start): + raise ValueError("Some of the provided initial indexes are not in the data.") + # select the indices of the data_ids that correspond to the provided starting points + selected = start[:] + # Number of initial objects + num_selected = len(selected) + + # get selected samples form the working data array + selected_objects = np.take(X, selected, axis=0) + # Calculate the columnwise sum of the selected samples + selected_condensed = np.sum(selected_objects, axis=0) + + # until the desired number of objects is selected a new object is selected. + while num_selected < size: + # indices from which to select the new data points + select_from = np.delete(data_ids, selected) + + # Select new index. The new object is selected such that from all possible objects the + # similarity of the set of (selected_objects + new_object) is a minimum. + new_index = self._get_new_index(X, selected_condensed, num_selected, select_from) + + # updating column sum vector + selected_condensed += X[new_index] + + # updating selected indices + selected.append(new_index) + num_selected += 1 + + return selected + + +class SimilarityIndex: + r"""Calculate the n-ary similarity index of a set of vectors. + + This class provides methods for calculating the similarity index of a set of vectors represented + as a matrix. Each vector is a row in the matrix, and each column represents a feature of the + vector. The features in the vectors must be binary or real numbers between 0 and 1. + """ + + def __init__( + self, + method: str = "isim", + inv_order: int = 1, + sim_index: str = "RR", + c_threshold: Union[None, str, int] = None, + w_factor: str = "fraction", + ): + """Initialize the class. + + Parameters + ---------- + method : {"isim", "esim"}, optional + Method used for calculating the similarity indexes. The methods are: + - "isim": Instant Similarity + The instant similarity index calculates the average similarity of a set of + objects without the need to calculate the similarity of all the possible pairs. + This method is easier to use than the ``esim`` (extended similarity index) as it + does not require the use of weight factors or coincidence thresholds. + - "esim": Extended Similarity + The extended similarity index calculates the similarity of a set of objects + without the need to calculate the similarity of all the possible pairs. This + method requires the use of weight factors and coincidence thresholds. + Default is "isim". + + inv_order : int, optional + Integer indicating the 1/inv_order power used to approximate the average of the + similarity values elevated to 1/inv_order. This is not used for calculating the + medoid or the outlier. Default is 1. + + sim_index : str, optional + The key with the abbreviation of the similarity index to be used for calculations. + Possible values are: + - 'AC': Austin-Colwell + - 'BUB': Baroni-Urbani-Buser + - 'CTn': Consoni-Todschini n + - 'Fai': Faith + - 'Gle': Gleason + - 'Ja': Jaccard + - 'Ja0': Jaccard 0-variant + - 'JT': Jaccard-Tanimoto + - 'RT': Rogers-Tanimoto + - 'RR': Russel-Rao + - 'SM': Sokal-Michener + - 'SSn': Sokal-Sneath n + Default is 'RR'. + + c_threshold : {None, 'dissimilar', int}, optional + The coincidence threshold used for calculating similarity counters. A position in the + elements is considered a coincidence (coincides among all the elements considered) if + the number of elements that have the same value in that position is greater than the + coincidence threshold. + - None : Default, c_threshold = n_objects % 2 + - 'dissimilar' : c_threshold = ceil(n_objects / 2) + - int : Integer number < n_objects + It is only used for the 'esim' method. + + w_factor : {"fraction", "power_n"}, optional + The type of weight function to be used. + - 'fraction' : + similarity = d[k] / n, dissimilarity = 1 - (d[k] - n_objects % 2) / n_objects + - 'power_n' : + similarity = n ** -(n_objects - d[k]), dissimilarity = n ** -(d[k] - n_objects % 2) + - other values : + similarity = dissimilarity = 1 + Default is 'fraction'. + other values : similarity = dissimilarity = 1 + It is only used for the 'esim' method. Default is 'fraction'. + """ + # check if the method is valid + if method not in ["isim", "esim"]: + raise ValueError(f'Method "{method}" is not available please select "isim" or "esim".') + + # check if the similarity index is valid + if sim_index not in _similarity_index_dict: + raise ValueError( + f'Similarity index "{sim_index}" is not available. ' + f"See the documentation for the available similarity indexes." + ) + # for the esim method, check if the w_factor and c_threshold are valid + if method == "esim": + # check if the c_threshold is valid + if c_threshold not in ["dissimilar", None]: + if not isinstance(c_threshold, int): + raise ValueError( + f'Invalid c_threshold. It must be an integer or "dissimilar" or None. ' + f"Given c_threshold = {c_threshold}" + ) + # check if the w_factor is valid + if w_factor != "fraction": + if w_factor.split("_")[0] != "power" or not w_factor.split("_")[-1].isdigit(): + print( + f'Invalid weight factor "{w_factor}" given. Using default value ' + '"similarity = dissimilarity = 1".' + ) + w_factor = False + self.method = method + self.inv_order = inv_order + self.similarity_index = sim_index + self.w_factor = w_factor + self.c_threshold = c_threshold + + def _calculate_counters(self, X: np.ndarray, nsamples: Optional[int] = None) -> dict: + """Calculate 1-similarity, 0-similarity, and dissimilarity counters. + + Arguments + --------- + X : np.ndarray + Array of arrays, each sub-array contains the binary or real valued vector. The values + must be between 0 and 1. If the number of rows ==1, the data is treated as the + columnwise sum of the objects. If the number of rows > 1, the data is treated as the + objects. + nsamples: int + Number of objects, only necessary if the columnwise sum of the objects is provided + instead of the data (num rows== 1). If the data is provided, the number of objects is + calculated as the length of the data. + + Returns + ------- + counters : dict + Dictionary with the weighted and non-weighted counters. + """ + # Check if the data is a np.ndarray of a list + if not isinstance(X, np.ndarray): + raise TypeError("Argument X is not a np.ndarray, please input the right data type!") + # Check if data is a columnwise sum or the objects + if X.ndim == 1: + c_total = X + # If data is a columnwise sum, check if n_objects is provided + if nsamples is None: + raise ValueError("Argument X is the columnwise sum, please specify nsamples") + else: + c_total = np.sum(X, axis=0) + if nsamples is not None and nsamples != len(X): + warnings.warn( + f"Warning, specified number of objects {nsamples} is different from the number" + " of objects in data {len_arr}\n" + "Doing calculations with", + nsamples, + "objects.", + ) + nsamples = len(X) + + # if method is isim, calculate the counters using the instant similarity index + if self.method == "isim": + # calculate number of instances with common on bits (common 1s) for each column + a_array = c_total * (c_total - 1) / 2 + # calculate number of instances with common off bits (common 0s) for each column + off_coincidences = nsamples - c_total + d_array = off_coincidences * (off_coincidences - 1) / 2 + # calculate number of instances with dissimilar bits for each column + dis_array = off_coincidences * c_total + + # calculate total a, d, b + c counters + a = np.sum(np.power(a_array, 1.0 / self.inv_order)) + d = np.sum(np.power(d_array, 1.0 / self.inv_order)) + total_dis = np.sum(np.power(dis_array, 1 / self.inv_order)) + + # calculate total similarity, and total similarity + dissimilarity + total_sim = a + d + p = total_sim + total_dis + + # in the isim method, the counters are not weighted, so the weighted counters are equal + # to the non-weighted counters + w_a = a + w_d = d + total_w_sim = total_sim + total_w_dis = total_dis + w_p = p + + elif self.method == "esim": + # Assign c_threshold + if self.c_threshold is None: + tmp_c_threshold = nsamples % 2 + elif self.c_threshold == "dissimilar": + tmp_c_threshold = math.ceil(nsamples / 2) + elif isinstance(self.c_threshold, int): + if self.c_threshold >= nsamples: + raise ValueError( + "c_threshold cannot be equal or greater than nsamples. \n" + f"c_threshold = {self.c_threshold} nsamples = {nsamples}" + ) + tmp_c_threshold = self.c_threshold + else: + raise ValueError( + "c_threshold must be None, 'dissimilar' or an integer. \n" + f"Given c_threshold = {self.c_threshold}" + ) + + # Calculate a, d, b + c + # Calculate the positions (columns) of common on bits (common 1s) between the objects + a_indices = 2 * c_total - nsamples > tmp_c_threshold + # Calculate the positions (columns) common off bits (common 0s) between the objects + d_indices = nsamples - 2 * c_total > tmp_c_threshold + # Calculate the positions (columns) of dissimilar bits between the objects (b + c) + # the dissimilar bits are the bits that are not common between the objects + dis_indices = np.abs(2 * c_total - nsamples) <= tmp_c_threshold + + # Calculate the number of columns with common on bits (common 1s) between the objects + a = np.sum(np.power(a_indices, 1.0 / self.inv_order)) + # Calculate the number of columns with common off bits (common 0s) between the objects + d = np.sum(np.power(d_indices, 1.0 / self.inv_order)) + # Calculate the number of columns with dissimilar bits between the objects (b + c) + total_dis = np.sum(np.power(dis_indices, 1.0 / self.inv_order)) + + # calculate the weights for each column indexed as with common on bits (common 1s) + a_w_array = self._f_s(2 * c_total[a_indices] - nsamples, nsamples) + # calculate the weights for each column indexed as with common off bits (common 0s) + d_w_array = self._f_s(abs(2 * c_total[d_indices] - nsamples), nsamples) + # calculate the weights for each column indexed as with dissimilar bits + total_w_dis_array = self._f_d(abs(2 * c_total[dis_indices] - nsamples), nsamples) + + # calculate the total weight for each type of counter + w_a = np.sum(np.power(a_w_array, 1.0 / self.inv_order)) + w_d = np.sum(np.power(d_w_array, 1.0 / self.inv_order)) + total_w_dis = np.sum(np.power(total_w_dis_array, 1.0 / self.inv_order)) + + # calculate the counters needed to calculate the similarity indexes + total_sim = a + d + total_w_sim = w_a + w_d + p = total_sim + total_dis + w_p = total_w_sim + total_w_dis + + counters = { + "a": a, + "w_a": w_a, + "d": d, + "w_d": w_d, + "total_sim": total_sim, + "total_w_sim": total_w_sim, + "total_dis": total_dis, + "total_w_dis": total_w_dis, + "p": p, + "w_p": w_p, + } + return counters + + def _f_s(self, d, n) -> float: + """Calculate the similarity weight factor for a given number of similar objects in a set. + + Parameters + ---------- + d : int + Number of similar objects. + n : int + Total number of objects. + + Returns + ------- + w_s : float + Weight factor for the similarity depending on the number of objects that are similar (d) + in a set of (n) objects. + """ + if self.w_factor: + # power_n case + if "power" in self.w_factor: + power = int(self.w_factor.split("_")[-1]) + return power ** -(n - d).astype(float) + # fraction case + elif self.w_factor == "fraction": + return d / n + else: + raise ValueError( + f"w_factor must be 'fraction' or 'power_n'. \n Given w_factor = {self.w_factor}" + ) + # default case, the similarity counters are not weighted + return 1 + + def _f_d(self, d, n) -> float: + """Calculate the dissimilarity weight factor for a given number of similar objects in a set. + + Parameters + ---------- + d : int + Number of similar objects. + n : int + Total number of objects. + + Returns + ------- + w_s : float + Weight factor for the dissimilarity depending on the number of objects that are similar + (d) in a set of (n) objects. + """ + if self.w_factor: + # power_n case + if "power" in self.w_factor: + power = int(self.w_factor.split("_")[-1]) + return power ** -(d - n % 2).astype(float) + # fraction case + elif self.w_factor == "fraction": + return 1 - (d - n % 2) / n + else: + raise ValueError( + f"w_factor must be 'fraction' or 'power_n'. \n Given w_factor = {self.w_factor}" + ) + # default case, the dissimilarity counters are not weighted + return 1 + + def __call__(self, X: np.ndarray, nsamples: int = None) -> float: + """Calculate the similarity index of a set of vectors. + + Parameters + ---------- + X : np.ndarray + Array of arrays, each sub-array contains the binary or real valued vector. The values + must be between 0 and 1. If the number of rows ==1, the data is treated as the + columnwise sum of the objects. If the number of rows > 1, the data is treated as the + objects. + nsamples: int + Number of objects in the data. Is only necessary if the data is a columnwise sum of + the objects. If the data is not the columnwise sum of the objects, the number of objects + is calculated as the length of the data. + Returns + ------- + similarity_index: float + Similarity index of the set of vectors. + """ + # check if arr is a np.ndarray + if not isinstance(X, np.ndarray): + raise TypeError("Input data is not a np.ndarray, please input the right data type") + + # if the data is a columnwise sum of the objects check that n_objects is provided + if X.ndim == 1: + c_total = X + if not nsamples: + raise ValueError("Input data is the columnwise sum, please specify nsamples") + # if the data is not a columnwise sum of the objects, calculate the columnwise sum and the + # number of objects + else: + c_total = np.sum(X, axis=0) + if nsamples is not None and nsamples != len(X): + warnings.warn( + f"Warning, specified number of objects {nsamples} is different from the number" + " of objects in data {len_arr}\n" + "Doing calculations with", + nsamples, + "objects.", + ) + nsamples = X.shape[0] + + # calculate the counters needed to calculate the similarity indexes + counters = self._calculate_counters(X=c_total, nsamples=nsamples) + # calculate the similarity index + similarity_index = _similarity_index_dict[self.similarity_index](counters) + + return similarity_index + + +# Utility functions section +# ------------------------- + +# Functions that calculate the similarity indexes. The functions are named as the similarity +# index they calculate. The _nw suffix indicates that the similarity index is not weighted. +# More information about the similarity indexes can be found in the following paper: + + +def _ac_nw(counters: dict) -> float: + """Calculate the Austin-Colwell (AC) similarity index. + + https://jcheminf.biomedcentral.com/articles/10.1186/s13321-021-00505-3""" + ac_nw = (2 / np.pi) * np.arcsin(np.sqrt(counters["total_w_sim"] / counters["p"])) + return ac_nw + + +def _bub_nw(counters: dict) -> float: + """Calculate the Baroni-Urbani-Buser (BUB) similarity index. + + https://jcheminf.biomedcentral.com/articles/10.1186/s13321-021-00505-3""" + bub_nw = ((counters["w_a"] * counters["w_d"]) ** 0.5 + counters["w_a"]) / ( + (counters["a"] * counters["d"]) ** 0.5 + counters["a"] + counters["total_dis"] + ) + return bub_nw + + +def _ct1_nw(counters: dict) -> float: + """Calculate the Consoni-Todschini 1 (CT1) similarity index. + + https://jcheminf.biomedcentral.com/articles/10.1186/s13321-021-00505-3""" + ct1_nw = (log(1 + counters["w_a"] + counters["w_d"])) / (log(1 + counters["p"])) + return ct1_nw + + +def _ct2_nw(counters: dict) -> float: + """Calculate the Consoni-Todschini 2 (CT2) similarity index. + + https://jcheminf.biomedcentral.com/articles/10.1186/s13321-021-00505-3""" + ct2_nw = (log(1 + counters["w_p"]) - log(1 + counters["total_w_dis"])) / ( + log(1 + counters["p"]) + ) + return ct2_nw + + +def _ct3_nw(counters: dict) -> float: + """Calculate the Consoni-Todschini 3 (CT3) similarity index. + + https://jcheminf.biomedcentral.com/articles/10.1186/s13321-021-00505-3""" + ct3_nw = (log(1 + counters["w_a"])) / (log(1 + counters["p"])) + return ct3_nw + + +def _ct4_nw(counters: dict) -> float: + """Calculate the Consoni-Todschini 4 (CT4) similarity index. + + https://jcheminf.biomedcentral.com/articles/10.1186/s13321-021-00505-3""" + ct4_nw = (log(1 + counters["w_a"])) / (log(1 + counters["a"] + counters["total_dis"])) + return ct4_nw + + +def _fai_nw(counters: dict) -> float: + """Calculate the Faith (Fai) similarity index. + + https://jcheminf.biomedcentral.com/articles/10.1186/s13321-021-00505-3""" + fai_nw = (counters["w_a"] + 0.5 * counters["w_d"]) / (counters["p"]) + return fai_nw + + +def _gle_nw(counters: dict) -> float: + """Calculate the Gleason (Gle) similarity index. + + https://jcheminf.biomedcentral.com/articles/10.1186/s13321-021-00505-3""" + gle_nw = (2 * counters["w_a"]) / (2 * counters["a"] + counters["total_dis"]) + return gle_nw + + +def _ja_nw(counters: dict) -> float: + """Calculate the Jaccard (Ja) similarity index. + + https://jcheminf.biomedcentral.com/articles/10.1186/s13321-021-00505-3""" + ja_nw = (3 * counters["w_a"]) / (3 * counters["a"] + counters["total_dis"]) + return ja_nw + + +def _ja0_nw(counters: dict) -> float: + """Calculate the Jaccard 0-variant (Ja0) similarity index. + + https://jcheminf.biomedcentral.com/articles/10.1186/s13321-021-00505-3""" + ja0_nw = (3 * counters["total_w_sim"]) / (3 * counters["total_sim"] + counters["total_dis"]) + return ja0_nw + + +def _jt_nw(counters: dict) -> float: + """Calculate the Jaccard-Tanimoto (JT) similarity index. + + https://jcheminf.biomedcentral.com/articles/10.1186/s13321-021-00505-3""" + jt_nw = (counters["w_a"]) / (counters["a"] + counters["total_dis"]) + return jt_nw + + +def _rt_nw(counters: dict) -> float: + """Calculate the Rogers-Tanimoto (RT) similarity index. + + https://jcheminf.biomedcentral.com/articles/10.1186/s13321-021-00505-3""" + rt_nw = (counters["total_w_sim"]) / (counters["p"] + counters["total_dis"]) + return rt_nw + + +def _rr_nw(counters: dict) -> float: + """Calculate the Russel-Rao (RR) similarity index. + + https://jcheminf.biomedcentral.com/articles/10.1186/s13321-021-00505-3""" + rr_nw = (counters["w_a"]) / (counters["p"]) + return rr_nw + + +def _sm_nw(counters: dict) -> float: + """Calculate the Sokal-Michener (SM) similarity index. + + https://jcheminf.biomedcentral.com/articles/10.1186/s13321-021-00505-3""" + sm_nw = (counters["total_w_sim"]) / (counters["p"]) + return sm_nw + + +def _ss1_nw(counters: dict) -> float: + """Calculate the Sokal-Sneath 1 (SS1) similarity index. + + https://jcheminf.biomedcentral.com/articles/10.1186/s13321-021-00505-3""" + ss1_nw = (counters["w_a"]) / (counters["a"] + 2 * counters["total_dis"]) + return ss1_nw + + +def _ss2_nw(counters: dict) -> float: + """Calculate the Sokal-Sneath 2 (SS2) similarity index. + + https://jcheminf.biomedcentral.com/articles/10.1186/s13321-021-00505-3""" + ss2_nw = (2 * counters["total_w_sim"]) / (counters["p"] + counters["total_sim"]) + return ss2_nw + + +# Dictionary with the similarity indexes functions as values and the keys are the abbreviations +_similarity_index_dict = { + "AC": _ac_nw, + "BUB": _bub_nw, + "CT1": _ct1_nw, + "CT2": _ct2_nw, + "CT3": _ct3_nw, + "CT4": _ct4_nw, + "Fai": _fai_nw, + "Gle": _gle_nw, + "Ja": _ja_nw, + "Ja0": _ja0_nw, + "JT": _jt_nw, + "RT": _rt_nw, + "RR": _rr_nw, + "SM": _sm_nw, + "SS1": _ss1_nw, + "SS2": _ss2_nw, +} diff --git a/selector/methods/tests/__init__.py b/selector/methods/tests/__init__.py index e8247618..82d239c9 100644 --- a/selector/methods/tests/__init__.py +++ b/selector/methods/tests/__init__.py @@ -1,23 +1,23 @@ -# -*- coding: utf-8 -*- -# -# The Selector is a Python library of algorithms for selecting diverse -# subsets of data for machine-learning. -# -# Copyright (C) 2022-2024 The QC-Devs Community -# -# This file is part of Selector. -# -# Selector is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 -# of the License, or (at your option) any later version. -# -# Selector is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see -# -# -- +# -*- coding: utf-8 -*- +# +# The Selector is a Python library of algorithms for selecting diverse +# subsets of data for machine-learning. +# +# Copyright (C) 2022-2024 The QC-Devs Community +# +# This file is part of Selector. +# +# Selector is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 +# of the License, or (at your option) any later version. +# +# Selector is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see +# +# -- diff --git a/selector/methods/tests/common.py b/selector/methods/tests/common.py index 9c152d30..c5aa26a5 100644 --- a/selector/methods/tests/common.py +++ b/selector/methods/tests/common.py @@ -1,144 +1,144 @@ -# -*- coding: utf-8 -*- -# -# The Selector is a Python library of algorithms for selecting diverse -# subsets of data for machine-learning. -# -# Copyright (C) 2022-2024 The QC-Devs Community -# -# This file is part of Selector. -# -# Selector is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 -# of the License, or (at your option) any later version. -# -# Selector is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see -# -# -- -"""Common functions for test module.""" - -from importlib import resources -from typing import Any, Tuple, Union - -import numpy as np -from sklearn.datasets import make_blobs -from sklearn.metrics import pairwise_distances - -__all__ = [ - "generate_synthetic_cluster_data", - "generate_synthetic_data", - "get_data_file_path", -] - - -def generate_synthetic_cluster_data(): - # generate the first cluster with 3 points - cluster_one = np.array([[0, 0], [0, 1], [0, 2]]) - # generate the second cluster with 6 points - cluster_two = np.array([[3, 0], [3, 1], [3, 2], [3, 3], [3, 4], [3, 5]]) - # generate the third cluster with 9 points - cluster_three = np.array( - [[6, 0], [6, 1], [6, 2], [6, 3], [6, 4], [6, 5], [6, 6], [6, 7], [6, 8]] - ) - # concatenate the clusters - coords = np.vstack([cluster_one, cluster_two, cluster_three]) - # generate the labels - labels = np.hstack([[0 for _ in range(3)], [1 for _ in range(6)], [2 for _ in range(9)]]) - - return coords, labels, cluster_one, cluster_two, cluster_three - - -def generate_synthetic_data( - n_samples: int = 100, - n_features: int = 2, - n_clusters: int = 2, - cluster_std: float = 1.0, - center_box: Tuple[float, float] = (-10.0, 10.0), - metric: str = "euclidean", - shuffle: bool = True, - random_state: int = 42, - pairwise_dist: bool = False, - **kwargs: Any, -) -> Union[Tuple[np.ndarray, np.ndarray], Tuple[np.ndarray, np.ndarray, np.ndarray]]: - """Generate synthetic data. - - Parameters - ---------- - n_samples : int, optional - The number of sample points. - n_features : int, optional - The number of features. - n_clusters : int, optional - The number of clusters. - cluster_std : float, optional - The standard deviation of the clusters. - center_box : tuple[float, float], optional - The bounding box for each cluster center when centers are generated at random. - metric : str, optional - The metric used for computing pairwise distances. For the supported - distance matrix, please refer to - https://scikit-learn.org/stable/modules/generated/sklearn.metrics.pairwise_distances.html. - shuffle : bool, optional - Whether to shuffle the samples. - random_state : int, optional - The random state used for generating synthetic data. - pairwise_dist : bool, optional - If True, then compute and return the pairwise distances between sample points. - **kwargs : Any, optional - Additional keyword arguments for the scikit-learn `pairwise_distances` function. - - Returns - ------- - syn_data : np.ndarray - The synthetic data. - class_labels : np.ndarray - The integer labels for cluster membership of each sample. - dist: np.ndarray - The symmetric pairwise distances between samples. - - """ - # pylint: disable=W0632 - syn_data, class_labels = make_blobs( - n_samples=n_samples, - n_features=n_features, - centers=n_clusters, - cluster_std=cluster_std, - center_box=center_box, - shuffle=shuffle, - random_state=random_state, - return_centers=False, - ) - if pairwise_dist: - dist = pairwise_distances( - X=syn_data, - Y=None, - metric=metric, - **kwargs, - ) - return syn_data, class_labels, dist - return syn_data, class_labels - - -def get_data_file_path(file_name): - """Get the absolute path of the data file inside the package. - - Parameters - ---------- - file_name : str - The name of the data file to load. - - Returns - ------- - str - The absolute path of the data file inside the package - - """ - data_file_path = resources.files("selector.methods.tests").joinpath(f"data/{file_name}") - - return data_file_path +# -*- coding: utf-8 -*- +# +# The Selector is a Python library of algorithms for selecting diverse +# subsets of data for machine-learning. +# +# Copyright (C) 2022-2024 The QC-Devs Community +# +# This file is part of Selector. +# +# Selector is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 +# of the License, or (at your option) any later version. +# +# Selector is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see +# +# -- +"""Common functions for test module.""" + +from importlib import resources +from typing import Any, Tuple, Union + +import numpy as np +from sklearn.datasets import make_blobs +from sklearn.metrics import pairwise_distances + +__all__ = [ + "generate_synthetic_cluster_data", + "generate_synthetic_data", + "get_data_file_path", +] + + +def generate_synthetic_cluster_data(): + # generate the first cluster with 3 points + cluster_one = np.array([[0, 0], [0, 1], [0, 2]]) + # generate the second cluster with 6 points + cluster_two = np.array([[3, 0], [3, 1], [3, 2], [3, 3], [3, 4], [3, 5]]) + # generate the third cluster with 9 points + cluster_three = np.array( + [[6, 0], [6, 1], [6, 2], [6, 3], [6, 4], [6, 5], [6, 6], [6, 7], [6, 8]] + ) + # concatenate the clusters + coords = np.vstack([cluster_one, cluster_two, cluster_three]) + # generate the labels + labels = np.hstack([[0 for _ in range(3)], [1 for _ in range(6)], [2 for _ in range(9)]]) + + return coords, labels, cluster_one, cluster_two, cluster_three + + +def generate_synthetic_data( + n_samples: int = 100, + n_features: int = 2, + n_clusters: int = 2, + cluster_std: float = 1.0, + center_box: Tuple[float, float] = (-10.0, 10.0), + metric: str = "euclidean", + shuffle: bool = True, + random_state: int = 42, + pairwise_dist: bool = False, + **kwargs: Any, +) -> Union[Tuple[np.ndarray, np.ndarray], Tuple[np.ndarray, np.ndarray, np.ndarray]]: + """Generate synthetic data. + + Parameters + ---------- + n_samples : int, optional + The number of sample points. + n_features : int, optional + The number of features. + n_clusters : int, optional + The number of clusters. + cluster_std : float, optional + The standard deviation of the clusters. + center_box : tuple[float, float], optional + The bounding box for each cluster center when centers are generated at random. + metric : str, optional + The metric used for computing pairwise distances. For the supported + distance matrix, please refer to + https://scikit-learn.org/stable/modules/generated/sklearn.metrics.pairwise_distances.html. + shuffle : bool, optional + Whether to shuffle the samples. + random_state : int, optional + The random state used for generating synthetic data. + pairwise_dist : bool, optional + If True, then compute and return the pairwise distances between sample points. + **kwargs : Any, optional + Additional keyword arguments for the scikit-learn `pairwise_distances` function. + + Returns + ------- + syn_data : np.ndarray + The synthetic data. + class_labels : np.ndarray + The integer labels for cluster membership of each sample. + dist: np.ndarray + The symmetric pairwise distances between samples. + + """ + # pylint: disable=W0632 + syn_data, class_labels = make_blobs( + n_samples=n_samples, + n_features=n_features, + centers=n_clusters, + cluster_std=cluster_std, + center_box=center_box, + shuffle=shuffle, + random_state=random_state, + return_centers=False, + ) + if pairwise_dist: + dist = pairwise_distances( + X=syn_data, + Y=None, + metric=metric, + **kwargs, + ) + return syn_data, class_labels, dist + return syn_data, class_labels + + +def get_data_file_path(file_name): + """Get the absolute path of the data file inside the package. + + Parameters + ---------- + file_name : str + The name of the data file to load. + + Returns + ------- + str + The absolute path of the data file inside the package + + """ + data_file_path = resources.files("selector.methods.tests").joinpath(f"data/{file_name}") + + return data_file_path diff --git a/selector/methods/tests/data/coords_imbalance_case1.txt b/selector/methods/tests/data/coords_imbalance_case1.txt index 8a29ea2e..ff3d35e9 100644 --- a/selector/methods/tests/data/coords_imbalance_case1.txt +++ b/selector/methods/tests/data/coords_imbalance_case1.txt @@ -1,52 +1,52 @@ --2.988371860898040300e+00,8.828627151534506723e+00 --2.522694847790684314e+00,7.956575199242423402e+00 -2.721107620929060111e+00,1.946655808491515094e+00 -3.856625543891864183e+00,1.651108167735056309e+00 -4.447517871446978965e+00,2.274717026274344356e+00 -4.247770683095943411e+00,5.096547358086134238e-01 -5.161820401844998685e+00,2.270154357173918225e+00 -3.448575339025452990e+00,2.629723292574561722e+00 -4.110118632461063015e+00,2.486437117054088208e+00 -4.605167066522858121e+00,8.044916463211999602e-01 -3.959854114649610679e+00,2.205423381101735636e+00 -4.935999113292677265e+00,2.234224956120621108e+00 --7.194896435791616085e+00,-6.121140372782679862e+00 --6.521839830802987237e+00,-6.319325066907712340e+00 --6.665533447021066316e+00,-8.125848371987935082e+00 --4.564968624477761416e+00,-8.747374785867695124e+00 --4.735683101825944874e+00,-6.246190570957935506e+00 --7.144284024389226495e+00,-4.159940426686327797e+00 --6.364591923942610308e+00,-6.366323642363737711e+00 --7.769141620776792934e+00,-7.695919878241385348e+00 --6.821418472705270020e+00,-8.023079891106569050e+00 --7.541413655919658510e+00,-6.027676258479722549e+00 --6.706446265300088250e+00,-6.494792213547110116e+00 --6.406389566577725070e+00,-6.952938505932819702e+00 --7.609993822868406532e+00,-6.663651003693972008e+00 --5.796575947975993515e+00,-5.826307541241043886e+00 --7.351559056940703663e+00,-5.791158996308579887e+00 --7.364990738980373486e+00,-6.798235453889623692e+00 --6.956728900565374296e+00,-6.538957618459303234e+00 --6.253959843386263984e+00,-7.737267149692229395e+00 --6.057567031156779969e+00,-4.983316610621999487e+00 --7.594930900411238639e+00,-6.200511844341271228e+00 --7.125015307154140665e+00,-7.633845757633435980e+00 --7.672147929583970516e+00,-6.994846034742845831e+00 --7.103089976477121148e+00,-6.166109099183854525e+00 --6.602936391821250695e+00,-6.052926344239923040e+00 --8.904769777808876796e+00,-6.693655278506518869e+00 --8.257296559108361578e+00,-7.817934633191069516e+00 --6.364579504845222502e+00,-3.027378102621225864e+00 --6.834055351247456223e+00,-7.531709940881763821e+00 --7.652452405688841885e+00,-7.116928200015955497e+00 --7.726420909219674726e+00,-8.394956817961810813e+00 --6.866625299273363403e+00,-5.426575516118630205e+00 --6.374639912170812828e+00,-6.014354399105824811e+00 --7.326142143218291380e+00,-6.023710798952474299e+00 --6.308736680458102875e+00,-5.744543953095347710e+00 --8.079923598207045643e+00,-7.214610829116894664e+00 --6.193367000776756726e+00,-8.492825464465598273e+00 --5.925625427658067323e+00,-6.228718341970148842e+00 --7.950519689212382168e+00,-6.397637178032761440e+00 --7.763484627352402967e+00,-6.726384487330419049e+00 --6.815347172055806979e+00,-7.957854371205252519e+00 +-2.988371860898040300e+00,8.828627151534506723e+00 +-2.522694847790684314e+00,7.956575199242423402e+00 +2.721107620929060111e+00,1.946655808491515094e+00 +3.856625543891864183e+00,1.651108167735056309e+00 +4.447517871446978965e+00,2.274717026274344356e+00 +4.247770683095943411e+00,5.096547358086134238e-01 +5.161820401844998685e+00,2.270154357173918225e+00 +3.448575339025452990e+00,2.629723292574561722e+00 +4.110118632461063015e+00,2.486437117054088208e+00 +4.605167066522858121e+00,8.044916463211999602e-01 +3.959854114649610679e+00,2.205423381101735636e+00 +4.935999113292677265e+00,2.234224956120621108e+00 +-7.194896435791616085e+00,-6.121140372782679862e+00 +-6.521839830802987237e+00,-6.319325066907712340e+00 +-6.665533447021066316e+00,-8.125848371987935082e+00 +-4.564968624477761416e+00,-8.747374785867695124e+00 +-4.735683101825944874e+00,-6.246190570957935506e+00 +-7.144284024389226495e+00,-4.159940426686327797e+00 +-6.364591923942610308e+00,-6.366323642363737711e+00 +-7.769141620776792934e+00,-7.695919878241385348e+00 +-6.821418472705270020e+00,-8.023079891106569050e+00 +-7.541413655919658510e+00,-6.027676258479722549e+00 +-6.706446265300088250e+00,-6.494792213547110116e+00 +-6.406389566577725070e+00,-6.952938505932819702e+00 +-7.609993822868406532e+00,-6.663651003693972008e+00 +-5.796575947975993515e+00,-5.826307541241043886e+00 +-7.351559056940703663e+00,-5.791158996308579887e+00 +-7.364990738980373486e+00,-6.798235453889623692e+00 +-6.956728900565374296e+00,-6.538957618459303234e+00 +-6.253959843386263984e+00,-7.737267149692229395e+00 +-6.057567031156779969e+00,-4.983316610621999487e+00 +-7.594930900411238639e+00,-6.200511844341271228e+00 +-7.125015307154140665e+00,-7.633845757633435980e+00 +-7.672147929583970516e+00,-6.994846034742845831e+00 +-7.103089976477121148e+00,-6.166109099183854525e+00 +-6.602936391821250695e+00,-6.052926344239923040e+00 +-8.904769777808876796e+00,-6.693655278506518869e+00 +-8.257296559108361578e+00,-7.817934633191069516e+00 +-6.364579504845222502e+00,-3.027378102621225864e+00 +-6.834055351247456223e+00,-7.531709940881763821e+00 +-7.652452405688841885e+00,-7.116928200015955497e+00 +-7.726420909219674726e+00,-8.394956817961810813e+00 +-6.866625299273363403e+00,-5.426575516118630205e+00 +-6.374639912170812828e+00,-6.014354399105824811e+00 +-7.326142143218291380e+00,-6.023710798952474299e+00 +-6.308736680458102875e+00,-5.744543953095347710e+00 +-8.079923598207045643e+00,-7.214610829116894664e+00 +-6.193367000776756726e+00,-8.492825464465598273e+00 +-5.925625427658067323e+00,-6.228718341970148842e+00 +-7.950519689212382168e+00,-6.397637178032761440e+00 +-7.763484627352402967e+00,-6.726384487330419049e+00 +-6.815347172055806979e+00,-7.957854371205252519e+00 diff --git a/selector/methods/tests/data/coords_imbalance_case2.txt b/selector/methods/tests/data/coords_imbalance_case2.txt index 9f5600b2..ea0a34d1 100644 --- a/selector/methods/tests/data/coords_imbalance_case2.txt +++ b/selector/methods/tests/data/coords_imbalance_case2.txt @@ -1,54 +1,54 @@ --2.545023662162701594e+00,1.057892978401232931e+01 --3.348415146275388832e+00,8.705073752347109561e+00 --3.186119623358708797e+00,9.625962417039191976e+00 -6.526064737438631802e+00,2.147747496772570930e+00 -5.265546183993107476e+00,1.116012127524449449e+00 -3.793085118159696290e+00,4.583224592548673648e-01 -4.605167066522858121e+00,8.044916463211999602e-01 -3.665197166000779827e+00,2.760254287683184149e+00 -4.890371686573978138e+00,2.319617893437707856e+00 -3.089215405161968686e+00,2.041732658746759466e+00 -4.416416050902250312e+00,2.687170178032824097e+00 -3.568986338166989292e+00,2.455642099183917182e+00 -4.447517871446978965e+00,2.274717026274344356e+00 -5.161820401844998685e+00,2.270154357173918225e+00 --6.598635323416237597e+00,-7.502809113096540194e+00 --6.364591923942610308e+00,-6.366323642363737711e+00 --7.351559056940703663e+00,-5.791158996308579887e+00 --4.757470994138636833e+00,-5.847644332724799554e+00 --7.132195342544430439e+00,-8.127892775240795231e+00 --6.766109845900022179e+00,-6.217978918754900164e+00 --6.680567495577800052e+00,-7.480326470434741637e+00 --7.354572502312226590e+00,-7.533438825849658294e+00 --4.735683101825944874e+00,-6.246190570957935506e+00 --8.140511145486314604e+00,-5.962247646221170427e+00 --6.374639912170812828e+00,-6.014354399105824811e+00 --4.746593816495003892e+00,-8.832197392798448732e+00 --7.652452405688841885e+00,-7.116928200015955497e+00 --6.435807763005041870e+00,-6.105475539846610289e+00 --6.308736680458102875e+00,-5.744543953095347710e+00 --6.900528785115418451e+00,-6.762782209967165059e+00 --6.834055351247456223e+00,-7.531709940881763821e+00 --8.079923598207045643e+00,-7.214610829116894664e+00 --7.672147929583970516e+00,-6.994846034742845831e+00 --5.293610375005918023e+00,-8.117925092102796114e+00 --7.087749441508545800e+00,-7.373110527934779945e+00 --5.247215887219635277e+00,-8.310250971236579076e+00 --6.364579504845222502e+00,-3.027378102621225864e+00 --7.364990738980373486e+00,-6.798235453889623692e+00 --7.861135842199221457e+00,-6.418006119012676258e+00 --6.132333586028008376e+00,-6.269739327842481558e+00 --5.925625427658067323e+00,-6.228718341970148842e+00 --5.612716041964647573e+00,-7.587779058894727591e+00 --5.980027315718019487e+00,-6.572810072399337677e+00 --7.031412286186853322e+00,-6.291792386791370539e+00 --4.564968624477761416e+00,-8.747374785867695124e+00 --7.319671677848253566e+00,-6.749369015989855392e+00 --5.438353902085154346e+00,-8.315971744455385561e+00 --6.809825106161251362e+00,-7.265423190137706655e+00 --8.904769777808876796e+00,-6.693655278506518869e+00 --6.193367000776756726e+00,-8.492825464465598273e+00 --8.398997157105283051e+00,-7.364343666142198153e+00 --6.522611705186222686e+00,-7.573019188536600943e+00 --5.716463438996310487e+00,-6.869876532256359525e+00 --1.012089453122034222e+01,-7.904497234610236234e+00 +-2.545023662162701594e+00,1.057892978401232931e+01 +-3.348415146275388832e+00,8.705073752347109561e+00 +-3.186119623358708797e+00,9.625962417039191976e+00 +6.526064737438631802e+00,2.147747496772570930e+00 +5.265546183993107476e+00,1.116012127524449449e+00 +3.793085118159696290e+00,4.583224592548673648e-01 +4.605167066522858121e+00,8.044916463211999602e-01 +3.665197166000779827e+00,2.760254287683184149e+00 +4.890371686573978138e+00,2.319617893437707856e+00 +3.089215405161968686e+00,2.041732658746759466e+00 +4.416416050902250312e+00,2.687170178032824097e+00 +3.568986338166989292e+00,2.455642099183917182e+00 +4.447517871446978965e+00,2.274717026274344356e+00 +5.161820401844998685e+00,2.270154357173918225e+00 +-6.598635323416237597e+00,-7.502809113096540194e+00 +-6.364591923942610308e+00,-6.366323642363737711e+00 +-7.351559056940703663e+00,-5.791158996308579887e+00 +-4.757470994138636833e+00,-5.847644332724799554e+00 +-7.132195342544430439e+00,-8.127892775240795231e+00 +-6.766109845900022179e+00,-6.217978918754900164e+00 +-6.680567495577800052e+00,-7.480326470434741637e+00 +-7.354572502312226590e+00,-7.533438825849658294e+00 +-4.735683101825944874e+00,-6.246190570957935506e+00 +-8.140511145486314604e+00,-5.962247646221170427e+00 +-6.374639912170812828e+00,-6.014354399105824811e+00 +-4.746593816495003892e+00,-8.832197392798448732e+00 +-7.652452405688841885e+00,-7.116928200015955497e+00 +-6.435807763005041870e+00,-6.105475539846610289e+00 +-6.308736680458102875e+00,-5.744543953095347710e+00 +-6.900528785115418451e+00,-6.762782209967165059e+00 +-6.834055351247456223e+00,-7.531709940881763821e+00 +-8.079923598207045643e+00,-7.214610829116894664e+00 +-7.672147929583970516e+00,-6.994846034742845831e+00 +-5.293610375005918023e+00,-8.117925092102796114e+00 +-7.087749441508545800e+00,-7.373110527934779945e+00 +-5.247215887219635277e+00,-8.310250971236579076e+00 +-6.364579504845222502e+00,-3.027378102621225864e+00 +-7.364990738980373486e+00,-6.798235453889623692e+00 +-7.861135842199221457e+00,-6.418006119012676258e+00 +-6.132333586028008376e+00,-6.269739327842481558e+00 +-5.925625427658067323e+00,-6.228718341970148842e+00 +-5.612716041964647573e+00,-7.587779058894727591e+00 +-5.980027315718019487e+00,-6.572810072399337677e+00 +-7.031412286186853322e+00,-6.291792386791370539e+00 +-4.564968624477761416e+00,-8.747374785867695124e+00 +-7.319671677848253566e+00,-6.749369015989855392e+00 +-5.438353902085154346e+00,-8.315971744455385561e+00 +-6.809825106161251362e+00,-7.265423190137706655e+00 +-8.904769777808876796e+00,-6.693655278506518869e+00 +-6.193367000776756726e+00,-8.492825464465598273e+00 +-8.398997157105283051e+00,-7.364343666142198153e+00 +-6.522611705186222686e+00,-7.573019188536600943e+00 +-5.716463438996310487e+00,-6.869876532256359525e+00 +-1.012089453122034222e+01,-7.904497234610236234e+00 diff --git a/selector/methods/tests/data/labels_imbalance_case1.txt b/selector/methods/tests/data/labels_imbalance_case1.txt index 96ed3569..99d7f177 100644 --- a/selector/methods/tests/data/labels_imbalance_case1.txt +++ b/selector/methods/tests/data/labels_imbalance_case1.txt @@ -1,52 +1,52 @@ -0.000000000000000000e+00 -0.000000000000000000e+00 -1.000000000000000000e+00 -1.000000000000000000e+00 -1.000000000000000000e+00 -1.000000000000000000e+00 -1.000000000000000000e+00 -1.000000000000000000e+00 -1.000000000000000000e+00 -1.000000000000000000e+00 -1.000000000000000000e+00 -1.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 +0.000000000000000000e+00 +0.000000000000000000e+00 +1.000000000000000000e+00 +1.000000000000000000e+00 +1.000000000000000000e+00 +1.000000000000000000e+00 +1.000000000000000000e+00 +1.000000000000000000e+00 +1.000000000000000000e+00 +1.000000000000000000e+00 +1.000000000000000000e+00 +1.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 diff --git a/selector/methods/tests/data/labels_imbalance_case2.txt b/selector/methods/tests/data/labels_imbalance_case2.txt index b3bb027f..b38d5c1e 100644 --- a/selector/methods/tests/data/labels_imbalance_case2.txt +++ b/selector/methods/tests/data/labels_imbalance_case2.txt @@ -1,54 +1,54 @@ -0.000000000000000000e+00 -0.000000000000000000e+00 -0.000000000000000000e+00 -1.000000000000000000e+00 -1.000000000000000000e+00 -1.000000000000000000e+00 -1.000000000000000000e+00 -1.000000000000000000e+00 -1.000000000000000000e+00 -1.000000000000000000e+00 -1.000000000000000000e+00 -1.000000000000000000e+00 -1.000000000000000000e+00 -1.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 -2.000000000000000000e+00 +0.000000000000000000e+00 +0.000000000000000000e+00 +0.000000000000000000e+00 +1.000000000000000000e+00 +1.000000000000000000e+00 +1.000000000000000000e+00 +1.000000000000000000e+00 +1.000000000000000000e+00 +1.000000000000000000e+00 +1.000000000000000000e+00 +1.000000000000000000e+00 +1.000000000000000000e+00 +1.000000000000000000e+00 +1.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 +2.000000000000000000e+00 diff --git a/selector/methods/tests/data/ref_esim_selection_data.csv b/selector/methods/tests/data/ref_esim_selection_data.csv index e7c551f4..c42d46d1 100644 --- a/selector/methods/tests/data/ref_esim_selection_data.csv +++ b/selector/methods/tests/data/ref_esim_selection_data.csv @@ -1,577 +1,577 @@ -c_threshold;w_factor;sample_size;start_idx;n_ary;result -None;fraction;10;medoid;AC;[96,33,0,49,1,66,3,35,8,37] -None;fraction;10;outlier;AC;[4,42,8,17,5,19,10,22,13,49] -None;fraction;10;[1,2,3];AC;[1,2,3,16,0,64,6,85,4,12] -None;fraction;10;medoid;BUB;[69,13,0,27,1,66,2,19,3,31] -None;fraction;10;outlier;BUB;[34,85,0,2,1,41,3,20,4,64] -None;fraction;10;[1,2,3];BUB;[1,2,3,16,0,64,6,85,4,12] -None;fraction;10;medoid;CT1;[96,33,0,49,1,66,3,35,8,37] -None;fraction;10;outlier;CT1;[4,42,8,17,5,99,13,54,12,0] -None;fraction;10;[1,2,3];CT1;[1,2,3,16,0,64,6,85,4,12] -None;fraction;10;medoid;CT2;[80,1,0,64,2,4,7,97,5,6] -None;fraction;10;outlier;CT2;[4,42,8,17,5,19,10,22,13,49] -None;fraction;10;[1,2,3];CT2;[1,2,3,16,0,64,6,85,4,12] -None;fraction;10;medoid;CT3;[1,8,2,31,0,26,3,19,5,27] -None;fraction;10;outlier;CT3;[8,5,0,2,1,47,3,19,7,93] -None;fraction;10;[1,2,3];CT3;[1,2,3,78,0,41,4,85,6,64] -None;fraction;10;medoid;CT4;[23,78,0,26,1,58,2,8,3,48] -None;fraction;10;outlier;CT4;[34,85,0,2,1,41,3,20,4,64] -None;fraction;10;[1,2,3];CT4;[1,2,3,78,0,41,4,85,6,64] -None;fraction;10;medoid;Fai;[96,33,0,49,1,66,3,35,8,37] -None;fraction;10;outlier;Fai;[34,43,2,25,0,26,1,66,7,97] -None;fraction;10;[1,2,3];Fai;[1,2,3,16,0,64,6,85,4,12] -None;fraction;10;medoid;Gle;[69,13,0,27,1,66,2,19,3,31] -None;fraction;10;outlier;Gle;[34,85,0,2,1,41,3,20,4,64] -None;fraction;10;[1,2,3];Gle;[1,2,3,78,0,41,4,85,6,64] -None;fraction;10;medoid;Ja;[69,13,0,27,1,66,2,19,3,31] -None;fraction;10;outlier;Ja;[34,85,0,2,1,41,3,20,4,64] -None;fraction;10;[1,2,3];Ja;[1,2,3,78,0,41,4,85,6,64] -None;fraction;10;medoid;Ja0;[50,28,0,21,16,74,20,40,7,36] -None;fraction;10;outlier;Ja0;[49,9,7,66,0,35,2,25,3,76] -None;fraction;10;[1,2,3];Ja0;[1,2,3,16,0,64,6,85,4,12] -None;fraction;10;medoid;JT;[69,13,0,27,1,66,2,19,3,31] -None;fraction;10;outlier;JT;[34,85,0,2,1,41,3,20,4,64] -None;fraction;10;[1,2,3];JT;[1,2,3,78,0,41,4,85,6,64] -None;fraction;10;medoid;RT;[96,33,0,49,1,66,3,35,8,37] -None;fraction;10;outlier;RT;[4,42,8,17,5,19,10,22,13,49] -None;fraction;10;[1,2,3];RT;[1,2,3,16,0,64,6,85,4,12] -None;fraction;10;medoid;RR;[1,8,2,31,0,26,3,19,5,27] -None;fraction;10;outlier;RR;[8,5,0,2,1,47,3,19,7,93] -None;fraction;10;[1,2,3];RR;[1,2,3,78,0,41,4,85,6,64] -None;fraction;10;medoid;SM;[96,33,0,49,1,66,3,35,8,37] -None;fraction;10;outlier;SM;[4,42,8,17,5,19,10,22,13,49] -None;fraction;10;[1,2,3];SM;[1,2,3,16,0,64,6,85,4,12] -None;fraction;10;medoid;SS1;[23,78,0,26,1,58,2,8,3,48] -None;fraction;10;outlier;SS1;[34,85,0,2,1,41,3,20,4,64] -None;fraction;10;[1,2,3];SS1;[1,2,3,78,0,41,4,85,6,64] -None;fraction;10;medoid;SS2;[50,28,0,21,16,74,20,40,7,36] -None;fraction;10;outlier;SS2;[49,9,7,66,0,35,2,25,3,76] -None;fraction;10;[1,2,3];SS2;[1,2,3,16,0,64,6,85,4,12] -None;fraction;20;medoid;AC;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16] -None;fraction;20;outlier;AC;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76] -None;fraction;20;[1,2,3];AC;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] -None;fraction;20;medoid;BUB;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97] -None;fraction;20;outlier;BUB;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,49,10,28,12,40] -None;fraction;20;[1,2,3];BUB;[1,2,3,16,0,64,6,85,4,12,8,28,5,40,7,9,10,66,11,19] -None;fraction;20;medoid;CT1;[96,33,0,49,1,66,3,35,8,37,5,40,7,20,6,91,4,12,19,31] -None;fraction;20;outlier;CT1;[4,42,8,17,5,99,13,54,12,0,19,33,2,18,7,20,3,49,9,41] -None;fraction;20;[1,2,3];CT1;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,86,10,19] -None;fraction;20;medoid;CT2;[80,1,0,64,2,4,7,97,5,6,28,77,3,76,8,15,22,47,12,43] -None;fraction;20;outlier;CT2;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76] -None;fraction;20;[1,2,3];CT2;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] -None;fraction;20;medoid;CT3;[1,8,2,31,0,26,3,19,5,27,4,39,6,22,7,85,9,11,10,66] -None;fraction;20;outlier;CT3;[8,5,0,2,1,47,3,19,7,93,4,76,11,41,6,85,9,42,10,66] -None;fraction;20;[1,2,3];CT3;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] -None;fraction;20;medoid;CT4;[23,78,0,26,1,58,2,8,3,48,4,76,5,6,7,97,9,66,10,49] -None;fraction;20;outlier;CT4;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89] -None;fraction;20;[1,2,3];CT4;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] -None;fraction;20;medoid;Fai;[96,33,0,49,1,66,3,35,8,37,5,40,7,20,6,91,4,12,19,31] -None;fraction;20;outlier;Fai;[34,43,2,25,0,26,1,66,7,97,6,69,5,8,10,19,12,57,3,78] -None;fraction;20;[1,2,3];Fai;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,86,10,19] -None;fraction;20;medoid;Gle;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97] -None;fraction;20;outlier;Gle;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89] -None;fraction;20;[1,2,3];Gle;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] -None;fraction;20;medoid;Ja;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97] -None;fraction;20;outlier;Ja;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89] -None;fraction;20;[1,2,3];Ja;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] -None;fraction;20;medoid;Ja0;[50,28,0,21,16,74,20,40,7,36,4,49,8,17,5,54,1,86,3,6] -None;fraction;20;outlier;Ja0;[49,9,7,66,0,35,2,25,3,76,4,85,1,8,5,32,16,65,12,54] -None;fraction;20;[1,2,3];Ja0;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] -None;fraction;20;medoid;JT;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97] -None;fraction;20;outlier;JT;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89] -None;fraction;20;[1,2,3];JT;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] -None;fraction;20;medoid;RT;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16] -None;fraction;20;outlier;RT;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76] -None;fraction;20;[1,2,3];RT;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] -None;fraction;20;medoid;RR;[1,8,2,31,0,26,3,19,5,27,4,39,6,22,7,85,9,11,10,66] -None;fraction;20;outlier;RR;[8,5,0,2,1,47,3,19,7,93,4,76,11,41,6,85,9,42,10,66] -None;fraction;20;[1,2,3];RR;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] -None;fraction;20;medoid;SM;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16] -None;fraction;20;outlier;SM;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76] -None;fraction;20;[1,2,3];SM;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] -None;fraction;20;medoid;SS1;[23,78,0,26,1,58,2,8,3,48,4,76,5,6,7,97,9,66,10,49] -None;fraction;20;outlier;SS1;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89] -None;fraction;20;[1,2,3];SS1;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] -None;fraction;20;medoid;SS2;[50,28,0,21,16,74,20,40,7,36,4,49,8,17,5,54,1,86,3,6] -None;fraction;20;outlier;SS2;[49,9,7,66,0,35,2,25,3,76,4,85,1,8,5,32,16,65,12,54] -None;fraction;20;[1,2,3];SS2;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] -None;fraction;30;medoid;AC;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16,21,85,10,24,11,54,12,19,18,62] -None;fraction;30;outlier;AC;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76,27,54,6,31,15,91,18,44,7,80] -None;fraction;30;[1,2,3];AC;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] -None;fraction;30;medoid;BUB;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97,11,28,14,21,15,36,23,47,16,91] -None;fraction;30;outlier;BUB;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,49,10,28,12,40,14,66,19,44,11,48,13,22,15,91] -None;fraction;30;[1,2,3];BUB;[1,2,3,16,0,64,6,85,4,12,8,28,5,40,7,9,10,66,11,19,13,22,14,21,20,58,15,91,17,84] -None;fraction;30;medoid;CT1;[96,33,0,49,1,66,3,35,8,37,5,40,7,20,6,91,4,12,19,31,2,25,9,57,22,26,10,27,23,85] -None;fraction;30;outlier;CT1;[4,42,8,17,5,99,13,54,12,0,19,33,2,18,7,20,3,49,9,41,11,31,6,66,22,47,1,69,34,57] -None;fraction;30;[1,2,3];CT1;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,86,10,19,22,49,14,40,18,44,13,69,20,32] -None;fraction;30;medoid;CT2;[80,1,0,64,2,4,7,97,5,6,28,77,3,76,8,15,22,47,12,43,11,19,10,66,68,49,9,29,13,69] -None;fraction;30;outlier;CT2;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76,27,54,6,31,15,91,18,44,7,80] -None;fraction;30;[1,2,3];CT2;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] -None;fraction;30;medoid;CT3;[1,8,2,31,0,26,3,19,5,27,4,39,6,22,7,85,9,11,10,66,12,28,13,54,14,29,15,91,16,21] -None;fraction;30;outlier;CT3;[8,5,0,2,1,47,3,19,7,93,4,76,11,41,6,85,9,42,10,66,21,78,12,54,13,22,14,58,15,86] -None;fraction;30;[1,2,3];CT3;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,22] -None;fraction;30;medoid;CT4;[23,78,0,26,1,58,2,8,3,48,4,76,5,6,7,97,9,66,10,49,11,64,12,54,13,56,14,22,15,53] -None;fraction;30;outlier;CT4;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89,12,56,13,22,14,58,15,91,16,21] -None;fraction;30;[1,2,3];CT4;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,84] -None;fraction;30;medoid;Fai;[96,33,0,49,1,66,3,35,8,37,5,40,7,20,6,91,4,12,19,31,2,25,9,58,10,80,71,54,13,36] -None;fraction;30;outlier;Fai;[34,43,2,25,0,26,1,66,7,97,6,69,5,8,10,19,12,57,3,78,17,91,4,80,22,13,14,27,49,9] -None;fraction;30;[1,2,3];Fai;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,86,10,19,22,49,14,40,18,44,13,69,20,55] -None;fraction;30;medoid;Gle;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97,11,28,14,21,15,36,23,47,16,91] -None;fraction;30;outlier;Gle;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89,12,56,13,22,14,58,15,91,16,21] -None;fraction;30;[1,2,3];Gle;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,84] -None;fraction;30;medoid;Ja;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97,11,28,14,21,15,36,23,47,16,91] -None;fraction;30;outlier;Ja;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89,12,56,13,22,14,58,15,91,16,21] -None;fraction;30;[1,2,3];Ja;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,84] -None;fraction;30;medoid;Ja0;[50,28,0,21,16,74,20,40,7,36,4,49,8,17,5,54,1,86,3,6,22,57,19,42,9,33,14,24,2,84] -None;fraction;30;outlier;Ja0;[49,9,7,66,0,35,2,25,3,76,4,85,1,8,5,32,16,65,12,54,6,24,22,47,71,14,40,80,57,72] -None;fraction;30;[1,2,3];Ja0;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] -None;fraction;30;medoid;JT;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97,11,28,14,21,15,36,23,47,16,91] -None;fraction;30;outlier;JT;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89,12,56,13,22,14,58,15,91,16,21] -None;fraction;30;[1,2,3];JT;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,84] -None;fraction;30;medoid;RT;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16,21,85,10,24,11,54,12,19,18,62] -None;fraction;30;outlier;RT;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76,27,54,6,31,15,91,18,44,7,80] -None;fraction;30;[1,2,3];RT;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] -None;fraction;30;medoid;RR;[1,8,2,31,0,26,3,19,5,27,4,39,6,22,7,85,9,11,10,66,12,28,13,54,14,29,15,91,16,21] -None;fraction;30;outlier;RR;[8,5,0,2,1,47,3,19,7,93,4,76,11,41,6,85,9,42,10,66,21,78,12,54,13,22,14,58,15,86] -None;fraction;30;[1,2,3];RR;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,22] -None;fraction;30;medoid;SM;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16,21,85,10,24,11,54,12,19,18,62] -None;fraction;30;outlier;SM;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76,27,54,6,31,15,91,18,44,7,80] -None;fraction;30;[1,2,3];SM;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] -None;fraction;30;medoid;SS1;[23,78,0,26,1,58,2,8,3,48,4,76,5,6,7,97,9,66,10,49,11,64,12,54,13,56,14,22,15,53] -None;fraction;30;outlier;SS1;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89,12,56,13,22,14,58,15,91,16,21] -None;fraction;30;[1,2,3];SS1;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,84] -None;fraction;30;medoid;SS2;[50,28,0,21,16,74,20,40,7,36,4,49,8,17,5,54,1,86,3,6,22,57,19,42,9,33,14,24,2,84] -None;fraction;30;outlier;SS2;[49,9,7,66,0,35,2,25,3,76,4,85,1,8,5,32,16,65,12,54,6,24,22,47,71,14,40,80,57,72] -None;fraction;30;[1,2,3];SS2;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] -None;power_3;10;medoid;AC;[96,33,0,49,1,66,3,35,8,37] -None;power_3;10;outlier;AC;[4,42,8,17,5,19,10,22,13,49] -None;power_3;10;[1,2,3];AC;[1,2,3,16,0,64,6,85,4,12] -None;power_3;10;medoid;BUB;[69,13,0,27,1,66,2,19,3,31] -None;power_3;10;outlier;BUB;[34,85,0,2,1,41,3,20,4,64] -None;power_3;10;[1,2,3];BUB;[1,2,3,16,0,64,6,85,4,12] -None;power_3;10;medoid;CT1;[96,33,0,49,1,66,3,35,8,37] -None;power_3;10;outlier;CT1;[4,42,8,17,5,99,13,54,12,0] -None;power_3;10;[1,2,3];CT1;[1,2,3,16,0,64,6,85,4,12] -None;power_3;10;medoid;CT2;[80,1,0,64,2,4,7,97,5,6] -None;power_3;10;outlier;CT2;[4,42,8,17,5,19,10,22,13,49] -None;power_3;10;[1,2,3];CT2;[1,2,3,16,0,64,6,85,4,12] -None;power_3;10;medoid;CT3;[1,8,2,31,0,26,3,19,5,27] -None;power_3;10;outlier;CT3;[8,5,0,2,1,47,3,19,7,93] -None;power_3;10;[1,2,3];CT3;[1,2,3,78,0,41,4,85,6,64] -None;power_3;10;medoid;CT4;[23,78,0,26,1,58,2,8,3,48] -None;power_3;10;outlier;CT4;[34,85,0,2,1,41,3,20,4,64] -None;power_3;10;[1,2,3];CT4;[1,2,3,78,0,41,4,85,6,64] -None;power_3;10;medoid;Fai;[96,33,0,49,1,66,3,35,8,37] -None;power_3;10;outlier;Fai;[34,43,2,25,0,26,1,66,7,97] -None;power_3;10;[1,2,3];Fai;[1,2,3,16,0,64,6,85,4,12] -None;power_3;10;medoid;Gle;[69,13,0,27,1,66,2,19,3,31] -None;power_3;10;outlier;Gle;[34,85,0,2,1,41,3,20,4,64] -None;power_3;10;[1,2,3];Gle;[1,2,3,78,0,41,4,85,6,64] -None;power_3;10;medoid;Ja;[69,13,0,27,1,66,2,19,3,31] -None;power_3;10;outlier;Ja;[34,85,0,2,1,41,3,20,4,64] -None;power_3;10;[1,2,3];Ja;[1,2,3,78,0,41,4,85,6,64] -None;power_3;10;medoid;Ja0;[50,28,0,21,16,74,20,40,7,36] -None;power_3;10;outlier;Ja0;[49,9,7,66,0,35,2,25,3,76] -None;power_3;10;[1,2,3];Ja0;[1,2,3,16,0,64,6,85,4,12] -None;power_3;10;medoid;JT;[69,13,0,27,1,66,2,19,3,31] -None;power_3;10;outlier;JT;[34,85,0,2,1,41,3,20,4,64] -None;power_3;10;[1,2,3];JT;[1,2,3,78,0,41,4,85,6,64] -None;power_3;10;medoid;RT;[96,33,0,49,1,66,3,35,8,37] -None;power_3;10;outlier;RT;[4,42,8,17,5,19,10,22,13,49] -None;power_3;10;[1,2,3];RT;[1,2,3,16,0,64,6,85,4,12] -None;power_3;10;medoid;RR;[1,8,2,31,0,26,3,19,5,27] -None;power_3;10;outlier;RR;[8,5,0,2,1,47,3,19,7,93] -None;power_3;10;[1,2,3];RR;[1,2,3,78,0,41,4,85,6,64] -None;power_3;10;medoid;SM;[96,33,0,49,1,66,3,35,8,37] -None;power_3;10;outlier;SM;[4,42,8,17,5,19,10,22,13,49] -None;power_3;10;[1,2,3];SM;[1,2,3,16,0,64,6,85,4,12] -None;power_3;10;medoid;SS1;[23,78,0,26,1,58,2,8,3,48] -None;power_3;10;outlier;SS1;[34,85,0,2,1,41,3,20,4,64] -None;power_3;10;[1,2,3];SS1;[1,2,3,78,0,41,4,85,6,64] -None;power_3;10;medoid;SS2;[50,28,0,21,16,74,20,40,7,36] -None;power_3;10;outlier;SS2;[49,9,7,66,0,35,2,25,3,76] -None;power_3;10;[1,2,3];SS2;[1,2,3,16,0,64,6,85,4,12] -None;power_3;20;medoid;AC;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16] -None;power_3;20;outlier;AC;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76] -None;power_3;20;[1,2,3];AC;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] -None;power_3;20;medoid;BUB;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97] -None;power_3;20;outlier;BUB;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,49,10,28,12,40] -None;power_3;20;[1,2,3];BUB;[1,2,3,16,0,64,6,85,4,12,8,28,5,40,7,9,10,66,11,19] -None;power_3;20;medoid;CT1;[96,33,0,49,1,66,3,35,8,37,5,40,7,20,6,91,4,12,19,31] -None;power_3;20;outlier;CT1;[4,42,8,17,5,99,13,54,12,0,19,33,2,18,7,20,3,49,9,41] -None;power_3;20;[1,2,3];CT1;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,86,10,19] -None;power_3;20;medoid;CT2;[80,1,0,64,2,4,7,97,5,6,28,77,3,76,8,15,22,47,12,43] -None;power_3;20;outlier;CT2;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76] -None;power_3;20;[1,2,3];CT2;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] -None;power_3;20;medoid;CT3;[1,8,2,31,0,26,3,19,5,27,4,39,6,22,7,85,9,11,10,66] -None;power_3;20;outlier;CT3;[8,5,0,2,1,47,3,19,7,93,4,76,11,41,6,85,9,42,10,66] -None;power_3;20;[1,2,3];CT3;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] -None;power_3;20;medoid;CT4;[23,78,0,26,1,58,2,8,3,48,4,76,5,6,7,97,9,66,10,49] -None;power_3;20;outlier;CT4;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89] -None;power_3;20;[1,2,3];CT4;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] -None;power_3;20;medoid;Fai;[96,33,0,49,1,66,3,35,8,37,5,40,7,20,6,91,4,12,19,31] -None;power_3;20;outlier;Fai;[34,43,2,25,0,26,1,66,7,97,6,69,5,8,10,19,12,57,3,78] -None;power_3;20;[1,2,3];Fai;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,86,10,19] -None;power_3;20;medoid;Gle;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97] -None;power_3;20;outlier;Gle;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89] -None;power_3;20;[1,2,3];Gle;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] -None;power_3;20;medoid;Ja;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97] -None;power_3;20;outlier;Ja;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89] -None;power_3;20;[1,2,3];Ja;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] -None;power_3;20;medoid;Ja0;[50,28,0,21,16,74,20,40,7,36,4,49,8,17,5,54,1,86,3,6] -None;power_3;20;outlier;Ja0;[49,9,7,66,0,35,2,25,3,76,4,85,1,8,5,32,16,65,12,54] -None;power_3;20;[1,2,3];Ja0;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] -None;power_3;20;medoid;JT;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97] -None;power_3;20;outlier;JT;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89] -None;power_3;20;[1,2,3];JT;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] -None;power_3;20;medoid;RT;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16] -None;power_3;20;outlier;RT;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76] -None;power_3;20;[1,2,3];RT;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] -None;power_3;20;medoid;RR;[1,8,2,31,0,26,3,19,5,27,4,39,6,22,7,85,9,11,10,66] -None;power_3;20;outlier;RR;[8,5,0,2,1,47,3,19,7,93,4,76,11,41,6,85,9,42,10,66] -None;power_3;20;[1,2,3];RR;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] -None;power_3;20;medoid;SM;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16] -None;power_3;20;outlier;SM;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76] -None;power_3;20;[1,2,3];SM;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] -None;power_3;20;medoid;SS1;[23,78,0,26,1,58,2,8,3,48,4,76,5,6,7,97,9,66,10,49] -None;power_3;20;outlier;SS1;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89] -None;power_3;20;[1,2,3];SS1;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] -None;power_3;20;medoid;SS2;[50,28,0,21,16,74,20,40,7,36,4,49,8,17,5,54,1,86,3,6] -None;power_3;20;outlier;SS2;[49,9,7,66,0,35,2,25,3,76,4,85,1,8,5,32,16,65,12,54] -None;power_3;20;[1,2,3];SS2;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] -None;power_3;30;medoid;AC;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16,21,85,10,24,11,54,12,19,18,62] -None;power_3;30;outlier;AC;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76,27,54,6,31,15,91,18,44,7,80] -None;power_3;30;[1,2,3];AC;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] -None;power_3;30;medoid;BUB;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97,11,28,14,21,15,36,23,47,16,91] -None;power_3;30;outlier;BUB;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,49,10,28,12,40,14,66,19,44,11,48,13,22,15,91] -None;power_3;30;[1,2,3];BUB;[1,2,3,16,0,64,6,85,4,12,8,28,5,40,7,9,10,66,11,19,13,22,14,21,20,58,15,91,17,84] -None;power_3;30;medoid;CT1;[96,33,0,49,1,66,3,35,8,37,5,40,7,20,6,91,4,12,19,31,2,25,9,57,22,26,10,27,23,85] -None;power_3;30;outlier;CT1;[4,42,8,17,5,99,13,54,12,0,19,33,2,18,7,20,3,49,9,41,11,31,6,66,22,47,1,69,34,57] -None;power_3;30;[1,2,3];CT1;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,86,10,19,22,49,14,40,18,44,13,69,20,32] -None;power_3;30;medoid;CT2;[80,1,0,64,2,4,7,97,5,6,28,77,3,76,8,15,22,47,12,43,11,19,10,66,68,49,9,29,13,69] -None;power_3;30;outlier;CT2;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76,27,54,6,31,15,91,18,44,7,80] -None;power_3;30;[1,2,3];CT2;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] -None;power_3;30;medoid;CT3;[1,8,2,31,0,26,3,19,5,27,4,39,6,22,7,85,9,11,10,66,12,28,13,54,14,29,15,91,16,21] -None;power_3;30;outlier;CT3;[8,5,0,2,1,47,3,19,7,93,4,76,11,41,6,85,9,42,10,66,21,78,12,54,13,22,14,58,15,86] -None;power_3;30;[1,2,3];CT3;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,22] -None;power_3;30;medoid;CT4;[23,78,0,26,1,58,2,8,3,48,4,76,5,6,7,97,9,66,10,49,11,64,12,54,13,56,14,22,15,53] -None;power_3;30;outlier;CT4;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89,12,56,13,22,14,58,15,91,16,21] -None;power_3;30;[1,2,3];CT4;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,84] -None;power_3;30;medoid;Fai;[96,33,0,49,1,66,3,35,8,37,5,40,7,20,6,91,4,12,19,31,2,25,9,58,10,80,71,54,13,36] -None;power_3;30;outlier;Fai;[34,43,2,25,0,26,1,66,7,97,6,69,5,8,10,19,12,57,3,78,17,91,4,80,22,13,14,27,49,9] -None;power_3;30;[1,2,3];Fai;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,86,10,19,22,49,14,40,18,44,13,69,20,55] -None;power_3;30;medoid;Gle;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97,11,28,14,21,15,36,23,47,16,91] -None;power_3;30;outlier;Gle;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89,12,56,13,22,14,58,15,91,16,21] -None;power_3;30;[1,2,3];Gle;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,84] -None;power_3;30;medoid;Ja;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97,11,28,14,21,15,36,23,47,16,91] -None;power_3;30;outlier;Ja;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89,12,56,13,22,14,58,15,91,16,21] -None;power_3;30;[1,2,3];Ja;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,84] -None;power_3;30;medoid;Ja0;[50,28,0,21,16,74,20,40,7,36,4,49,8,17,5,54,1,86,3,6,22,57,19,42,9,33,14,24,2,84] -None;power_3;30;outlier;Ja0;[49,9,7,66,0,35,2,25,3,76,4,85,1,8,5,32,16,65,12,54,6,24,22,47,71,14,40,80,57,72] -None;power_3;30;[1,2,3];Ja0;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] -None;power_3;30;medoid;JT;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97,11,28,14,21,15,36,23,47,16,91] -None;power_3;30;outlier;JT;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89,12,56,13,22,14,58,15,91,16,21] -None;power_3;30;[1,2,3];JT;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,84] -None;power_3;30;medoid;RT;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16,21,85,10,24,11,54,12,19,18,62] -None;power_3;30;outlier;RT;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76,27,54,6,31,15,91,18,44,7,80] -None;power_3;30;[1,2,3];RT;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] -None;power_3;30;medoid;RR;[1,8,2,31,0,26,3,19,5,27,4,39,6,22,7,85,9,11,10,66,12,28,13,54,14,29,15,91,16,21] -None;power_3;30;outlier;RR;[8,5,0,2,1,47,3,19,7,93,4,76,11,41,6,85,9,42,10,66,21,78,12,54,13,22,14,58,15,86] -None;power_3;30;[1,2,3];RR;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,22] -None;power_3;30;medoid;SM;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16,21,85,10,24,11,54,12,19,18,62] -None;power_3;30;outlier;SM;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76,27,54,6,31,15,91,18,44,7,80] -None;power_3;30;[1,2,3];SM;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] -None;power_3;30;medoid;SS1;[23,78,0,26,1,58,2,8,3,48,4,76,5,6,7,97,9,66,10,49,11,64,12,54,13,56,14,22,15,53] -None;power_3;30;outlier;SS1;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89,12,56,13,22,14,58,15,91,16,21] -None;power_3;30;[1,2,3];SS1;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,84] -None;power_3;30;medoid;SS2;[50,28,0,21,16,74,20,40,7,36,4,49,8,17,5,54,1,86,3,6,22,57,19,42,9,33,14,24,2,84] -None;power_3;30;outlier;SS2;[49,9,7,66,0,35,2,25,3,76,4,85,1,8,5,32,16,65,12,54,6,24,22,47,71,14,40,80,57,72] -None;power_3;30;[1,2,3];SS2;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] -dissimilar;fraction;10;medoid;AC;[96,33,0,49,1,66,3,35,8,37] -dissimilar;fraction;10;outlier;AC;[4,42,8,17,5,19,10,22,13,49] -dissimilar;fraction;10;[1,2,3];AC;[1,2,3,16,0,64,6,85,4,12] -dissimilar;fraction;10;medoid;BUB;[69,13,0,27,1,66,2,19,3,31] -dissimilar;fraction;10;outlier;BUB;[34,85,0,2,1,41,3,20,4,64] -dissimilar;fraction;10;[1,2,3];BUB;[1,2,3,16,0,64,6,85,4,12] -dissimilar;fraction;10;medoid;CT1;[96,33,0,49,1,66,3,35,8,37] -dissimilar;fraction;10;outlier;CT1;[4,42,8,17,5,99,13,54,12,0] -dissimilar;fraction;10;[1,2,3];CT1;[1,2,3,16,0,64,6,85,4,12] -dissimilar;fraction;10;medoid;CT2;[80,1,0,64,2,4,7,97,5,6] -dissimilar;fraction;10;outlier;CT2;[4,42,8,17,5,19,10,22,13,49] -dissimilar;fraction;10;[1,2,3];CT2;[1,2,3,16,0,64,6,85,4,12] -dissimilar;fraction;10;medoid;CT3;[1,8,2,31,0,26,3,19,5,27] -dissimilar;fraction;10;outlier;CT3;[8,5,0,2,1,47,3,19,7,93] -dissimilar;fraction;10;[1,2,3];CT3;[1,2,3,78,0,41,4,85,6,64] -dissimilar;fraction;10;medoid;CT4;[23,78,0,26,1,58,2,8,3,48] -dissimilar;fraction;10;outlier;CT4;[34,85,0,2,1,41,3,20,4,64] -dissimilar;fraction;10;[1,2,3];CT4;[1,2,3,78,0,41,4,85,6,64] -dissimilar;fraction;10;medoid;Fai;[96,33,0,49,1,66,3,35,8,37] -dissimilar;fraction;10;outlier;Fai;[34,43,2,25,0,26,1,66,7,97] -dissimilar;fraction;10;[1,2,3];Fai;[1,2,3,16,0,64,6,85,4,12] -dissimilar;fraction;10;medoid;Gle;[69,13,0,27,1,66,2,19,3,31] -dissimilar;fraction;10;outlier;Gle;[34,85,0,2,1,41,3,20,4,64] -dissimilar;fraction;10;[1,2,3];Gle;[1,2,3,78,0,41,4,85,6,64] -dissimilar;fraction;10;medoid;Ja;[69,13,0,27,1,66,2,19,3,31] -dissimilar;fraction;10;outlier;Ja;[34,85,0,2,1,41,3,20,4,64] -dissimilar;fraction;10;[1,2,3];Ja;[1,2,3,78,0,41,4,85,6,64] -dissimilar;fraction;10;medoid;Ja0;[50,28,0,21,16,74,20,40,7,36] -dissimilar;fraction;10;outlier;Ja0;[49,9,7,66,0,35,2,25,3,76] -dissimilar;fraction;10;[1,2,3];Ja0;[1,2,3,16,0,64,6,85,4,12] -dissimilar;fraction;10;medoid;JT;[69,13,0,27,1,66,2,19,3,31] -dissimilar;fraction;10;outlier;JT;[34,85,0,2,1,41,3,20,4,64] -dissimilar;fraction;10;[1,2,3];JT;[1,2,3,78,0,41,4,85,6,64] -dissimilar;fraction;10;medoid;RT;[96,33,0,49,1,66,3,35,8,37] -dissimilar;fraction;10;outlier;RT;[4,42,8,17,5,19,10,22,13,49] -dissimilar;fraction;10;[1,2,3];RT;[1,2,3,16,0,64,6,85,4,12] -dissimilar;fraction;10;medoid;RR;[1,8,2,31,0,26,3,19,5,27] -dissimilar;fraction;10;outlier;RR;[8,5,0,2,1,47,3,19,7,93] -dissimilar;fraction;10;[1,2,3];RR;[1,2,3,78,0,41,4,85,6,64] -dissimilar;fraction;10;medoid;SM;[96,33,0,49,1,66,3,35,8,37] -dissimilar;fraction;10;outlier;SM;[4,42,8,17,5,19,10,22,13,49] -dissimilar;fraction;10;[1,2,3];SM;[1,2,3,16,0,64,6,85,4,12] -dissimilar;fraction;10;medoid;SS1;[23,78,0,26,1,58,2,8,3,48] -dissimilar;fraction;10;outlier;SS1;[34,85,0,2,1,41,3,20,4,64] -dissimilar;fraction;10;[1,2,3];SS1;[1,2,3,78,0,41,4,85,6,64] -dissimilar;fraction;10;medoid;SS2;[50,28,0,21,16,74,20,40,7,36] -dissimilar;fraction;10;outlier;SS2;[49,9,7,66,0,35,2,25,3,76] -dissimilar;fraction;10;[1,2,3];SS2;[1,2,3,16,0,64,6,85,4,12] -dissimilar;fraction;20;medoid;AC;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16] -dissimilar;fraction;20;outlier;AC;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76] -dissimilar;fraction;20;[1,2,3];AC;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] -dissimilar;fraction;20;medoid;BUB;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97] -dissimilar;fraction;20;outlier;BUB;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,49,10,28,12,40] -dissimilar;fraction;20;[1,2,3];BUB;[1,2,3,16,0,64,6,85,4,12,8,28,5,40,7,9,10,66,11,19] -dissimilar;fraction;20;medoid;CT1;[96,33,0,49,1,66,3,35,8,37,5,40,7,20,6,91,4,12,19,31] -dissimilar;fraction;20;outlier;CT1;[4,42,8,17,5,99,13,54,12,0,19,33,2,18,7,20,3,49,9,41] -dissimilar;fraction;20;[1,2,3];CT1;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,86,10,19] -dissimilar;fraction;20;medoid;CT2;[80,1,0,64,2,4,7,97,5,6,28,77,3,76,8,15,22,47,12,43] -dissimilar;fraction;20;outlier;CT2;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76] -dissimilar;fraction;20;[1,2,3];CT2;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] -dissimilar;fraction;20;medoid;CT3;[1,8,2,31,0,26,3,19,5,27,4,39,6,22,7,85,9,11,10,66] -dissimilar;fraction;20;outlier;CT3;[8,5,0,2,1,47,3,19,7,93,4,76,11,41,6,85,9,42,10,66] -dissimilar;fraction;20;[1,2,3];CT3;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] -dissimilar;fraction;20;medoid;CT4;[23,78,0,26,1,58,2,8,3,48,4,76,5,6,7,97,9,66,10,49] -dissimilar;fraction;20;outlier;CT4;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89] -dissimilar;fraction;20;[1,2,3];CT4;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] -dissimilar;fraction;20;medoid;Fai;[96,33,0,49,1,66,3,35,8,37,5,40,7,20,6,91,4,12,19,31] -dissimilar;fraction;20;outlier;Fai;[34,43,2,25,0,26,1,66,7,97,6,69,5,8,10,19,12,57,3,78] -dissimilar;fraction;20;[1,2,3];Fai;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,86,10,19] -dissimilar;fraction;20;medoid;Gle;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97] -dissimilar;fraction;20;outlier;Gle;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89] -dissimilar;fraction;20;[1,2,3];Gle;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] -dissimilar;fraction;20;medoid;Ja;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97] -dissimilar;fraction;20;outlier;Ja;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89] -dissimilar;fraction;20;[1,2,3];Ja;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] -dissimilar;fraction;20;medoid;Ja0;[50,28,0,21,16,74,20,40,7,36,4,49,8,17,5,54,1,86,3,6] -dissimilar;fraction;20;outlier;Ja0;[49,9,7,66,0,35,2,25,3,76,4,85,1,8,5,32,16,65,12,54] -dissimilar;fraction;20;[1,2,3];Ja0;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] -dissimilar;fraction;20;medoid;JT;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97] -dissimilar;fraction;20;outlier;JT;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89] -dissimilar;fraction;20;[1,2,3];JT;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] -dissimilar;fraction;20;medoid;RT;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16] -dissimilar;fraction;20;outlier;RT;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76] -dissimilar;fraction;20;[1,2,3];RT;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] -dissimilar;fraction;20;medoid;RR;[1,8,2,31,0,26,3,19,5,27,4,39,6,22,7,85,9,11,10,66] -dissimilar;fraction;20;outlier;RR;[8,5,0,2,1,47,3,19,7,93,4,76,11,41,6,85,9,42,10,66] -dissimilar;fraction;20;[1,2,3];RR;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] -dissimilar;fraction;20;medoid;SM;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16] -dissimilar;fraction;20;outlier;SM;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76] -dissimilar;fraction;20;[1,2,3];SM;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] -dissimilar;fraction;20;medoid;SS1;[23,78,0,26,1,58,2,8,3,48,4,76,5,6,7,97,9,66,10,49] -dissimilar;fraction;20;outlier;SS1;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89] -dissimilar;fraction;20;[1,2,3];SS1;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] -dissimilar;fraction;20;medoid;SS2;[50,28,0,21,16,74,20,40,7,36,4,49,8,17,5,54,1,86,3,6] -dissimilar;fraction;20;outlier;SS2;[49,9,7,66,0,35,2,25,3,76,4,85,1,8,5,32,16,65,12,54] -dissimilar;fraction;20;[1,2,3];SS2;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] -dissimilar;fraction;30;medoid;AC;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16,21,85,10,24,11,54,12,19,18,62] -dissimilar;fraction;30;outlier;AC;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76,27,54,6,31,15,91,18,44,7,80] -dissimilar;fraction;30;[1,2,3];AC;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] -dissimilar;fraction;30;medoid;BUB;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97,11,28,14,21,15,36,23,47,16,91] -dissimilar;fraction;30;outlier;BUB;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,49,10,28,12,40,14,66,19,44,11,48,13,22,15,91] -dissimilar;fraction;30;[1,2,3];BUB;[1,2,3,16,0,64,6,85,4,12,8,28,5,40,7,9,10,66,11,19,13,22,14,21,20,58,15,91,17,84] -dissimilar;fraction;30;medoid;CT1;[96,33,0,49,1,66,3,35,8,37,5,40,7,20,6,91,4,12,19,31,2,25,9,57,22,26,10,27,23,85] -dissimilar;fraction;30;outlier;CT1;[4,42,8,17,5,99,13,54,12,0,19,33,2,18,7,20,3,49,9,41,11,31,6,66,22,47,1,69,34,57] -dissimilar;fraction;30;[1,2,3];CT1;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,86,10,19,22,49,14,40,18,44,13,69,20,32] -dissimilar;fraction;30;medoid;CT2;[80,1,0,64,2,4,7,97,5,6,28,77,3,76,8,15,22,47,12,43,11,19,10,66,68,49,9,29,13,69] -dissimilar;fraction;30;outlier;CT2;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76,27,54,6,31,15,91,18,44,7,80] -dissimilar;fraction;30;[1,2,3];CT2;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] -dissimilar;fraction;30;medoid;CT3;[1,8,2,31,0,26,3,19,5,27,4,39,6,22,7,85,9,11,10,66,12,28,13,54,14,29,15,91,16,21] -dissimilar;fraction;30;outlier;CT3;[8,5,0,2,1,47,3,19,7,93,4,76,11,41,6,85,9,42,10,66,21,78,12,54,13,22,14,58,15,86] -dissimilar;fraction;30;[1,2,3];CT3;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,22] -dissimilar;fraction;30;medoid;CT4;[23,78,0,26,1,58,2,8,3,48,4,76,5,6,7,97,9,66,10,49,11,64,12,54,13,56,14,22,15,53] -dissimilar;fraction;30;outlier;CT4;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89,12,56,13,22,14,58,15,91,16,21] -dissimilar;fraction;30;[1,2,3];CT4;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,84] -dissimilar;fraction;30;medoid;Fai;[96,33,0,49,1,66,3,35,8,37,5,40,7,20,6,91,4,12,19,31,2,25,9,58,10,80,71,54,13,36] -dissimilar;fraction;30;outlier;Fai;[34,43,2,25,0,26,1,66,7,97,6,69,5,8,10,19,12,57,3,78,17,91,4,80,22,13,14,27,49,9] -dissimilar;fraction;30;[1,2,3];Fai;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,86,10,19,22,49,14,40,18,44,13,69,20,55] -dissimilar;fraction;30;medoid;Gle;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97,11,28,14,21,15,36,23,47,16,91] -dissimilar;fraction;30;outlier;Gle;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89,12,56,13,22,14,58,15,91,16,21] -dissimilar;fraction;30;[1,2,3];Gle;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,84] -dissimilar;fraction;30;medoid;Ja;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97,11,28,14,21,15,36,23,47,16,91] -dissimilar;fraction;30;outlier;Ja;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89,12,56,13,22,14,58,15,91,16,21] -dissimilar;fraction;30;[1,2,3];Ja;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,84] -dissimilar;fraction;30;medoid;Ja0;[50,28,0,21,16,74,20,40,7,36,4,49,8,17,5,54,1,86,3,6,22,57,19,42,9,33,14,24,2,84] -dissimilar;fraction;30;outlier;Ja0;[49,9,7,66,0,35,2,25,3,76,4,85,1,8,5,32,16,65,12,54,6,24,22,47,71,14,40,80,57,72] -dissimilar;fraction;30;[1,2,3];Ja0;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] -dissimilar;fraction;30;medoid;JT;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97,11,28,14,21,15,36,23,47,16,91] -dissimilar;fraction;30;outlier;JT;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89,12,56,13,22,14,58,15,91,16,21] -dissimilar;fraction;30;[1,2,3];JT;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,84] -dissimilar;fraction;30;medoid;RT;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16,21,85,10,24,11,54,12,19,18,62] -dissimilar;fraction;30;outlier;RT;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76,27,54,6,31,15,91,18,44,7,80] -dissimilar;fraction;30;[1,2,3];RT;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] -dissimilar;fraction;30;medoid;RR;[1,8,2,31,0,26,3,19,5,27,4,39,6,22,7,85,9,11,10,66,12,28,13,54,14,29,15,91,16,21] -dissimilar;fraction;30;outlier;RR;[8,5,0,2,1,47,3,19,7,93,4,76,11,41,6,85,9,42,10,66,21,78,12,54,13,22,14,58,15,86] -dissimilar;fraction;30;[1,2,3];RR;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,22] -dissimilar;fraction;30;medoid;SM;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16,21,85,10,24,11,54,12,19,18,62] -dissimilar;fraction;30;outlier;SM;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76,27,54,6,31,15,91,18,44,7,80] -dissimilar;fraction;30;[1,2,3];SM;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] -dissimilar;fraction;30;medoid;SS1;[23,78,0,26,1,58,2,8,3,48,4,76,5,6,7,97,9,66,10,49,11,64,12,54,13,56,14,22,15,53] -dissimilar;fraction;30;outlier;SS1;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89,12,56,13,22,14,58,15,91,16,21] -dissimilar;fraction;30;[1,2,3];SS1;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,84] -dissimilar;fraction;30;medoid;SS2;[50,28,0,21,16,74,20,40,7,36,4,49,8,17,5,54,1,86,3,6,22,57,19,42,9,33,14,24,2,84] -dissimilar;fraction;30;outlier;SS2;[49,9,7,66,0,35,2,25,3,76,4,85,1,8,5,32,16,65,12,54,6,24,22,47,71,14,40,80,57,72] -dissimilar;fraction;30;[1,2,3];SS2;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] -dissimilar;power_3;10;medoid;AC;[96,33,0,49,1,66,3,35,8,37] -dissimilar;power_3;10;outlier;AC;[4,42,8,17,5,19,10,22,13,49] -dissimilar;power_3;10;[1,2,3];AC;[1,2,3,16,0,64,6,85,4,12] -dissimilar;power_3;10;medoid;BUB;[69,13,0,27,1,66,2,19,3,31] -dissimilar;power_3;10;outlier;BUB;[34,85,0,2,1,41,3,20,4,64] -dissimilar;power_3;10;[1,2,3];BUB;[1,2,3,16,0,64,6,85,4,12] -dissimilar;power_3;10;medoid;CT1;[96,33,0,49,1,66,3,35,8,37] -dissimilar;power_3;10;outlier;CT1;[4,42,8,17,5,99,13,54,12,0] -dissimilar;power_3;10;[1,2,3];CT1;[1,2,3,16,0,64,6,85,4,12] -dissimilar;power_3;10;medoid;CT2;[80,1,0,64,2,4,7,97,5,6] -dissimilar;power_3;10;outlier;CT2;[4,42,8,17,5,19,10,22,13,49] -dissimilar;power_3;10;[1,2,3];CT2;[1,2,3,16,0,64,6,85,4,12] -dissimilar;power_3;10;medoid;CT3;[1,8,2,31,0,26,3,19,5,27] -dissimilar;power_3;10;outlier;CT3;[8,5,0,2,1,47,3,19,7,93] -dissimilar;power_3;10;[1,2,3];CT3;[1,2,3,78,0,41,4,85,6,64] -dissimilar;power_3;10;medoid;CT4;[23,78,0,26,1,58,2,8,3,48] -dissimilar;power_3;10;outlier;CT4;[34,85,0,2,1,41,3,20,4,64] -dissimilar;power_3;10;[1,2,3];CT4;[1,2,3,78,0,41,4,85,6,64] -dissimilar;power_3;10;medoid;Fai;[96,33,0,49,1,66,3,35,8,37] -dissimilar;power_3;10;outlier;Fai;[34,43,2,25,0,26,1,66,7,97] -dissimilar;power_3;10;[1,2,3];Fai;[1,2,3,16,0,64,6,85,4,12] -dissimilar;power_3;10;medoid;Gle;[69,13,0,27,1,66,2,19,3,31] -dissimilar;power_3;10;outlier;Gle;[34,85,0,2,1,41,3,20,4,64] -dissimilar;power_3;10;[1,2,3];Gle;[1,2,3,78,0,41,4,85,6,64] -dissimilar;power_3;10;medoid;Ja;[69,13,0,27,1,66,2,19,3,31] -dissimilar;power_3;10;outlier;Ja;[34,85,0,2,1,41,3,20,4,64] -dissimilar;power_3;10;[1,2,3];Ja;[1,2,3,78,0,41,4,85,6,64] -dissimilar;power_3;10;medoid;Ja0;[50,28,0,21,16,74,20,40,7,36] -dissimilar;power_3;10;outlier;Ja0;[49,9,7,66,0,35,2,25,3,76] -dissimilar;power_3;10;[1,2,3];Ja0;[1,2,3,16,0,64,6,85,4,12] -dissimilar;power_3;10;medoid;JT;[69,13,0,27,1,66,2,19,3,31] -dissimilar;power_3;10;outlier;JT;[34,85,0,2,1,41,3,20,4,64] -dissimilar;power_3;10;[1,2,3];JT;[1,2,3,78,0,41,4,85,6,64] -dissimilar;power_3;10;medoid;RT;[96,33,0,49,1,66,3,35,8,37] -dissimilar;power_3;10;outlier;RT;[4,42,8,17,5,19,10,22,13,49] -dissimilar;power_3;10;[1,2,3];RT;[1,2,3,16,0,64,6,85,4,12] -dissimilar;power_3;10;medoid;RR;[1,8,2,31,0,26,3,19,5,27] -dissimilar;power_3;10;outlier;RR;[8,5,0,2,1,47,3,19,7,93] -dissimilar;power_3;10;[1,2,3];RR;[1,2,3,78,0,41,4,85,6,64] -dissimilar;power_3;10;medoid;SM;[96,33,0,49,1,66,3,35,8,37] -dissimilar;power_3;10;outlier;SM;[4,42,8,17,5,19,10,22,13,49] -dissimilar;power_3;10;[1,2,3];SM;[1,2,3,16,0,64,6,85,4,12] -dissimilar;power_3;10;medoid;SS1;[23,78,0,26,1,58,2,8,3,48] -dissimilar;power_3;10;outlier;SS1;[34,85,0,2,1,41,3,20,4,64] -dissimilar;power_3;10;[1,2,3];SS1;[1,2,3,78,0,41,4,85,6,64] -dissimilar;power_3;10;medoid;SS2;[50,28,0,21,16,74,20,40,7,36] -dissimilar;power_3;10;outlier;SS2;[49,9,7,66,0,35,2,25,3,76] -dissimilar;power_3;10;[1,2,3];SS2;[1,2,3,16,0,64,6,85,4,12] -dissimilar;power_3;20;medoid;AC;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16] -dissimilar;power_3;20;outlier;AC;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76] -dissimilar;power_3;20;[1,2,3];AC;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] -dissimilar;power_3;20;medoid;BUB;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97] -dissimilar;power_3;20;outlier;BUB;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,49,10,28,12,40] -dissimilar;power_3;20;[1,2,3];BUB;[1,2,3,16,0,64,6,85,4,12,8,28,5,40,7,9,10,66,11,19] -dissimilar;power_3;20;medoid;CT1;[96,33,0,49,1,66,3,35,8,37,5,40,7,20,6,91,4,12,19,31] -dissimilar;power_3;20;outlier;CT1;[4,42,8,17,5,99,13,54,12,0,19,33,2,18,7,20,3,49,9,41] -dissimilar;power_3;20;[1,2,3];CT1;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,86,10,19] -dissimilar;power_3;20;medoid;CT2;[80,1,0,64,2,4,7,97,5,6,28,77,3,76,8,15,22,47,12,43] -dissimilar;power_3;20;outlier;CT2;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76] -dissimilar;power_3;20;[1,2,3];CT2;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] -dissimilar;power_3;20;medoid;CT3;[1,8,2,31,0,26,3,19,5,27,4,39,6,22,7,85,9,11,10,66] -dissimilar;power_3;20;outlier;CT3;[8,5,0,2,1,47,3,19,7,93,4,76,11,41,6,85,9,42,10,66] -dissimilar;power_3;20;[1,2,3];CT3;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] -dissimilar;power_3;20;medoid;CT4;[23,78,0,26,1,58,2,8,3,48,4,76,5,6,7,97,9,66,10,49] -dissimilar;power_3;20;outlier;CT4;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89] -dissimilar;power_3;20;[1,2,3];CT4;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] -dissimilar;power_3;20;medoid;Fai;[96,33,0,49,1,66,3,35,8,37,5,40,7,20,6,91,4,12,19,31] -dissimilar;power_3;20;outlier;Fai;[34,43,2,25,0,26,1,66,7,97,6,69,5,8,10,19,12,57,3,78] -dissimilar;power_3;20;[1,2,3];Fai;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,86,10,19] -dissimilar;power_3;20;medoid;Gle;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97] -dissimilar;power_3;20;outlier;Gle;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89] -dissimilar;power_3;20;[1,2,3];Gle;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] -dissimilar;power_3;20;medoid;Ja;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97] -dissimilar;power_3;20;outlier;Ja;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89] -dissimilar;power_3;20;[1,2,3];Ja;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] -dissimilar;power_3;20;medoid;Ja0;[50,28,0,21,16,74,20,40,7,36,4,49,8,17,5,54,1,86,3,6] -dissimilar;power_3;20;outlier;Ja0;[49,9,7,66,0,35,2,25,3,76,4,85,1,8,5,32,16,65,12,54] -dissimilar;power_3;20;[1,2,3];Ja0;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] -dissimilar;power_3;20;medoid;JT;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97] -dissimilar;power_3;20;outlier;JT;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89] -dissimilar;power_3;20;[1,2,3];JT;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] -dissimilar;power_3;20;medoid;RT;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16] -dissimilar;power_3;20;outlier;RT;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76] -dissimilar;power_3;20;[1,2,3];RT;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] -dissimilar;power_3;20;medoid;RR;[1,8,2,31,0,26,3,19,5,27,4,39,6,22,7,85,9,11,10,66] -dissimilar;power_3;20;outlier;RR;[8,5,0,2,1,47,3,19,7,93,4,76,11,41,6,85,9,42,10,66] -dissimilar;power_3;20;[1,2,3];RR;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] -dissimilar;power_3;20;medoid;SM;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16] -dissimilar;power_3;20;outlier;SM;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76] -dissimilar;power_3;20;[1,2,3];SM;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] -dissimilar;power_3;20;medoid;SS1;[23,78,0,26,1,58,2,8,3,48,4,76,5,6,7,97,9,66,10,49] -dissimilar;power_3;20;outlier;SS1;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89] -dissimilar;power_3;20;[1,2,3];SS1;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] -dissimilar;power_3;20;medoid;SS2;[50,28,0,21,16,74,20,40,7,36,4,49,8,17,5,54,1,86,3,6] -dissimilar;power_3;20;outlier;SS2;[49,9,7,66,0,35,2,25,3,76,4,85,1,8,5,32,16,65,12,54] -dissimilar;power_3;20;[1,2,3];SS2;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] -dissimilar;power_3;30;medoid;AC;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16,21,85,10,24,11,54,12,19,18,62] -dissimilar;power_3;30;outlier;AC;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76,27,54,6,31,15,91,18,44,7,80] -dissimilar;power_3;30;[1,2,3];AC;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] -dissimilar;power_3;30;medoid;BUB;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97,11,28,14,21,15,36,23,47,16,91] -dissimilar;power_3;30;outlier;BUB;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,49,10,28,12,40,14,66,19,44,11,48,13,22,15,91] -dissimilar;power_3;30;[1,2,3];BUB;[1,2,3,16,0,64,6,85,4,12,8,28,5,40,7,9,10,66,11,19,13,22,14,21,20,58,15,91,17,84] -dissimilar;power_3;30;medoid;CT1;[96,33,0,49,1,66,3,35,8,37,5,40,7,20,6,91,4,12,19,31,2,25,9,57,22,26,10,27,23,85] -dissimilar;power_3;30;outlier;CT1;[4,42,8,17,5,99,13,54,12,0,19,33,2,18,7,20,3,49,9,41,11,31,6,66,22,47,1,69,34,57] -dissimilar;power_3;30;[1,2,3];CT1;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,86,10,19,22,49,14,40,18,44,13,69,20,32] -dissimilar;power_3;30;medoid;CT2;[80,1,0,64,2,4,7,97,5,6,28,77,3,76,8,15,22,47,12,43,11,19,10,66,68,49,9,29,13,69] -dissimilar;power_3;30;outlier;CT2;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76,27,54,6,31,15,91,18,44,7,80] -dissimilar;power_3;30;[1,2,3];CT2;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] -dissimilar;power_3;30;medoid;CT3;[1,8,2,31,0,26,3,19,5,27,4,39,6,22,7,85,9,11,10,66,12,28,13,54,14,29,15,91,16,21] -dissimilar;power_3;30;outlier;CT3;[8,5,0,2,1,47,3,19,7,93,4,76,11,41,6,85,9,42,10,66,21,78,12,54,13,22,14,58,15,86] -dissimilar;power_3;30;[1,2,3];CT3;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,22] -dissimilar;power_3;30;medoid;CT4;[23,78,0,26,1,58,2,8,3,48,4,76,5,6,7,97,9,66,10,49,11,64,12,54,13,56,14,22,15,53] -dissimilar;power_3;30;outlier;CT4;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89,12,56,13,22,14,58,15,91,16,21] -dissimilar;power_3;30;[1,2,3];CT4;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,84] -dissimilar;power_3;30;medoid;Fai;[96,33,0,49,1,66,3,35,8,37,5,40,7,20,6,91,4,12,19,31,2,25,9,58,10,80,71,54,13,36] -dissimilar;power_3;30;outlier;Fai;[34,43,2,25,0,26,1,66,7,97,6,69,5,8,10,19,12,57,3,78,17,91,4,80,22,13,14,27,49,9] -dissimilar;power_3;30;[1,2,3];Fai;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,86,10,19,22,49,14,40,18,44,13,69,20,55] -dissimilar;power_3;30;medoid;Gle;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97,11,28,14,21,15,36,23,47,16,91] -dissimilar;power_3;30;outlier;Gle;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89,12,56,13,22,14,58,15,91,16,21] -dissimilar;power_3;30;[1,2,3];Gle;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,84] -dissimilar;power_3;30;medoid;Ja;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97,11,28,14,21,15,36,23,47,16,91] -dissimilar;power_3;30;outlier;Ja;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89,12,56,13,22,14,58,15,91,16,21] -dissimilar;power_3;30;[1,2,3];Ja;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,84] -dissimilar;power_3;30;medoid;Ja0;[50,28,0,21,16,74,20,40,7,36,4,49,8,17,5,54,1,86,3,6,22,57,19,42,9,33,14,24,2,84] -dissimilar;power_3;30;outlier;Ja0;[49,9,7,66,0,35,2,25,3,76,4,85,1,8,5,32,16,65,12,54,6,24,22,47,71,14,40,80,57,72] -dissimilar;power_3;30;[1,2,3];Ja0;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] -dissimilar;power_3;30;medoid;JT;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97,11,28,14,21,15,36,23,47,16,91] -dissimilar;power_3;30;outlier;JT;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89,12,56,13,22,14,58,15,91,16,21] -dissimilar;power_3;30;[1,2,3];JT;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,84] -dissimilar;power_3;30;medoid;RT;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16,21,85,10,24,11,54,12,19,18,62] -dissimilar;power_3;30;outlier;RT;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76,27,54,6,31,15,91,18,44,7,80] -dissimilar;power_3;30;[1,2,3];RT;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] -dissimilar;power_3;30;medoid;RR;[1,8,2,31,0,26,3,19,5,27,4,39,6,22,7,85,9,11,10,66,12,28,13,54,14,29,15,91,16,21] -dissimilar;power_3;30;outlier;RR;[8,5,0,2,1,47,3,19,7,93,4,76,11,41,6,85,9,42,10,66,21,78,12,54,13,22,14,58,15,86] -dissimilar;power_3;30;[1,2,3];RR;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,22] -dissimilar;power_3;30;medoid;SM;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16,21,85,10,24,11,54,12,19,18,62] -dissimilar;power_3;30;outlier;SM;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76,27,54,6,31,15,91,18,44,7,80] -dissimilar;power_3;30;[1,2,3];SM;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] -dissimilar;power_3;30;medoid;SS1;[23,78,0,26,1,58,2,8,3,48,4,76,5,6,7,97,9,66,10,49,11,64,12,54,13,56,14,22,15,53] -dissimilar;power_3;30;outlier;SS1;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89,12,56,13,22,14,58,15,91,16,21] -dissimilar;power_3;30;[1,2,3];SS1;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,84] -dissimilar;power_3;30;medoid;SS2;[50,28,0,21,16,74,20,40,7,36,4,49,8,17,5,54,1,86,3,6,22,57,19,42,9,33,14,24,2,84] -dissimilar;power_3;30;outlier;SS2;[49,9,7,66,0,35,2,25,3,76,4,85,1,8,5,32,16,65,12,54,6,24,22,47,71,14,40,80,57,72] -dissimilar;power_3;30;[1,2,3];SS2;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] +c_threshold;w_factor;sample_size;start_idx;n_ary;result +None;fraction;10;medoid;AC;[96,33,0,49,1,66,3,35,8,37] +None;fraction;10;outlier;AC;[4,42,8,17,5,19,10,22,13,49] +None;fraction;10;[1,2,3];AC;[1,2,3,16,0,64,6,85,4,12] +None;fraction;10;medoid;BUB;[69,13,0,27,1,66,2,19,3,31] +None;fraction;10;outlier;BUB;[34,85,0,2,1,41,3,20,4,64] +None;fraction;10;[1,2,3];BUB;[1,2,3,16,0,64,6,85,4,12] +None;fraction;10;medoid;CT1;[96,33,0,49,1,66,3,35,8,37] +None;fraction;10;outlier;CT1;[4,42,8,17,5,99,13,54,12,0] +None;fraction;10;[1,2,3];CT1;[1,2,3,16,0,64,6,85,4,12] +None;fraction;10;medoid;CT2;[80,1,0,64,2,4,7,97,5,6] +None;fraction;10;outlier;CT2;[4,42,8,17,5,19,10,22,13,49] +None;fraction;10;[1,2,3];CT2;[1,2,3,16,0,64,6,85,4,12] +None;fraction;10;medoid;CT3;[1,8,2,31,0,26,3,19,5,27] +None;fraction;10;outlier;CT3;[8,5,0,2,1,47,3,19,7,93] +None;fraction;10;[1,2,3];CT3;[1,2,3,78,0,41,4,85,6,64] +None;fraction;10;medoid;CT4;[23,78,0,26,1,58,2,8,3,48] +None;fraction;10;outlier;CT4;[34,85,0,2,1,41,3,20,4,64] +None;fraction;10;[1,2,3];CT4;[1,2,3,78,0,41,4,85,6,64] +None;fraction;10;medoid;Fai;[96,33,0,49,1,66,3,35,8,37] +None;fraction;10;outlier;Fai;[34,43,2,25,0,26,1,66,7,97] +None;fraction;10;[1,2,3];Fai;[1,2,3,16,0,64,6,85,4,12] +None;fraction;10;medoid;Gle;[69,13,0,27,1,66,2,19,3,31] +None;fraction;10;outlier;Gle;[34,85,0,2,1,41,3,20,4,64] +None;fraction;10;[1,2,3];Gle;[1,2,3,78,0,41,4,85,6,64] +None;fraction;10;medoid;Ja;[69,13,0,27,1,66,2,19,3,31] +None;fraction;10;outlier;Ja;[34,85,0,2,1,41,3,20,4,64] +None;fraction;10;[1,2,3];Ja;[1,2,3,78,0,41,4,85,6,64] +None;fraction;10;medoid;Ja0;[50,28,0,21,16,74,20,40,7,36] +None;fraction;10;outlier;Ja0;[49,9,7,66,0,35,2,25,3,76] +None;fraction;10;[1,2,3];Ja0;[1,2,3,16,0,64,6,85,4,12] +None;fraction;10;medoid;JT;[69,13,0,27,1,66,2,19,3,31] +None;fraction;10;outlier;JT;[34,85,0,2,1,41,3,20,4,64] +None;fraction;10;[1,2,3];JT;[1,2,3,78,0,41,4,85,6,64] +None;fraction;10;medoid;RT;[96,33,0,49,1,66,3,35,8,37] +None;fraction;10;outlier;RT;[4,42,8,17,5,19,10,22,13,49] +None;fraction;10;[1,2,3];RT;[1,2,3,16,0,64,6,85,4,12] +None;fraction;10;medoid;RR;[1,8,2,31,0,26,3,19,5,27] +None;fraction;10;outlier;RR;[8,5,0,2,1,47,3,19,7,93] +None;fraction;10;[1,2,3];RR;[1,2,3,78,0,41,4,85,6,64] +None;fraction;10;medoid;SM;[96,33,0,49,1,66,3,35,8,37] +None;fraction;10;outlier;SM;[4,42,8,17,5,19,10,22,13,49] +None;fraction;10;[1,2,3];SM;[1,2,3,16,0,64,6,85,4,12] +None;fraction;10;medoid;SS1;[23,78,0,26,1,58,2,8,3,48] +None;fraction;10;outlier;SS1;[34,85,0,2,1,41,3,20,4,64] +None;fraction;10;[1,2,3];SS1;[1,2,3,78,0,41,4,85,6,64] +None;fraction;10;medoid;SS2;[50,28,0,21,16,74,20,40,7,36] +None;fraction;10;outlier;SS2;[49,9,7,66,0,35,2,25,3,76] +None;fraction;10;[1,2,3];SS2;[1,2,3,16,0,64,6,85,4,12] +None;fraction;20;medoid;AC;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16] +None;fraction;20;outlier;AC;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76] +None;fraction;20;[1,2,3];AC;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] +None;fraction;20;medoid;BUB;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97] +None;fraction;20;outlier;BUB;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,49,10,28,12,40] +None;fraction;20;[1,2,3];BUB;[1,2,3,16,0,64,6,85,4,12,8,28,5,40,7,9,10,66,11,19] +None;fraction;20;medoid;CT1;[96,33,0,49,1,66,3,35,8,37,5,40,7,20,6,91,4,12,19,31] +None;fraction;20;outlier;CT1;[4,42,8,17,5,99,13,54,12,0,19,33,2,18,7,20,3,49,9,41] +None;fraction;20;[1,2,3];CT1;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,86,10,19] +None;fraction;20;medoid;CT2;[80,1,0,64,2,4,7,97,5,6,28,77,3,76,8,15,22,47,12,43] +None;fraction;20;outlier;CT2;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76] +None;fraction;20;[1,2,3];CT2;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] +None;fraction;20;medoid;CT3;[1,8,2,31,0,26,3,19,5,27,4,39,6,22,7,85,9,11,10,66] +None;fraction;20;outlier;CT3;[8,5,0,2,1,47,3,19,7,93,4,76,11,41,6,85,9,42,10,66] +None;fraction;20;[1,2,3];CT3;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] +None;fraction;20;medoid;CT4;[23,78,0,26,1,58,2,8,3,48,4,76,5,6,7,97,9,66,10,49] +None;fraction;20;outlier;CT4;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89] +None;fraction;20;[1,2,3];CT4;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] +None;fraction;20;medoid;Fai;[96,33,0,49,1,66,3,35,8,37,5,40,7,20,6,91,4,12,19,31] +None;fraction;20;outlier;Fai;[34,43,2,25,0,26,1,66,7,97,6,69,5,8,10,19,12,57,3,78] +None;fraction;20;[1,2,3];Fai;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,86,10,19] +None;fraction;20;medoid;Gle;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97] +None;fraction;20;outlier;Gle;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89] +None;fraction;20;[1,2,3];Gle;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] +None;fraction;20;medoid;Ja;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97] +None;fraction;20;outlier;Ja;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89] +None;fraction;20;[1,2,3];Ja;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] +None;fraction;20;medoid;Ja0;[50,28,0,21,16,74,20,40,7,36,4,49,8,17,5,54,1,86,3,6] +None;fraction;20;outlier;Ja0;[49,9,7,66,0,35,2,25,3,76,4,85,1,8,5,32,16,65,12,54] +None;fraction;20;[1,2,3];Ja0;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] +None;fraction;20;medoid;JT;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97] +None;fraction;20;outlier;JT;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89] +None;fraction;20;[1,2,3];JT;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] +None;fraction;20;medoid;RT;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16] +None;fraction;20;outlier;RT;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76] +None;fraction;20;[1,2,3];RT;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] +None;fraction;20;medoid;RR;[1,8,2,31,0,26,3,19,5,27,4,39,6,22,7,85,9,11,10,66] +None;fraction;20;outlier;RR;[8,5,0,2,1,47,3,19,7,93,4,76,11,41,6,85,9,42,10,66] +None;fraction;20;[1,2,3];RR;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] +None;fraction;20;medoid;SM;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16] +None;fraction;20;outlier;SM;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76] +None;fraction;20;[1,2,3];SM;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] +None;fraction;20;medoid;SS1;[23,78,0,26,1,58,2,8,3,48,4,76,5,6,7,97,9,66,10,49] +None;fraction;20;outlier;SS1;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89] +None;fraction;20;[1,2,3];SS1;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] +None;fraction;20;medoid;SS2;[50,28,0,21,16,74,20,40,7,36,4,49,8,17,5,54,1,86,3,6] +None;fraction;20;outlier;SS2;[49,9,7,66,0,35,2,25,3,76,4,85,1,8,5,32,16,65,12,54] +None;fraction;20;[1,2,3];SS2;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] +None;fraction;30;medoid;AC;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16,21,85,10,24,11,54,12,19,18,62] +None;fraction;30;outlier;AC;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76,27,54,6,31,15,91,18,44,7,80] +None;fraction;30;[1,2,3];AC;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] +None;fraction;30;medoid;BUB;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97,11,28,14,21,15,36,23,47,16,91] +None;fraction;30;outlier;BUB;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,49,10,28,12,40,14,66,19,44,11,48,13,22,15,91] +None;fraction;30;[1,2,3];BUB;[1,2,3,16,0,64,6,85,4,12,8,28,5,40,7,9,10,66,11,19,13,22,14,21,20,58,15,91,17,84] +None;fraction;30;medoid;CT1;[96,33,0,49,1,66,3,35,8,37,5,40,7,20,6,91,4,12,19,31,2,25,9,57,22,26,10,27,23,85] +None;fraction;30;outlier;CT1;[4,42,8,17,5,99,13,54,12,0,19,33,2,18,7,20,3,49,9,41,11,31,6,66,22,47,1,69,34,57] +None;fraction;30;[1,2,3];CT1;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,86,10,19,22,49,14,40,18,44,13,69,20,32] +None;fraction;30;medoid;CT2;[80,1,0,64,2,4,7,97,5,6,28,77,3,76,8,15,22,47,12,43,11,19,10,66,68,49,9,29,13,69] +None;fraction;30;outlier;CT2;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76,27,54,6,31,15,91,18,44,7,80] +None;fraction;30;[1,2,3];CT2;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] +None;fraction;30;medoid;CT3;[1,8,2,31,0,26,3,19,5,27,4,39,6,22,7,85,9,11,10,66,12,28,13,54,14,29,15,91,16,21] +None;fraction;30;outlier;CT3;[8,5,0,2,1,47,3,19,7,93,4,76,11,41,6,85,9,42,10,66,21,78,12,54,13,22,14,58,15,86] +None;fraction;30;[1,2,3];CT3;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,22] +None;fraction;30;medoid;CT4;[23,78,0,26,1,58,2,8,3,48,4,76,5,6,7,97,9,66,10,49,11,64,12,54,13,56,14,22,15,53] +None;fraction;30;outlier;CT4;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89,12,56,13,22,14,58,15,91,16,21] +None;fraction;30;[1,2,3];CT4;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,84] +None;fraction;30;medoid;Fai;[96,33,0,49,1,66,3,35,8,37,5,40,7,20,6,91,4,12,19,31,2,25,9,58,10,80,71,54,13,36] +None;fraction;30;outlier;Fai;[34,43,2,25,0,26,1,66,7,97,6,69,5,8,10,19,12,57,3,78,17,91,4,80,22,13,14,27,49,9] +None;fraction;30;[1,2,3];Fai;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,86,10,19,22,49,14,40,18,44,13,69,20,55] +None;fraction;30;medoid;Gle;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97,11,28,14,21,15,36,23,47,16,91] +None;fraction;30;outlier;Gle;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89,12,56,13,22,14,58,15,91,16,21] +None;fraction;30;[1,2,3];Gle;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,84] +None;fraction;30;medoid;Ja;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97,11,28,14,21,15,36,23,47,16,91] +None;fraction;30;outlier;Ja;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89,12,56,13,22,14,58,15,91,16,21] +None;fraction;30;[1,2,3];Ja;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,84] +None;fraction;30;medoid;Ja0;[50,28,0,21,16,74,20,40,7,36,4,49,8,17,5,54,1,86,3,6,22,57,19,42,9,33,14,24,2,84] +None;fraction;30;outlier;Ja0;[49,9,7,66,0,35,2,25,3,76,4,85,1,8,5,32,16,65,12,54,6,24,22,47,71,14,40,80,57,72] +None;fraction;30;[1,2,3];Ja0;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] +None;fraction;30;medoid;JT;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97,11,28,14,21,15,36,23,47,16,91] +None;fraction;30;outlier;JT;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89,12,56,13,22,14,58,15,91,16,21] +None;fraction;30;[1,2,3];JT;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,84] +None;fraction;30;medoid;RT;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16,21,85,10,24,11,54,12,19,18,62] +None;fraction;30;outlier;RT;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76,27,54,6,31,15,91,18,44,7,80] +None;fraction;30;[1,2,3];RT;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] +None;fraction;30;medoid;RR;[1,8,2,31,0,26,3,19,5,27,4,39,6,22,7,85,9,11,10,66,12,28,13,54,14,29,15,91,16,21] +None;fraction;30;outlier;RR;[8,5,0,2,1,47,3,19,7,93,4,76,11,41,6,85,9,42,10,66,21,78,12,54,13,22,14,58,15,86] +None;fraction;30;[1,2,3];RR;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,22] +None;fraction;30;medoid;SM;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16,21,85,10,24,11,54,12,19,18,62] +None;fraction;30;outlier;SM;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76,27,54,6,31,15,91,18,44,7,80] +None;fraction;30;[1,2,3];SM;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] +None;fraction;30;medoid;SS1;[23,78,0,26,1,58,2,8,3,48,4,76,5,6,7,97,9,66,10,49,11,64,12,54,13,56,14,22,15,53] +None;fraction;30;outlier;SS1;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89,12,56,13,22,14,58,15,91,16,21] +None;fraction;30;[1,2,3];SS1;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,84] +None;fraction;30;medoid;SS2;[50,28,0,21,16,74,20,40,7,36,4,49,8,17,5,54,1,86,3,6,22,57,19,42,9,33,14,24,2,84] +None;fraction;30;outlier;SS2;[49,9,7,66,0,35,2,25,3,76,4,85,1,8,5,32,16,65,12,54,6,24,22,47,71,14,40,80,57,72] +None;fraction;30;[1,2,3];SS2;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] +None;power_3;10;medoid;AC;[96,33,0,49,1,66,3,35,8,37] +None;power_3;10;outlier;AC;[4,42,8,17,5,19,10,22,13,49] +None;power_3;10;[1,2,3];AC;[1,2,3,16,0,64,6,85,4,12] +None;power_3;10;medoid;BUB;[69,13,0,27,1,66,2,19,3,31] +None;power_3;10;outlier;BUB;[34,85,0,2,1,41,3,20,4,64] +None;power_3;10;[1,2,3];BUB;[1,2,3,16,0,64,6,85,4,12] +None;power_3;10;medoid;CT1;[96,33,0,49,1,66,3,35,8,37] +None;power_3;10;outlier;CT1;[4,42,8,17,5,99,13,54,12,0] +None;power_3;10;[1,2,3];CT1;[1,2,3,16,0,64,6,85,4,12] +None;power_3;10;medoid;CT2;[80,1,0,64,2,4,7,97,5,6] +None;power_3;10;outlier;CT2;[4,42,8,17,5,19,10,22,13,49] +None;power_3;10;[1,2,3];CT2;[1,2,3,16,0,64,6,85,4,12] +None;power_3;10;medoid;CT3;[1,8,2,31,0,26,3,19,5,27] +None;power_3;10;outlier;CT3;[8,5,0,2,1,47,3,19,7,93] +None;power_3;10;[1,2,3];CT3;[1,2,3,78,0,41,4,85,6,64] +None;power_3;10;medoid;CT4;[23,78,0,26,1,58,2,8,3,48] +None;power_3;10;outlier;CT4;[34,85,0,2,1,41,3,20,4,64] +None;power_3;10;[1,2,3];CT4;[1,2,3,78,0,41,4,85,6,64] +None;power_3;10;medoid;Fai;[96,33,0,49,1,66,3,35,8,37] +None;power_3;10;outlier;Fai;[34,43,2,25,0,26,1,66,7,97] +None;power_3;10;[1,2,3];Fai;[1,2,3,16,0,64,6,85,4,12] +None;power_3;10;medoid;Gle;[69,13,0,27,1,66,2,19,3,31] +None;power_3;10;outlier;Gle;[34,85,0,2,1,41,3,20,4,64] +None;power_3;10;[1,2,3];Gle;[1,2,3,78,0,41,4,85,6,64] +None;power_3;10;medoid;Ja;[69,13,0,27,1,66,2,19,3,31] +None;power_3;10;outlier;Ja;[34,85,0,2,1,41,3,20,4,64] +None;power_3;10;[1,2,3];Ja;[1,2,3,78,0,41,4,85,6,64] +None;power_3;10;medoid;Ja0;[50,28,0,21,16,74,20,40,7,36] +None;power_3;10;outlier;Ja0;[49,9,7,66,0,35,2,25,3,76] +None;power_3;10;[1,2,3];Ja0;[1,2,3,16,0,64,6,85,4,12] +None;power_3;10;medoid;JT;[69,13,0,27,1,66,2,19,3,31] +None;power_3;10;outlier;JT;[34,85,0,2,1,41,3,20,4,64] +None;power_3;10;[1,2,3];JT;[1,2,3,78,0,41,4,85,6,64] +None;power_3;10;medoid;RT;[96,33,0,49,1,66,3,35,8,37] +None;power_3;10;outlier;RT;[4,42,8,17,5,19,10,22,13,49] +None;power_3;10;[1,2,3];RT;[1,2,3,16,0,64,6,85,4,12] +None;power_3;10;medoid;RR;[1,8,2,31,0,26,3,19,5,27] +None;power_3;10;outlier;RR;[8,5,0,2,1,47,3,19,7,93] +None;power_3;10;[1,2,3];RR;[1,2,3,78,0,41,4,85,6,64] +None;power_3;10;medoid;SM;[96,33,0,49,1,66,3,35,8,37] +None;power_3;10;outlier;SM;[4,42,8,17,5,19,10,22,13,49] +None;power_3;10;[1,2,3];SM;[1,2,3,16,0,64,6,85,4,12] +None;power_3;10;medoid;SS1;[23,78,0,26,1,58,2,8,3,48] +None;power_3;10;outlier;SS1;[34,85,0,2,1,41,3,20,4,64] +None;power_3;10;[1,2,3];SS1;[1,2,3,78,0,41,4,85,6,64] +None;power_3;10;medoid;SS2;[50,28,0,21,16,74,20,40,7,36] +None;power_3;10;outlier;SS2;[49,9,7,66,0,35,2,25,3,76] +None;power_3;10;[1,2,3];SS2;[1,2,3,16,0,64,6,85,4,12] +None;power_3;20;medoid;AC;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16] +None;power_3;20;outlier;AC;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76] +None;power_3;20;[1,2,3];AC;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] +None;power_3;20;medoid;BUB;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97] +None;power_3;20;outlier;BUB;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,49,10,28,12,40] +None;power_3;20;[1,2,3];BUB;[1,2,3,16,0,64,6,85,4,12,8,28,5,40,7,9,10,66,11,19] +None;power_3;20;medoid;CT1;[96,33,0,49,1,66,3,35,8,37,5,40,7,20,6,91,4,12,19,31] +None;power_3;20;outlier;CT1;[4,42,8,17,5,99,13,54,12,0,19,33,2,18,7,20,3,49,9,41] +None;power_3;20;[1,2,3];CT1;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,86,10,19] +None;power_3;20;medoid;CT2;[80,1,0,64,2,4,7,97,5,6,28,77,3,76,8,15,22,47,12,43] +None;power_3;20;outlier;CT2;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76] +None;power_3;20;[1,2,3];CT2;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] +None;power_3;20;medoid;CT3;[1,8,2,31,0,26,3,19,5,27,4,39,6,22,7,85,9,11,10,66] +None;power_3;20;outlier;CT3;[8,5,0,2,1,47,3,19,7,93,4,76,11,41,6,85,9,42,10,66] +None;power_3;20;[1,2,3];CT3;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] +None;power_3;20;medoid;CT4;[23,78,0,26,1,58,2,8,3,48,4,76,5,6,7,97,9,66,10,49] +None;power_3;20;outlier;CT4;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89] +None;power_3;20;[1,2,3];CT4;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] +None;power_3;20;medoid;Fai;[96,33,0,49,1,66,3,35,8,37,5,40,7,20,6,91,4,12,19,31] +None;power_3;20;outlier;Fai;[34,43,2,25,0,26,1,66,7,97,6,69,5,8,10,19,12,57,3,78] +None;power_3;20;[1,2,3];Fai;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,86,10,19] +None;power_3;20;medoid;Gle;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97] +None;power_3;20;outlier;Gle;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89] +None;power_3;20;[1,2,3];Gle;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] +None;power_3;20;medoid;Ja;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97] +None;power_3;20;outlier;Ja;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89] +None;power_3;20;[1,2,3];Ja;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] +None;power_3;20;medoid;Ja0;[50,28,0,21,16,74,20,40,7,36,4,49,8,17,5,54,1,86,3,6] +None;power_3;20;outlier;Ja0;[49,9,7,66,0,35,2,25,3,76,4,85,1,8,5,32,16,65,12,54] +None;power_3;20;[1,2,3];Ja0;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] +None;power_3;20;medoid;JT;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97] +None;power_3;20;outlier;JT;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89] +None;power_3;20;[1,2,3];JT;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] +None;power_3;20;medoid;RT;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16] +None;power_3;20;outlier;RT;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76] +None;power_3;20;[1,2,3];RT;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] +None;power_3;20;medoid;RR;[1,8,2,31,0,26,3,19,5,27,4,39,6,22,7,85,9,11,10,66] +None;power_3;20;outlier;RR;[8,5,0,2,1,47,3,19,7,93,4,76,11,41,6,85,9,42,10,66] +None;power_3;20;[1,2,3];RR;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] +None;power_3;20;medoid;SM;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16] +None;power_3;20;outlier;SM;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76] +None;power_3;20;[1,2,3];SM;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] +None;power_3;20;medoid;SS1;[23,78,0,26,1,58,2,8,3,48,4,76,5,6,7,97,9,66,10,49] +None;power_3;20;outlier;SS1;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89] +None;power_3;20;[1,2,3];SS1;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] +None;power_3;20;medoid;SS2;[50,28,0,21,16,74,20,40,7,36,4,49,8,17,5,54,1,86,3,6] +None;power_3;20;outlier;SS2;[49,9,7,66,0,35,2,25,3,76,4,85,1,8,5,32,16,65,12,54] +None;power_3;20;[1,2,3];SS2;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] +None;power_3;30;medoid;AC;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16,21,85,10,24,11,54,12,19,18,62] +None;power_3;30;outlier;AC;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76,27,54,6,31,15,91,18,44,7,80] +None;power_3;30;[1,2,3];AC;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] +None;power_3;30;medoid;BUB;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97,11,28,14,21,15,36,23,47,16,91] +None;power_3;30;outlier;BUB;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,49,10,28,12,40,14,66,19,44,11,48,13,22,15,91] +None;power_3;30;[1,2,3];BUB;[1,2,3,16,0,64,6,85,4,12,8,28,5,40,7,9,10,66,11,19,13,22,14,21,20,58,15,91,17,84] +None;power_3;30;medoid;CT1;[96,33,0,49,1,66,3,35,8,37,5,40,7,20,6,91,4,12,19,31,2,25,9,57,22,26,10,27,23,85] +None;power_3;30;outlier;CT1;[4,42,8,17,5,99,13,54,12,0,19,33,2,18,7,20,3,49,9,41,11,31,6,66,22,47,1,69,34,57] +None;power_3;30;[1,2,3];CT1;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,86,10,19,22,49,14,40,18,44,13,69,20,32] +None;power_3;30;medoid;CT2;[80,1,0,64,2,4,7,97,5,6,28,77,3,76,8,15,22,47,12,43,11,19,10,66,68,49,9,29,13,69] +None;power_3;30;outlier;CT2;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76,27,54,6,31,15,91,18,44,7,80] +None;power_3;30;[1,2,3];CT2;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] +None;power_3;30;medoid;CT3;[1,8,2,31,0,26,3,19,5,27,4,39,6,22,7,85,9,11,10,66,12,28,13,54,14,29,15,91,16,21] +None;power_3;30;outlier;CT3;[8,5,0,2,1,47,3,19,7,93,4,76,11,41,6,85,9,42,10,66,21,78,12,54,13,22,14,58,15,86] +None;power_3;30;[1,2,3];CT3;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,22] +None;power_3;30;medoid;CT4;[23,78,0,26,1,58,2,8,3,48,4,76,5,6,7,97,9,66,10,49,11,64,12,54,13,56,14,22,15,53] +None;power_3;30;outlier;CT4;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89,12,56,13,22,14,58,15,91,16,21] +None;power_3;30;[1,2,3];CT4;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,84] +None;power_3;30;medoid;Fai;[96,33,0,49,1,66,3,35,8,37,5,40,7,20,6,91,4,12,19,31,2,25,9,58,10,80,71,54,13,36] +None;power_3;30;outlier;Fai;[34,43,2,25,0,26,1,66,7,97,6,69,5,8,10,19,12,57,3,78,17,91,4,80,22,13,14,27,49,9] +None;power_3;30;[1,2,3];Fai;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,86,10,19,22,49,14,40,18,44,13,69,20,55] +None;power_3;30;medoid;Gle;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97,11,28,14,21,15,36,23,47,16,91] +None;power_3;30;outlier;Gle;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89,12,56,13,22,14,58,15,91,16,21] +None;power_3;30;[1,2,3];Gle;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,84] +None;power_3;30;medoid;Ja;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97,11,28,14,21,15,36,23,47,16,91] +None;power_3;30;outlier;Ja;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89,12,56,13,22,14,58,15,91,16,21] +None;power_3;30;[1,2,3];Ja;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,84] +None;power_3;30;medoid;Ja0;[50,28,0,21,16,74,20,40,7,36,4,49,8,17,5,54,1,86,3,6,22,57,19,42,9,33,14,24,2,84] +None;power_3;30;outlier;Ja0;[49,9,7,66,0,35,2,25,3,76,4,85,1,8,5,32,16,65,12,54,6,24,22,47,71,14,40,80,57,72] +None;power_3;30;[1,2,3];Ja0;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] +None;power_3;30;medoid;JT;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97,11,28,14,21,15,36,23,47,16,91] +None;power_3;30;outlier;JT;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89,12,56,13,22,14,58,15,91,16,21] +None;power_3;30;[1,2,3];JT;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,84] +None;power_3;30;medoid;RT;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16,21,85,10,24,11,54,12,19,18,62] +None;power_3;30;outlier;RT;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76,27,54,6,31,15,91,18,44,7,80] +None;power_3;30;[1,2,3];RT;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] +None;power_3;30;medoid;RR;[1,8,2,31,0,26,3,19,5,27,4,39,6,22,7,85,9,11,10,66,12,28,13,54,14,29,15,91,16,21] +None;power_3;30;outlier;RR;[8,5,0,2,1,47,3,19,7,93,4,76,11,41,6,85,9,42,10,66,21,78,12,54,13,22,14,58,15,86] +None;power_3;30;[1,2,3];RR;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,22] +None;power_3;30;medoid;SM;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16,21,85,10,24,11,54,12,19,18,62] +None;power_3;30;outlier;SM;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76,27,54,6,31,15,91,18,44,7,80] +None;power_3;30;[1,2,3];SM;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] +None;power_3;30;medoid;SS1;[23,78,0,26,1,58,2,8,3,48,4,76,5,6,7,97,9,66,10,49,11,64,12,54,13,56,14,22,15,53] +None;power_3;30;outlier;SS1;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89,12,56,13,22,14,58,15,91,16,21] +None;power_3;30;[1,2,3];SS1;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,84] +None;power_3;30;medoid;SS2;[50,28,0,21,16,74,20,40,7,36,4,49,8,17,5,54,1,86,3,6,22,57,19,42,9,33,14,24,2,84] +None;power_3;30;outlier;SS2;[49,9,7,66,0,35,2,25,3,76,4,85,1,8,5,32,16,65,12,54,6,24,22,47,71,14,40,80,57,72] +None;power_3;30;[1,2,3];SS2;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] +dissimilar;fraction;10;medoid;AC;[96,33,0,49,1,66,3,35,8,37] +dissimilar;fraction;10;outlier;AC;[4,42,8,17,5,19,10,22,13,49] +dissimilar;fraction;10;[1,2,3];AC;[1,2,3,16,0,64,6,85,4,12] +dissimilar;fraction;10;medoid;BUB;[69,13,0,27,1,66,2,19,3,31] +dissimilar;fraction;10;outlier;BUB;[34,85,0,2,1,41,3,20,4,64] +dissimilar;fraction;10;[1,2,3];BUB;[1,2,3,16,0,64,6,85,4,12] +dissimilar;fraction;10;medoid;CT1;[96,33,0,49,1,66,3,35,8,37] +dissimilar;fraction;10;outlier;CT1;[4,42,8,17,5,99,13,54,12,0] +dissimilar;fraction;10;[1,2,3];CT1;[1,2,3,16,0,64,6,85,4,12] +dissimilar;fraction;10;medoid;CT2;[80,1,0,64,2,4,7,97,5,6] +dissimilar;fraction;10;outlier;CT2;[4,42,8,17,5,19,10,22,13,49] +dissimilar;fraction;10;[1,2,3];CT2;[1,2,3,16,0,64,6,85,4,12] +dissimilar;fraction;10;medoid;CT3;[1,8,2,31,0,26,3,19,5,27] +dissimilar;fraction;10;outlier;CT3;[8,5,0,2,1,47,3,19,7,93] +dissimilar;fraction;10;[1,2,3];CT3;[1,2,3,78,0,41,4,85,6,64] +dissimilar;fraction;10;medoid;CT4;[23,78,0,26,1,58,2,8,3,48] +dissimilar;fraction;10;outlier;CT4;[34,85,0,2,1,41,3,20,4,64] +dissimilar;fraction;10;[1,2,3];CT4;[1,2,3,78,0,41,4,85,6,64] +dissimilar;fraction;10;medoid;Fai;[96,33,0,49,1,66,3,35,8,37] +dissimilar;fraction;10;outlier;Fai;[34,43,2,25,0,26,1,66,7,97] +dissimilar;fraction;10;[1,2,3];Fai;[1,2,3,16,0,64,6,85,4,12] +dissimilar;fraction;10;medoid;Gle;[69,13,0,27,1,66,2,19,3,31] +dissimilar;fraction;10;outlier;Gle;[34,85,0,2,1,41,3,20,4,64] +dissimilar;fraction;10;[1,2,3];Gle;[1,2,3,78,0,41,4,85,6,64] +dissimilar;fraction;10;medoid;Ja;[69,13,0,27,1,66,2,19,3,31] +dissimilar;fraction;10;outlier;Ja;[34,85,0,2,1,41,3,20,4,64] +dissimilar;fraction;10;[1,2,3];Ja;[1,2,3,78,0,41,4,85,6,64] +dissimilar;fraction;10;medoid;Ja0;[50,28,0,21,16,74,20,40,7,36] +dissimilar;fraction;10;outlier;Ja0;[49,9,7,66,0,35,2,25,3,76] +dissimilar;fraction;10;[1,2,3];Ja0;[1,2,3,16,0,64,6,85,4,12] +dissimilar;fraction;10;medoid;JT;[69,13,0,27,1,66,2,19,3,31] +dissimilar;fraction;10;outlier;JT;[34,85,0,2,1,41,3,20,4,64] +dissimilar;fraction;10;[1,2,3];JT;[1,2,3,78,0,41,4,85,6,64] +dissimilar;fraction;10;medoid;RT;[96,33,0,49,1,66,3,35,8,37] +dissimilar;fraction;10;outlier;RT;[4,42,8,17,5,19,10,22,13,49] +dissimilar;fraction;10;[1,2,3];RT;[1,2,3,16,0,64,6,85,4,12] +dissimilar;fraction;10;medoid;RR;[1,8,2,31,0,26,3,19,5,27] +dissimilar;fraction;10;outlier;RR;[8,5,0,2,1,47,3,19,7,93] +dissimilar;fraction;10;[1,2,3];RR;[1,2,3,78,0,41,4,85,6,64] +dissimilar;fraction;10;medoid;SM;[96,33,0,49,1,66,3,35,8,37] +dissimilar;fraction;10;outlier;SM;[4,42,8,17,5,19,10,22,13,49] +dissimilar;fraction;10;[1,2,3];SM;[1,2,3,16,0,64,6,85,4,12] +dissimilar;fraction;10;medoid;SS1;[23,78,0,26,1,58,2,8,3,48] +dissimilar;fraction;10;outlier;SS1;[34,85,0,2,1,41,3,20,4,64] +dissimilar;fraction;10;[1,2,3];SS1;[1,2,3,78,0,41,4,85,6,64] +dissimilar;fraction;10;medoid;SS2;[50,28,0,21,16,74,20,40,7,36] +dissimilar;fraction;10;outlier;SS2;[49,9,7,66,0,35,2,25,3,76] +dissimilar;fraction;10;[1,2,3];SS2;[1,2,3,16,0,64,6,85,4,12] +dissimilar;fraction;20;medoid;AC;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16] +dissimilar;fraction;20;outlier;AC;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76] +dissimilar;fraction;20;[1,2,3];AC;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] +dissimilar;fraction;20;medoid;BUB;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97] +dissimilar;fraction;20;outlier;BUB;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,49,10,28,12,40] +dissimilar;fraction;20;[1,2,3];BUB;[1,2,3,16,0,64,6,85,4,12,8,28,5,40,7,9,10,66,11,19] +dissimilar;fraction;20;medoid;CT1;[96,33,0,49,1,66,3,35,8,37,5,40,7,20,6,91,4,12,19,31] +dissimilar;fraction;20;outlier;CT1;[4,42,8,17,5,99,13,54,12,0,19,33,2,18,7,20,3,49,9,41] +dissimilar;fraction;20;[1,2,3];CT1;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,86,10,19] +dissimilar;fraction;20;medoid;CT2;[80,1,0,64,2,4,7,97,5,6,28,77,3,76,8,15,22,47,12,43] +dissimilar;fraction;20;outlier;CT2;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76] +dissimilar;fraction;20;[1,2,3];CT2;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] +dissimilar;fraction;20;medoid;CT3;[1,8,2,31,0,26,3,19,5,27,4,39,6,22,7,85,9,11,10,66] +dissimilar;fraction;20;outlier;CT3;[8,5,0,2,1,47,3,19,7,93,4,76,11,41,6,85,9,42,10,66] +dissimilar;fraction;20;[1,2,3];CT3;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] +dissimilar;fraction;20;medoid;CT4;[23,78,0,26,1,58,2,8,3,48,4,76,5,6,7,97,9,66,10,49] +dissimilar;fraction;20;outlier;CT4;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89] +dissimilar;fraction;20;[1,2,3];CT4;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] +dissimilar;fraction;20;medoid;Fai;[96,33,0,49,1,66,3,35,8,37,5,40,7,20,6,91,4,12,19,31] +dissimilar;fraction;20;outlier;Fai;[34,43,2,25,0,26,1,66,7,97,6,69,5,8,10,19,12,57,3,78] +dissimilar;fraction;20;[1,2,3];Fai;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,86,10,19] +dissimilar;fraction;20;medoid;Gle;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97] +dissimilar;fraction;20;outlier;Gle;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89] +dissimilar;fraction;20;[1,2,3];Gle;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] +dissimilar;fraction;20;medoid;Ja;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97] +dissimilar;fraction;20;outlier;Ja;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89] +dissimilar;fraction;20;[1,2,3];Ja;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] +dissimilar;fraction;20;medoid;Ja0;[50,28,0,21,16,74,20,40,7,36,4,49,8,17,5,54,1,86,3,6] +dissimilar;fraction;20;outlier;Ja0;[49,9,7,66,0,35,2,25,3,76,4,85,1,8,5,32,16,65,12,54] +dissimilar;fraction;20;[1,2,3];Ja0;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] +dissimilar;fraction;20;medoid;JT;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97] +dissimilar;fraction;20;outlier;JT;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89] +dissimilar;fraction;20;[1,2,3];JT;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] +dissimilar;fraction;20;medoid;RT;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16] +dissimilar;fraction;20;outlier;RT;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76] +dissimilar;fraction;20;[1,2,3];RT;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] +dissimilar;fraction;20;medoid;RR;[1,8,2,31,0,26,3,19,5,27,4,39,6,22,7,85,9,11,10,66] +dissimilar;fraction;20;outlier;RR;[8,5,0,2,1,47,3,19,7,93,4,76,11,41,6,85,9,42,10,66] +dissimilar;fraction;20;[1,2,3];RR;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] +dissimilar;fraction;20;medoid;SM;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16] +dissimilar;fraction;20;outlier;SM;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76] +dissimilar;fraction;20;[1,2,3];SM;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] +dissimilar;fraction;20;medoid;SS1;[23,78,0,26,1,58,2,8,3,48,4,76,5,6,7,97,9,66,10,49] +dissimilar;fraction;20;outlier;SS1;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89] +dissimilar;fraction;20;[1,2,3];SS1;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] +dissimilar;fraction;20;medoid;SS2;[50,28,0,21,16,74,20,40,7,36,4,49,8,17,5,54,1,86,3,6] +dissimilar;fraction;20;outlier;SS2;[49,9,7,66,0,35,2,25,3,76,4,85,1,8,5,32,16,65,12,54] +dissimilar;fraction;20;[1,2,3];SS2;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] +dissimilar;fraction;30;medoid;AC;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16,21,85,10,24,11,54,12,19,18,62] +dissimilar;fraction;30;outlier;AC;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76,27,54,6,31,15,91,18,44,7,80] +dissimilar;fraction;30;[1,2,3];AC;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] +dissimilar;fraction;30;medoid;BUB;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97,11,28,14,21,15,36,23,47,16,91] +dissimilar;fraction;30;outlier;BUB;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,49,10,28,12,40,14,66,19,44,11,48,13,22,15,91] +dissimilar;fraction;30;[1,2,3];BUB;[1,2,3,16,0,64,6,85,4,12,8,28,5,40,7,9,10,66,11,19,13,22,14,21,20,58,15,91,17,84] +dissimilar;fraction;30;medoid;CT1;[96,33,0,49,1,66,3,35,8,37,5,40,7,20,6,91,4,12,19,31,2,25,9,57,22,26,10,27,23,85] +dissimilar;fraction;30;outlier;CT1;[4,42,8,17,5,99,13,54,12,0,19,33,2,18,7,20,3,49,9,41,11,31,6,66,22,47,1,69,34,57] +dissimilar;fraction;30;[1,2,3];CT1;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,86,10,19,22,49,14,40,18,44,13,69,20,32] +dissimilar;fraction;30;medoid;CT2;[80,1,0,64,2,4,7,97,5,6,28,77,3,76,8,15,22,47,12,43,11,19,10,66,68,49,9,29,13,69] +dissimilar;fraction;30;outlier;CT2;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76,27,54,6,31,15,91,18,44,7,80] +dissimilar;fraction;30;[1,2,3];CT2;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] +dissimilar;fraction;30;medoid;CT3;[1,8,2,31,0,26,3,19,5,27,4,39,6,22,7,85,9,11,10,66,12,28,13,54,14,29,15,91,16,21] +dissimilar;fraction;30;outlier;CT3;[8,5,0,2,1,47,3,19,7,93,4,76,11,41,6,85,9,42,10,66,21,78,12,54,13,22,14,58,15,86] +dissimilar;fraction;30;[1,2,3];CT3;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,22] +dissimilar;fraction;30;medoid;CT4;[23,78,0,26,1,58,2,8,3,48,4,76,5,6,7,97,9,66,10,49,11,64,12,54,13,56,14,22,15,53] +dissimilar;fraction;30;outlier;CT4;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89,12,56,13,22,14,58,15,91,16,21] +dissimilar;fraction;30;[1,2,3];CT4;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,84] +dissimilar;fraction;30;medoid;Fai;[96,33,0,49,1,66,3,35,8,37,5,40,7,20,6,91,4,12,19,31,2,25,9,58,10,80,71,54,13,36] +dissimilar;fraction;30;outlier;Fai;[34,43,2,25,0,26,1,66,7,97,6,69,5,8,10,19,12,57,3,78,17,91,4,80,22,13,14,27,49,9] +dissimilar;fraction;30;[1,2,3];Fai;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,86,10,19,22,49,14,40,18,44,13,69,20,55] +dissimilar;fraction;30;medoid;Gle;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97,11,28,14,21,15,36,23,47,16,91] +dissimilar;fraction;30;outlier;Gle;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89,12,56,13,22,14,58,15,91,16,21] +dissimilar;fraction;30;[1,2,3];Gle;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,84] +dissimilar;fraction;30;medoid;Ja;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97,11,28,14,21,15,36,23,47,16,91] +dissimilar;fraction;30;outlier;Ja;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89,12,56,13,22,14,58,15,91,16,21] +dissimilar;fraction;30;[1,2,3];Ja;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,84] +dissimilar;fraction;30;medoid;Ja0;[50,28,0,21,16,74,20,40,7,36,4,49,8,17,5,54,1,86,3,6,22,57,19,42,9,33,14,24,2,84] +dissimilar;fraction;30;outlier;Ja0;[49,9,7,66,0,35,2,25,3,76,4,85,1,8,5,32,16,65,12,54,6,24,22,47,71,14,40,80,57,72] +dissimilar;fraction;30;[1,2,3];Ja0;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] +dissimilar;fraction;30;medoid;JT;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97,11,28,14,21,15,36,23,47,16,91] +dissimilar;fraction;30;outlier;JT;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89,12,56,13,22,14,58,15,91,16,21] +dissimilar;fraction;30;[1,2,3];JT;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,84] +dissimilar;fraction;30;medoid;RT;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16,21,85,10,24,11,54,12,19,18,62] +dissimilar;fraction;30;outlier;RT;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76,27,54,6,31,15,91,18,44,7,80] +dissimilar;fraction;30;[1,2,3];RT;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] +dissimilar;fraction;30;medoid;RR;[1,8,2,31,0,26,3,19,5,27,4,39,6,22,7,85,9,11,10,66,12,28,13,54,14,29,15,91,16,21] +dissimilar;fraction;30;outlier;RR;[8,5,0,2,1,47,3,19,7,93,4,76,11,41,6,85,9,42,10,66,21,78,12,54,13,22,14,58,15,86] +dissimilar;fraction;30;[1,2,3];RR;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,22] +dissimilar;fraction;30;medoid;SM;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16,21,85,10,24,11,54,12,19,18,62] +dissimilar;fraction;30;outlier;SM;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76,27,54,6,31,15,91,18,44,7,80] +dissimilar;fraction;30;[1,2,3];SM;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] +dissimilar;fraction;30;medoid;SS1;[23,78,0,26,1,58,2,8,3,48,4,76,5,6,7,97,9,66,10,49,11,64,12,54,13,56,14,22,15,53] +dissimilar;fraction;30;outlier;SS1;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89,12,56,13,22,14,58,15,91,16,21] +dissimilar;fraction;30;[1,2,3];SS1;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,84] +dissimilar;fraction;30;medoid;SS2;[50,28,0,21,16,74,20,40,7,36,4,49,8,17,5,54,1,86,3,6,22,57,19,42,9,33,14,24,2,84] +dissimilar;fraction;30;outlier;SS2;[49,9,7,66,0,35,2,25,3,76,4,85,1,8,5,32,16,65,12,54,6,24,22,47,71,14,40,80,57,72] +dissimilar;fraction;30;[1,2,3];SS2;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] +dissimilar;power_3;10;medoid;AC;[96,33,0,49,1,66,3,35,8,37] +dissimilar;power_3;10;outlier;AC;[4,42,8,17,5,19,10,22,13,49] +dissimilar;power_3;10;[1,2,3];AC;[1,2,3,16,0,64,6,85,4,12] +dissimilar;power_3;10;medoid;BUB;[69,13,0,27,1,66,2,19,3,31] +dissimilar;power_3;10;outlier;BUB;[34,85,0,2,1,41,3,20,4,64] +dissimilar;power_3;10;[1,2,3];BUB;[1,2,3,16,0,64,6,85,4,12] +dissimilar;power_3;10;medoid;CT1;[96,33,0,49,1,66,3,35,8,37] +dissimilar;power_3;10;outlier;CT1;[4,42,8,17,5,99,13,54,12,0] +dissimilar;power_3;10;[1,2,3];CT1;[1,2,3,16,0,64,6,85,4,12] +dissimilar;power_3;10;medoid;CT2;[80,1,0,64,2,4,7,97,5,6] +dissimilar;power_3;10;outlier;CT2;[4,42,8,17,5,19,10,22,13,49] +dissimilar;power_3;10;[1,2,3];CT2;[1,2,3,16,0,64,6,85,4,12] +dissimilar;power_3;10;medoid;CT3;[1,8,2,31,0,26,3,19,5,27] +dissimilar;power_3;10;outlier;CT3;[8,5,0,2,1,47,3,19,7,93] +dissimilar;power_3;10;[1,2,3];CT3;[1,2,3,78,0,41,4,85,6,64] +dissimilar;power_3;10;medoid;CT4;[23,78,0,26,1,58,2,8,3,48] +dissimilar;power_3;10;outlier;CT4;[34,85,0,2,1,41,3,20,4,64] +dissimilar;power_3;10;[1,2,3];CT4;[1,2,3,78,0,41,4,85,6,64] +dissimilar;power_3;10;medoid;Fai;[96,33,0,49,1,66,3,35,8,37] +dissimilar;power_3;10;outlier;Fai;[34,43,2,25,0,26,1,66,7,97] +dissimilar;power_3;10;[1,2,3];Fai;[1,2,3,16,0,64,6,85,4,12] +dissimilar;power_3;10;medoid;Gle;[69,13,0,27,1,66,2,19,3,31] +dissimilar;power_3;10;outlier;Gle;[34,85,0,2,1,41,3,20,4,64] +dissimilar;power_3;10;[1,2,3];Gle;[1,2,3,78,0,41,4,85,6,64] +dissimilar;power_3;10;medoid;Ja;[69,13,0,27,1,66,2,19,3,31] +dissimilar;power_3;10;outlier;Ja;[34,85,0,2,1,41,3,20,4,64] +dissimilar;power_3;10;[1,2,3];Ja;[1,2,3,78,0,41,4,85,6,64] +dissimilar;power_3;10;medoid;Ja0;[50,28,0,21,16,74,20,40,7,36] +dissimilar;power_3;10;outlier;Ja0;[49,9,7,66,0,35,2,25,3,76] +dissimilar;power_3;10;[1,2,3];Ja0;[1,2,3,16,0,64,6,85,4,12] +dissimilar;power_3;10;medoid;JT;[69,13,0,27,1,66,2,19,3,31] +dissimilar;power_3;10;outlier;JT;[34,85,0,2,1,41,3,20,4,64] +dissimilar;power_3;10;[1,2,3];JT;[1,2,3,78,0,41,4,85,6,64] +dissimilar;power_3;10;medoid;RT;[96,33,0,49,1,66,3,35,8,37] +dissimilar;power_3;10;outlier;RT;[4,42,8,17,5,19,10,22,13,49] +dissimilar;power_3;10;[1,2,3];RT;[1,2,3,16,0,64,6,85,4,12] +dissimilar;power_3;10;medoid;RR;[1,8,2,31,0,26,3,19,5,27] +dissimilar;power_3;10;outlier;RR;[8,5,0,2,1,47,3,19,7,93] +dissimilar;power_3;10;[1,2,3];RR;[1,2,3,78,0,41,4,85,6,64] +dissimilar;power_3;10;medoid;SM;[96,33,0,49,1,66,3,35,8,37] +dissimilar;power_3;10;outlier;SM;[4,42,8,17,5,19,10,22,13,49] +dissimilar;power_3;10;[1,2,3];SM;[1,2,3,16,0,64,6,85,4,12] +dissimilar;power_3;10;medoid;SS1;[23,78,0,26,1,58,2,8,3,48] +dissimilar;power_3;10;outlier;SS1;[34,85,0,2,1,41,3,20,4,64] +dissimilar;power_3;10;[1,2,3];SS1;[1,2,3,78,0,41,4,85,6,64] +dissimilar;power_3;10;medoid;SS2;[50,28,0,21,16,74,20,40,7,36] +dissimilar;power_3;10;outlier;SS2;[49,9,7,66,0,35,2,25,3,76] +dissimilar;power_3;10;[1,2,3];SS2;[1,2,3,16,0,64,6,85,4,12] +dissimilar;power_3;20;medoid;AC;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16] +dissimilar;power_3;20;outlier;AC;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76] +dissimilar;power_3;20;[1,2,3];AC;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] +dissimilar;power_3;20;medoid;BUB;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97] +dissimilar;power_3;20;outlier;BUB;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,49,10,28,12,40] +dissimilar;power_3;20;[1,2,3];BUB;[1,2,3,16,0,64,6,85,4,12,8,28,5,40,7,9,10,66,11,19] +dissimilar;power_3;20;medoid;CT1;[96,33,0,49,1,66,3,35,8,37,5,40,7,20,6,91,4,12,19,31] +dissimilar;power_3;20;outlier;CT1;[4,42,8,17,5,99,13,54,12,0,19,33,2,18,7,20,3,49,9,41] +dissimilar;power_3;20;[1,2,3];CT1;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,86,10,19] +dissimilar;power_3;20;medoid;CT2;[80,1,0,64,2,4,7,97,5,6,28,77,3,76,8,15,22,47,12,43] +dissimilar;power_3;20;outlier;CT2;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76] +dissimilar;power_3;20;[1,2,3];CT2;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] +dissimilar;power_3;20;medoid;CT3;[1,8,2,31,0,26,3,19,5,27,4,39,6,22,7,85,9,11,10,66] +dissimilar;power_3;20;outlier;CT3;[8,5,0,2,1,47,3,19,7,93,4,76,11,41,6,85,9,42,10,66] +dissimilar;power_3;20;[1,2,3];CT3;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] +dissimilar;power_3;20;medoid;CT4;[23,78,0,26,1,58,2,8,3,48,4,76,5,6,7,97,9,66,10,49] +dissimilar;power_3;20;outlier;CT4;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89] +dissimilar;power_3;20;[1,2,3];CT4;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] +dissimilar;power_3;20;medoid;Fai;[96,33,0,49,1,66,3,35,8,37,5,40,7,20,6,91,4,12,19,31] +dissimilar;power_3;20;outlier;Fai;[34,43,2,25,0,26,1,66,7,97,6,69,5,8,10,19,12,57,3,78] +dissimilar;power_3;20;[1,2,3];Fai;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,86,10,19] +dissimilar;power_3;20;medoid;Gle;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97] +dissimilar;power_3;20;outlier;Gle;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89] +dissimilar;power_3;20;[1,2,3];Gle;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] +dissimilar;power_3;20;medoid;Ja;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97] +dissimilar;power_3;20;outlier;Ja;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89] +dissimilar;power_3;20;[1,2,3];Ja;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] +dissimilar;power_3;20;medoid;Ja0;[50,28,0,21,16,74,20,40,7,36,4,49,8,17,5,54,1,86,3,6] +dissimilar;power_3;20;outlier;Ja0;[49,9,7,66,0,35,2,25,3,76,4,85,1,8,5,32,16,65,12,54] +dissimilar;power_3;20;[1,2,3];Ja0;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] +dissimilar;power_3;20;medoid;JT;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97] +dissimilar;power_3;20;outlier;JT;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89] +dissimilar;power_3;20;[1,2,3];JT;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] +dissimilar;power_3;20;medoid;RT;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16] +dissimilar;power_3;20;outlier;RT;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76] +dissimilar;power_3;20;[1,2,3];RT;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] +dissimilar;power_3;20;medoid;RR;[1,8,2,31,0,26,3,19,5,27,4,39,6,22,7,85,9,11,10,66] +dissimilar;power_3;20;outlier;RR;[8,5,0,2,1,47,3,19,7,93,4,76,11,41,6,85,9,42,10,66] +dissimilar;power_3;20;[1,2,3];RR;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] +dissimilar;power_3;20;medoid;SM;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16] +dissimilar;power_3;20;outlier;SM;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76] +dissimilar;power_3;20;[1,2,3];SM;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] +dissimilar;power_3;20;medoid;SS1;[23,78,0,26,1,58,2,8,3,48,4,76,5,6,7,97,9,66,10,49] +dissimilar;power_3;20;outlier;SS1;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89] +dissimilar;power_3;20;[1,2,3];SS1;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13] +dissimilar;power_3;20;medoid;SS2;[50,28,0,21,16,74,20,40,7,36,4,49,8,17,5,54,1,86,3,6] +dissimilar;power_3;20;outlier;SS2;[49,9,7,66,0,35,2,25,3,76,4,85,1,8,5,32,16,65,12,54] +dissimilar;power_3;20;[1,2,3];SS2;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27] +dissimilar;power_3;30;medoid;AC;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16,21,85,10,24,11,54,12,19,18,62] +dissimilar;power_3;30;outlier;AC;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76,27,54,6,31,15,91,18,44,7,80] +dissimilar;power_3;30;[1,2,3];AC;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] +dissimilar;power_3;30;medoid;BUB;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97,11,28,14,21,15,36,23,47,16,91] +dissimilar;power_3;30;outlier;BUB;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,49,10,28,12,40,14,66,19,44,11,48,13,22,15,91] +dissimilar;power_3;30;[1,2,3];BUB;[1,2,3,16,0,64,6,85,4,12,8,28,5,40,7,9,10,66,11,19,13,22,14,21,20,58,15,91,17,84] +dissimilar;power_3;30;medoid;CT1;[96,33,0,49,1,66,3,35,8,37,5,40,7,20,6,91,4,12,19,31,2,25,9,57,22,26,10,27,23,85] +dissimilar;power_3;30;outlier;CT1;[4,42,8,17,5,99,13,54,12,0,19,33,2,18,7,20,3,49,9,41,11,31,6,66,22,47,1,69,34,57] +dissimilar;power_3;30;[1,2,3];CT1;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,86,10,19,22,49,14,40,18,44,13,69,20,32] +dissimilar;power_3;30;medoid;CT2;[80,1,0,64,2,4,7,97,5,6,28,77,3,76,8,15,22,47,12,43,11,19,10,66,68,49,9,29,13,69] +dissimilar;power_3;30;outlier;CT2;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76,27,54,6,31,15,91,18,44,7,80] +dissimilar;power_3;30;[1,2,3];CT2;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] +dissimilar;power_3;30;medoid;CT3;[1,8,2,31,0,26,3,19,5,27,4,39,6,22,7,85,9,11,10,66,12,28,13,54,14,29,15,91,16,21] +dissimilar;power_3;30;outlier;CT3;[8,5,0,2,1,47,3,19,7,93,4,76,11,41,6,85,9,42,10,66,21,78,12,54,13,22,14,58,15,86] +dissimilar;power_3;30;[1,2,3];CT3;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,22] +dissimilar;power_3;30;medoid;CT4;[23,78,0,26,1,58,2,8,3,48,4,76,5,6,7,97,9,66,10,49,11,64,12,54,13,56,14,22,15,53] +dissimilar;power_3;30;outlier;CT4;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89,12,56,13,22,14,58,15,91,16,21] +dissimilar;power_3;30;[1,2,3];CT4;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,84] +dissimilar;power_3;30;medoid;Fai;[96,33,0,49,1,66,3,35,8,37,5,40,7,20,6,91,4,12,19,31,2,25,9,58,10,80,71,54,13,36] +dissimilar;power_3;30;outlier;Fai;[34,43,2,25,0,26,1,66,7,97,6,69,5,8,10,19,12,57,3,78,17,91,4,80,22,13,14,27,49,9] +dissimilar;power_3;30;[1,2,3];Fai;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,86,10,19,22,49,14,40,18,44,13,69,20,55] +dissimilar;power_3;30;medoid;Gle;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97,11,28,14,21,15,36,23,47,16,91] +dissimilar;power_3;30;outlier;Gle;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89,12,56,13,22,14,58,15,91,16,21] +dissimilar;power_3;30;[1,2,3];Gle;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,84] +dissimilar;power_3;30;medoid;Ja;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97,11,28,14,21,15,36,23,47,16,91] +dissimilar;power_3;30;outlier;Ja;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89,12,56,13,22,14,58,15,91,16,21] +dissimilar;power_3;30;[1,2,3];Ja;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,84] +dissimilar;power_3;30;medoid;Ja0;[50,28,0,21,16,74,20,40,7,36,4,49,8,17,5,54,1,86,3,6,22,57,19,42,9,33,14,24,2,84] +dissimilar;power_3;30;outlier;Ja0;[49,9,7,66,0,35,2,25,3,76,4,85,1,8,5,32,16,65,12,54,6,24,22,47,71,14,40,80,57,72] +dissimilar;power_3;30;[1,2,3];Ja0;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] +dissimilar;power_3;30;medoid;JT;[69,13,0,27,1,66,2,19,3,31,4,85,5,6,7,8,9,12,10,97,11,28,14,21,15,36,23,47,16,91] +dissimilar;power_3;30;outlier;JT;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89,12,56,13,22,14,58,15,91,16,21] +dissimilar;power_3;30;[1,2,3];JT;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,84] +dissimilar;power_3;30;medoid;RT;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16,21,85,10,24,11,54,12,19,18,62] +dissimilar;power_3;30;outlier;RT;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76,27,54,6,31,15,91,18,44,7,80] +dissimilar;power_3;30;[1,2,3];RT;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] +dissimilar;power_3;30;medoid;RR;[1,8,2,31,0,26,3,19,5,27,4,39,6,22,7,85,9,11,10,66,12,28,13,54,14,29,15,91,16,21] +dissimilar;power_3;30;outlier;RR;[8,5,0,2,1,47,3,19,7,93,4,76,11,41,6,85,9,42,10,66,21,78,12,54,13,22,14,58,15,86] +dissimilar;power_3;30;[1,2,3];RR;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,22] +dissimilar;power_3;30;medoid;SM;[96,33,0,49,1,66,3,35,8,37,5,13,7,97,2,99,4,42,9,16,21,85,10,24,11,54,12,19,18,62] +dissimilar;power_3;30;outlier;SM;[4,42,8,17,5,19,10,22,13,49,0,69,2,34,14,84,1,66,3,76,27,54,6,31,15,91,18,44,7,80] +dissimilar;power_3;30;[1,2,3];SM;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] +dissimilar;power_3;30;medoid;SS1;[23,78,0,26,1,58,2,8,3,48,4,76,5,6,7,97,9,66,10,49,11,64,12,54,13,56,14,22,15,53] +dissimilar;power_3;30;outlier;SS1;[34,85,0,2,1,41,3,20,4,64,5,6,7,8,9,26,11,66,10,89,12,56,13,22,14,58,15,91,16,21] +dissimilar;power_3;30;[1,2,3];SS1;[1,2,3,78,0,41,4,85,6,64,5,8,7,27,9,28,10,66,11,13,12,19,14,58,15,91,16,40,17,84] +dissimilar;power_3;30;medoid;SS2;[50,28,0,21,16,74,20,40,7,36,4,49,8,17,5,54,1,86,3,6,22,57,19,42,9,33,14,24,2,84] +dissimilar;power_3;30;outlier;SS2;[49,9,7,66,0,35,2,25,3,76,4,85,1,8,5,32,16,65,12,54,6,24,22,47,71,14,40,80,57,72] +dissimilar;power_3;30;[1,2,3];SS2;[1,2,3,16,0,64,6,85,4,12,8,28,7,9,5,77,11,54,18,27,31,13,36,65,25,71,56,23,33,35] diff --git a/selector/methods/tests/test_distance.py b/selector/methods/tests/test_distance.py index 9f6d92d8..12701086 100644 --- a/selector/methods/tests/test_distance.py +++ b/selector/methods/tests/test_distance.py @@ -1,584 +1,584 @@ -# -*- coding: utf-8 -*- -# -# The Selector is a Python library of algorithms for selecting diverse -# subsets of data for machine-learning. -# -# Copyright (C) 2022-2024 The QC-Devs Community -# -# This file is part of Selector. -# -# Selector is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 -# of the License, or (at your option) any later version. -# -# Selector is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see -# -# -- -"""Test selector/methods/distance.py.""" - -import numpy as np -import pytest -from numpy.testing import assert_equal, assert_raises -from scipy.spatial.distance import pdist, squareform -from sklearn.metrics import pairwise_distances - -from selector.methods.distance import DISE, MaxMin, MaxSum, OptiSim -from selector.methods.tests.common import ( - generate_synthetic_cluster_data, - generate_synthetic_data, - get_data_file_path, -) - - -def test_maxmin(): - """Testing the MaxMin class.""" - # generate random data points belonging to one cluster - pairwise distance matrix - _, _, arr_dist = generate_synthetic_data( - n_samples=100, - n_features=2, - n_clusters=1, - pairwise_dist=True, - metric="euclidean", - random_state=42, - ) - - # generate random data points belonging to multiple clusters - class labels and pairwise distance matrix - _, class_labels_cluster, arr_dist_cluster = generate_synthetic_data( - n_samples=100, - n_features=2, - n_clusters=3, - pairwise_dist=True, - metric="euclidean", - random_state=42, - ) - - # use MaxMin algorithm to select points from clustered data - collector = MaxMin() - selected_ids = collector.select( - arr_dist_cluster, - size=12, - labels=class_labels_cluster, - proportional_selection=False, - ) - # make sure all the selected indices are the same with expectation - assert_equal(selected_ids, [41, 34, 94, 85, 51, 50, 66, 78, 21, 64, 29, 83]) - - # use MaxMin algorithm to select points from non-clustered data - collector = MaxMin() - selected_ids = collector.select(arr_dist, size=12) - # make sure all the selected indices are the same with expectation - assert_equal(selected_ids, [85, 57, 41, 25, 9, 62, 29, 65, 81, 61, 60, 97]) - - # use MaxMin algorithm to select points from non-clustered data with "medoid" as the reference point - collector_medoid_1 = MaxMin(ref_index=None) - selected_ids_medoid_1 = collector_medoid_1.select(arr_dist, size=12) - # make sure all the selected indices are the same with expectation - assert_equal(selected_ids_medoid_1, [85, 57, 41, 25, 9, 62, 29, 65, 81, 61, 60, 97]) - - # use MaxMin algorithm to select points from non-clustered data with "None" for the reference point - collector_medoid_2 = MaxMin(ref_index=None) - selected_ids_medoid_2 = collector_medoid_2.select(arr_dist, size=12) - # make sure all the selected indices are the same with expectation - assert_equal(selected_ids_medoid_2, [85, 57, 41, 25, 9, 62, 29, 65, 81, 61, 60, 97]) - - # use MaxMin algorithm to select points from non-clustered data with float as the reference point - collector_float = MaxMin(ref_index=85) - selected_ids_float = collector_float.select(arr_dist, size=12) - # make sure all the selected indices are the same with expectation - assert_equal(selected_ids_float, [85, 57, 41, 25, 9, 62, 29, 65, 81, 61, 60, 97]) - - # use MaxMin algorithm to select points from non-clustered data with a predefined list as the reference point - collector_float = MaxMin(ref_index=[85, 57, 41, 25]) - selected_ids_float = collector_float.select(arr_dist, size=12) - # make sure all the selected indices are the same with expectation - assert_equal(selected_ids_float, [85, 57, 41, 25, 9, 62, 29, 65, 81, 61, 60, 97]) - - # test failing case when ref_index is not a valid index - with pytest.raises(ValueError): - collector_float = MaxMin(ref_index=-3) - selected_ids_float = collector_float.select(arr_dist, size=12) - # test failing case when ref_index contains a complex number - with pytest.raises(ValueError): - collector_float = MaxMin(ref_index=[1 + 5j, 2, 5]) - _ = collector_float.select(arr_dist, size=12) - # test failing case when ref_index contains a negative number - with pytest.raises(ValueError): - collector_float = MaxMin(ref_index=[-1, 2, 5]) - _ = collector_float.select(arr_dist, size=12) - - # test failing case when the number of labels is not equal to the number of samples - with pytest.raises(ValueError): - collector_float = MaxMin(ref_index=85) - _ = collector_float.select( - arr_dist, size=12, labels=class_labels_cluster[:90], proportional_selection=False - ) - - # use MaxMin algorithm, this time instantiating with a distance metric - collector = MaxMin(fun_dist=lambda x: pairwise_distances(x, metric="euclidean")) - simple_coords = np.array([[0, 0], [2, 0], [0, 2], [2, 2], [-10, -10]]) - # provide coordinates rather than pairwise distance matrix to collector - selected_ids = collector.select(x=simple_coords, size=3) - # make sure all the selected indices are the same with expectation - assert_equal(selected_ids, [0, 4, 3]) - - # generating mocked clusters - np.random.seed(42) - cluster_one = np.random.normal(0, 1, (3, 2)) - cluster_two = np.random.normal(10, 1, (6, 2)) - cluster_three = np.random.normal(20, 1, (10, 2)) - labels_mocked = np.hstack( - [[0 for i in range(3)], [1 for i in range(6)], [2 for i in range(10)]] - ) - mocked_cluster_coords = np.vstack([cluster_one, cluster_two, cluster_three]) - - # selecting molecules - collector = MaxMin(lambda x: pairwise_distances(x, metric="euclidean")) - selected_mocked = collector.select( - mocked_cluster_coords, - size=15, - labels=labels_mocked, - proportional_selection=False, - ) - assert_equal(selected_mocked, [0, 1, 2, 3, 4, 5, 6, 7, 8, 16, 15, 10, 13, 9, 18]) - - -def test_maxmin_proportional_selection(): - """Test MaxMin class with proportional selection.""" - # generate the first cluster with 3 points - coords, labels, cluster_one, cluster_two, cluster_three = generate_synthetic_cluster_data() - # instantiate the MaxMin class - collector = MaxMin(fun_dist=lambda x: pairwise_distances(x, metric="euclidean"), ref_index=0) - # select 6 points with proportional selection from each cluster - selected_ids = collector.select( - coords, - size=6, - labels=labels, - proportional_selection=True, - ) - # make sure all the selected indices are the same with expectation - assert_equal(selected_ids, [0, 3, 8, 9, 17, 13]) - # check how many points are selected from each cluster - assert_equal(len(selected_ids), 6) - # check the number of points selected from cluster one - assert_equal((labels[selected_ids] == 0).sum(), 1) - # check the number of points selected from cluster two - assert_equal((labels[selected_ids] == 1).sum(), 2) - # check the number of points selected from cluster three - assert_equal((labels[selected_ids] == 2).sum(), 3) - - -def test_maxmin_proportional_selection_imbalance_1(): - """Test MaxMin class with proportional selection with imbalance case 1.""" - # load three-cluster data from file - # 2 from class 0, 10 from class 1, 40 from class 2 - coords_file_path = get_data_file_path("coords_imbalance_case1.txt") - coords = np.genfromtxt(coords_file_path, delimiter=",", skip_header=0) - labels_file_path = get_data_file_path("labels_imbalance_case1.txt") - labels = np.genfromtxt(labels_file_path, delimiter=",", skip_header=0) - - # instantiate the MaxMin class - collector = MaxMin(fun_dist=lambda x: pairwise_distances(x, metric="euclidean"), ref_index=0) - # select 12 points with proportional selection from each cluster - selected_ids = collector.select( - coords, - size=9, - labels=labels, - proportional_selection=True, - ) - - # make sure all the selected indices are the same with expectation - assert_equal(selected_ids, [0, 2, 6, 12, 15, 38, 16, 41, 36]) - # check how many points are selected from each cluster - assert_equal(len(selected_ids), 9) - # check the number of points selected from cluster one - assert_equal((labels[selected_ids] == 0).sum(), 1) - # check the number of points selected from cluster two - assert_equal((labels[selected_ids] == 1).sum(), 2) - # check the number of points selected from cluster three - assert_equal((labels[selected_ids] == 2).sum(), 6) - - -def test_maxmin_proportional_selection_imbalance_2(): - """Test MaxMin class with proportional selection with imbalance case 2.""" - # load three-cluster data from file - # 3 from class 0, 11 from class 1, 40 from class 2 - coords_file_path = get_data_file_path("coords_imbalance_case2.txt") - coords = np.genfromtxt(coords_file_path, delimiter=",", skip_header=0) - labels_file_path = get_data_file_path("labels_imbalance_case2.txt") - labels = np.genfromtxt(labels_file_path, delimiter=",", skip_header=0) - - # instantiate the MaxMin class - collector = MaxMin(fun_dist=lambda x: pairwise_distances(x, metric="euclidean"), ref_index=0) - # select 12 points with proportional selection from each cluster - selected_ids = collector.select( - coords, - size=14, - labels=labels, - proportional_selection=True, - ) - - # # make sure all the selected indices are the same with expectation - assert_equal(selected_ids, [0, 3, 9, 6, 14, 36, 53, 17, 44, 23, 28, 50, 52, 49]) - print(f"selected_ids: {selected_ids}") - # check how many points are selected from each cluster - assert_equal(len(selected_ids), 14) - # check the number of points selected from cluster one - assert_equal((labels[selected_ids] == 0).sum(), 1) - # check the number of points selected from cluster two - assert_equal((labels[selected_ids] == 1).sum(), 3) - # check the number of points selected from cluster three - assert_equal((labels[selected_ids] == 2).sum(), 10) - - -def test_maxmin_invalid_input(): - """Testing MaxMin class with invalid input.""" - # case when the distance matrix is not square - x_dist = np.array([[0, 1], [1, 0], [4, 9]]) - with pytest.raises(ValueError): - collector = MaxMin(ref_index=0) - _ = collector.select(x_dist, size=2) - - # case when the distance matrix is not symmetric - x_dist = np.array([[0, 1, 2, 1], [1, 1, 0, 3], [4, 9, 4, 0], [6, 5, 6, 7]]) - with pytest.raises(ValueError): - collector = MaxMin(ref_index=0) - _ = collector.select(x_dist, size=2) - - -def test_maxsum_clustered_data(): - """Testing MaxSum class.""" - # generate random data points belonging to multiple clusters - coordinates and class labels - coords_cluster, class_labels_cluster, coords_cluster_dist = generate_synthetic_data( - n_samples=100, - n_features=2, - n_clusters=3, - pairwise_dist=True, - metric="euclidean", - random_state=42, - ) - - # use MaxSum algorithm to select points from clustered data, instantiating with euclidean distance metric - collector = MaxSum(fun_dist=lambda x: pairwise_distances(x, metric="euclidean"), ref_index=None) - selected_ids = collector.select( - coords_cluster, - size=12, - labels=class_labels_cluster, - proportional_selection=False, - ) - # make sure all the selected indices are the same with expectation - assert_equal(selected_ids, [41, 34, 85, 94, 51, 50, 78, 66, 21, 64, 0, 83]) - - # use MaxSum algorithm to select points from clustered data without instantiating with euclidean distance metric - collector = MaxSum(ref_index=None) - selected_ids = collector.select( - coords_cluster_dist, - size=12, - labels=class_labels_cluster, - proportional_selection=False, - ) - # make sure all the selected indices are the same with expectation - assert_equal(selected_ids, [41, 34, 85, 94, 51, 50, 78, 66, 21, 64, 0, 83]) - - # check that ValueError is raised when number of points requested is greater than number of points in array - with pytest.raises(ValueError): - _ = collector.select_from_cluster( - coords_cluster, - size=101, - labels=class_labels_cluster, - ) - - -def test_maxsum_non_clustered_data(): - """Testing MaxSum class with non-clustered data.""" - # generate random data points belonging to one cluster - coordinates - coords, _, _ = generate_synthetic_data( - n_samples=100, - n_features=2, - n_clusters=1, - pairwise_dist=True, - metric="euclidean", - random_state=42, - ) - # use MaxSum algorithm to select points from non-clustered data, instantiating with euclidean distance metric - collector = MaxSum(fun_dist=lambda x: pairwise_distances(x, metric="euclidean"), ref_index=None) - selected_ids = collector.select(coords, size=12) - # make sure all the selected indices are the same with expectation - assert_equal(selected_ids, [85, 57, 25, 41, 95, 9, 21, 8, 13, 68, 37, 54]) - - # use MaxSum algorithm to select points from non-clustered data, instantiating with euclidean - # distance metric and using "medoid" as the reference point - collector = MaxSum(fun_dist=lambda x: pairwise_distances(x, metric="euclidean"), ref_index=None) - selected_ids = collector.select(coords, size=12) - # make sure all the selected indices are the same with expectation - assert_equal(selected_ids, [85, 57, 25, 41, 95, 9, 21, 8, 13, 68, 37, 54]) - - # use MaxSum algorithm to select points from non-clustered data, instantiating with euclidean - # distance metric and using a list as the reference points - collector = MaxSum( - fun_dist=lambda x: pairwise_distances(x, metric="euclidean"), - ref_index=[85, 57, 25, 41, 95], - ) - selected_ids = collector.select(coords, size=12) - # make sure all the selected indices are the same with expectation - assert_equal(selected_ids, [85, 57, 25, 41, 95, 9, 21, 8, 13, 68, 37, 54]) - - # use MaxSum algorithm to select points from non-clustered data, instantiating with euclidean - # distance metric and using an invalid reference point - with pytest.raises(ValueError): - collector = MaxSum( - fun_dist=lambda x: pairwise_distances(x, metric="euclidean"), ref_index=-1 - ) - selected_ids = collector.select(coords, size=12) - - -def test_maxsum_invalid_input(): - """Testing MaxSum class with invalid input.""" - # case when the distance matrix is not square - x_dist = np.array([[0, 1], [1, 0], [4, 9]]) - with pytest.raises(ValueError): - collector = MaxSum(ref_index=0) - _ = collector.select(x_dist, size=2) - - # case when the distance matrix is not square - x_dist = np.array([[0, 1, 2], [1, 0, 3], [4, 9, 0], [5, 6, 7]]) - with pytest.raises(ValueError): - collector = MaxSum(ref_index=0) - _ = collector.select(x_dist, size=2) - - # case when the distance matrix is not symmetric - x_dist = np.array([[0, 1, 2, 1], [1, 1, 0, 3], [4, 9, 4, 0], [6, 5, 6, 7]]) - with pytest.raises(ValueError): - collector = MaxSum(ref_index=0) - _ = collector.select(x_dist, size=2) - - -def test_maxsum_proportional_selection(): - """Test MaxSum class with proportional selection.""" - # generate the first cluster with 3 points - coords, labels, cluster_one, cluster_two, cluster_three = generate_synthetic_cluster_data() - # instantiate the MaxSum class - collector = MaxSum(fun_dist=lambda x: pairwise_distances(x, metric="euclidean"), ref_index=0) - # select 6 points with proportional selection from each cluster - selected_ids = collector.select( - coords, - size=6, - labels=labels, - proportional_selection=True, - ) - # make sure all the selected indices are the same with expectation - assert_equal(selected_ids, [0, 3, 8, 9, 17, 10]) - # check how many points are selected from each cluster - assert_equal(len(selected_ids), 6) - # check the number of points selected from cluster one - assert_equal((labels[selected_ids] == 0).sum(), 1) - # check the number of points selected from cluster two - assert_equal((labels[selected_ids] == 1).sum(), 2) - # check the number of points selected from cluster three - assert_equal((labels[selected_ids] == 2).sum(), 3) - - -def test_optisim(): - """Testing OptiSim class.""" - # generate random data points belonging to one cluster - coordinates and pairwise distance matrix - coords, _, arr_dist = generate_synthetic_data( - n_samples=100, - n_features=2, - n_clusters=1, - pairwise_dist=True, - metric="euclidean", - random_state=42, - ) - - # generate random data points belonging to multiple clusters - coordinates and class labels - coords_cluster, class_labels_cluster, _ = generate_synthetic_data( - n_samples=100, - n_features=2, - n_clusters=3, - pairwise_dist=True, - metric="euclidean", - random_state=42, - ) - - # use OptiSim algorithm to select points from clustered data - collector = OptiSim(ref_index=0) - selected_ids = collector.select(coords_cluster, size=12, labels=class_labels_cluster) - # make sure all the selected indices are the same with expectation - # assert_equal(selected_ids, [2, 85, 86, 59, 1, 66, 50, 68, 0, 64, 83, 72]) - - # use OptiSim algorithm to select points from non-clustered data - collector = OptiSim(ref_index=0) - selected_ids = collector.select(coords, size=12) - # make sure all the selected indices are the same with expectation - assert_equal(selected_ids, [0, 8, 55, 37, 41, 13, 12, 42, 6, 30, 57, 76]) - - # check if OptiSim gives same results as MaxMin for k=>infinity - collector = OptiSim(ref_index=85, k=999999) - selected_ids_optisim = collector.select(coords, size=12) - collector = MaxMin() - selected_ids_maxmin = collector.select(arr_dist, size=12) - assert_equal(selected_ids_optisim, selected_ids_maxmin) - - # test with invalid ref_index - with pytest.raises(ValueError): - collector = OptiSim(ref_index=10000) - _ = collector.select(coords, size=12) - - -def test_optisim_proportional_selection(): - """Test OptiSim class with proportional selection.""" - # generate the first cluster with 3 points - coords, labels, cluster_one, cluster_two, cluster_three = generate_synthetic_cluster_data() - # instantiate the Optisim class - collector = OptiSim(fun_dist=lambda x: pairwise_distances(x, metric="euclidean"), ref_index=0) - # select 6 points with proportional selection from each cluster - selected_ids = collector.select( - coords, - size=6, - labels=labels, - proportional_selection=True, - ) - # make sure all the selected indices are the same with expectation - assert_equal(selected_ids, [0, 3, 8, 9, 17, 13]) - # check how many points are selected from each cluster - assert_equal(len(selected_ids), 6) - # check the number of points selected from cluster one - assert_equal((labels[selected_ids] == 0).sum(), 1) - # check the number of points selected from cluster two - assert_equal((labels[selected_ids] == 1).sum(), 2) - # check the number of points selected from cluster three - assert_equal((labels[selected_ids] == 2).sum(), 3) - - -def test_directed_sphere_size_error(): - """Test DirectedSphereExclusion error when too many points requested.""" - x = np.array([[1, 9]] * 100) - collector = DISE() - assert_raises(ValueError, collector.select, x, size=105) - - -def test_directed_sphere_same_number_of_pts(): - """Test DirectSphereExclusion with `size` = number of points in dataset.""" - # (0,0) as the reference point - x = np.array([[0, 0], [0, 1], [0, 2], [0, 3]]) - collector = DISE(r0=1, tol=0, ref_index=0) - selected = collector.select(x, size=2) - assert_equal(selected, [0, 2]) - assert_equal(collector.r, 1) - - -def test_directed_sphere_same_number_of_pts_None(): - """Test DirectSphereExclusion with `size` = number of points in dataset with the ref_index None.""" - # None as the reference point - x = np.array([[0, 0], [0, 1], [0, 2], [0, 3], [0, 4]]) - collector = DISE(r0=1, tol=0, ref_index=None) - selected = collector.select(x, size=3) - assert_equal(selected, [2, 0, 4]) - assert_equal(collector.r, 1) - - -def test_directed_sphere_exclusion_select_more_number_of_pts(): - """Test DirectSphereExclusion on points on the line with `size` < number of points in dataset.""" - # (0,0) as the reference point - x = np.array([[0, 0], [0, 1], [0, 2], [0, 3], [0, 4], [0, 5], [0, 6]]) - collector = DISE(r0=0.5, tol=0, ref_index=0) - selected = collector.select(x, size=3) - expected = [0, 3, 6] - assert_equal(selected, expected) - assert_equal(collector.r, 2.0) - - -def test_directed_sphere_exclusion_on_line_with_smaller_radius(): - """Test Direct Sphere Exclusion on points on line with smaller distribution than the radius.""" - # (0,0) as the reference point - x = np.array( - [ - [0, 0], - [0, 1], - [0, 1.1], - [0, 1.2], - [0, 2], - [0, 3], - [0, 3.1], - [0, 3.2], - [0, 4], - [0, 5], - [0, 6], - ] - ) - collector = DISE(r0=0.5, tol=1, ref_index=1) - selected = collector.select(x, size=3) - expected = [1, 5, 9] - assert_equal(selected, expected) - assert_equal(collector.r, 1.0) - - -def test_directed_sphere_on_line_with_larger_radius(): - """Test Direct Sphere Exclusion on points on the line with a too large radius size.""" - # (0,0) as the reference point - x = np.array( - [ - [0, 0], - [0, 1], - [0, 1.1], - [0, 1.2], - [0, 2], - [0, 3], - [0, 3.1], - [0, 3.2], - [0, 4], - [0, 5], - ] - ) - collector = DISE(r0=2.0, tol=0, p=2.0, ref_index=1) - selected = collector.select(x, size=3) - expected = [1, 5, 9] - assert_equal(selected, expected) - assert_equal(collector.r, 1.0) - - -def test_directed_sphere_dist_func(): - """Test Direct Sphere Exclusion with a distance function.""" - # (0,0) as the reference point - x = np.array([[0, 0], [0, 1], [0, 2], [0, 3], [0, 4], [0, 5], [0, 6]]) - collector = DISE( - r0=0.5, - tol=0, - ref_index=0, - fun_dist=lambda x: squareform(pdist(x, metric="minkowski", p=0.1)), - ) - selected = collector.select(x, size=3) - expected = [0, 3, 6] - assert_equal(selected, expected) - assert_equal(collector.r, 2.0) - - -def test_directed_sphere_proportional_selection(): - """Test DISE class with proportional selection.""" - # generate the first cluster with 3 points - coords, labels, cluster_one, cluster_two, cluster_three = generate_synthetic_cluster_data() - # instantiate the DISE class - collector = DISE(fun_dist=lambda x: pairwise_distances(x, metric="euclidean"), ref_index=0) - # select 6 points with proportional selection from each cluster - selected_ids = collector.select( - coords, - size=6, - labels=labels, - proportional_selection=True, - ) - # make sure all the selected indices are the same with expectation - assert_equal(selected_ids, [0, 3, 7, 9, 12, 15]) - # check how many points are selected from each cluster - assert_equal(len(selected_ids), 6) - # check the number of points selected from cluster one - assert_equal((labels[selected_ids] == 0).sum(), 1) - # check the number of points selected from cluster two - assert_equal((labels[selected_ids] == 1).sum(), 2) - # check the number of points selected from cluster three - assert_equal((labels[selected_ids] == 2).sum(), 3) +# -*- coding: utf-8 -*- +# +# The Selector is a Python library of algorithms for selecting diverse +# subsets of data for machine-learning. +# +# Copyright (C) 2022-2024 The QC-Devs Community +# +# This file is part of Selector. +# +# Selector is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 +# of the License, or (at your option) any later version. +# +# Selector is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see +# +# -- +"""Test selector/methods/distance.py.""" + +import numpy as np +import pytest +from numpy.testing import assert_equal, assert_raises +from scipy.spatial.distance import pdist, squareform +from sklearn.metrics import pairwise_distances + +from selector.methods.distance import DISE, MaxMin, MaxSum, OptiSim +from selector.methods.tests.common import ( + generate_synthetic_cluster_data, + generate_synthetic_data, + get_data_file_path, +) + + +def test_maxmin(): + """Testing the MaxMin class.""" + # generate random data points belonging to one cluster - pairwise distance matrix + _, _, arr_dist = generate_synthetic_data( + n_samples=100, + n_features=2, + n_clusters=1, + pairwise_dist=True, + metric="euclidean", + random_state=42, + ) + + # generate random data points belonging to multiple clusters - class labels and pairwise distance matrix + _, class_labels_cluster, arr_dist_cluster = generate_synthetic_data( + n_samples=100, + n_features=2, + n_clusters=3, + pairwise_dist=True, + metric="euclidean", + random_state=42, + ) + + # use MaxMin algorithm to select points from clustered data + collector = MaxMin() + selected_ids = collector.select( + arr_dist_cluster, + size=12, + labels=class_labels_cluster, + proportional_selection=False, + ) + # make sure all the selected indices are the same with expectation + assert_equal(selected_ids, [41, 34, 94, 85, 51, 50, 66, 78, 21, 64, 29, 83]) + + # use MaxMin algorithm to select points from non-clustered data + collector = MaxMin() + selected_ids = collector.select(arr_dist, size=12) + # make sure all the selected indices are the same with expectation + assert_equal(selected_ids, [85, 57, 41, 25, 9, 62, 29, 65, 81, 61, 60, 97]) + + # use MaxMin algorithm to select points from non-clustered data with "medoid" as the reference point + collector_medoid_1 = MaxMin(ref_index=None) + selected_ids_medoid_1 = collector_medoid_1.select(arr_dist, size=12) + # make sure all the selected indices are the same with expectation + assert_equal(selected_ids_medoid_1, [85, 57, 41, 25, 9, 62, 29, 65, 81, 61, 60, 97]) + + # use MaxMin algorithm to select points from non-clustered data with "None" for the reference point + collector_medoid_2 = MaxMin(ref_index=None) + selected_ids_medoid_2 = collector_medoid_2.select(arr_dist, size=12) + # make sure all the selected indices are the same with expectation + assert_equal(selected_ids_medoid_2, [85, 57, 41, 25, 9, 62, 29, 65, 81, 61, 60, 97]) + + # use MaxMin algorithm to select points from non-clustered data with float as the reference point + collector_float = MaxMin(ref_index=85) + selected_ids_float = collector_float.select(arr_dist, size=12) + # make sure all the selected indices are the same with expectation + assert_equal(selected_ids_float, [85, 57, 41, 25, 9, 62, 29, 65, 81, 61, 60, 97]) + + # use MaxMin algorithm to select points from non-clustered data with a predefined list as the reference point + collector_float = MaxMin(ref_index=[85, 57, 41, 25]) + selected_ids_float = collector_float.select(arr_dist, size=12) + # make sure all the selected indices are the same with expectation + assert_equal(selected_ids_float, [85, 57, 41, 25, 9, 62, 29, 65, 81, 61, 60, 97]) + + # test failing case when ref_index is not a valid index + with pytest.raises(ValueError): + collector_float = MaxMin(ref_index=-3) + selected_ids_float = collector_float.select(arr_dist, size=12) + # test failing case when ref_index contains a complex number + with pytest.raises(ValueError): + collector_float = MaxMin(ref_index=[1 + 5j, 2, 5]) + _ = collector_float.select(arr_dist, size=12) + # test failing case when ref_index contains a negative number + with pytest.raises(ValueError): + collector_float = MaxMin(ref_index=[-1, 2, 5]) + _ = collector_float.select(arr_dist, size=12) + + # test failing case when the number of labels is not equal to the number of samples + with pytest.raises(ValueError): + collector_float = MaxMin(ref_index=85) + _ = collector_float.select( + arr_dist, size=12, labels=class_labels_cluster[:90], proportional_selection=False + ) + + # use MaxMin algorithm, this time instantiating with a distance metric + collector = MaxMin(fun_dist=lambda x: pairwise_distances(x, metric="euclidean")) + simple_coords = np.array([[0, 0], [2, 0], [0, 2], [2, 2], [-10, -10]]) + # provide coordinates rather than pairwise distance matrix to collector + selected_ids = collector.select(x=simple_coords, size=3) + # make sure all the selected indices are the same with expectation + assert_equal(selected_ids, [0, 4, 3]) + + # generating mocked clusters + np.random.seed(42) + cluster_one = np.random.normal(0, 1, (3, 2)) + cluster_two = np.random.normal(10, 1, (6, 2)) + cluster_three = np.random.normal(20, 1, (10, 2)) + labels_mocked = np.hstack( + [[0 for i in range(3)], [1 for i in range(6)], [2 for i in range(10)]] + ) + mocked_cluster_coords = np.vstack([cluster_one, cluster_two, cluster_three]) + + # selecting molecules + collector = MaxMin(lambda x: pairwise_distances(x, metric="euclidean")) + selected_mocked = collector.select( + mocked_cluster_coords, + size=15, + labels=labels_mocked, + proportional_selection=False, + ) + assert_equal(selected_mocked, [0, 1, 2, 3, 4, 5, 6, 7, 8, 16, 15, 10, 13, 9, 18]) + + +def test_maxmin_proportional_selection(): + """Test MaxMin class with proportional selection.""" + # generate the first cluster with 3 points + coords, labels, cluster_one, cluster_two, cluster_three = generate_synthetic_cluster_data() + # instantiate the MaxMin class + collector = MaxMin(fun_dist=lambda x: pairwise_distances(x, metric="euclidean"), ref_index=0) + # select 6 points with proportional selection from each cluster + selected_ids = collector.select( + coords, + size=6, + labels=labels, + proportional_selection=True, + ) + # make sure all the selected indices are the same with expectation + assert_equal(selected_ids, [0, 3, 8, 9, 17, 13]) + # check how many points are selected from each cluster + assert_equal(len(selected_ids), 6) + # check the number of points selected from cluster one + assert_equal((labels[selected_ids] == 0).sum(), 1) + # check the number of points selected from cluster two + assert_equal((labels[selected_ids] == 1).sum(), 2) + # check the number of points selected from cluster three + assert_equal((labels[selected_ids] == 2).sum(), 3) + + +def test_maxmin_proportional_selection_imbalance_1(): + """Test MaxMin class with proportional selection with imbalance case 1.""" + # load three-cluster data from file + # 2 from class 0, 10 from class 1, 40 from class 2 + coords_file_path = get_data_file_path("coords_imbalance_case1.txt") + coords = np.genfromtxt(coords_file_path, delimiter=",", skip_header=0) + labels_file_path = get_data_file_path("labels_imbalance_case1.txt") + labels = np.genfromtxt(labels_file_path, delimiter=",", skip_header=0) + + # instantiate the MaxMin class + collector = MaxMin(fun_dist=lambda x: pairwise_distances(x, metric="euclidean"), ref_index=0) + # select 12 points with proportional selection from each cluster + selected_ids = collector.select( + coords, + size=9, + labels=labels, + proportional_selection=True, + ) + + # make sure all the selected indices are the same with expectation + assert_equal(selected_ids, [0, 2, 6, 12, 15, 38, 16, 41, 36]) + # check how many points are selected from each cluster + assert_equal(len(selected_ids), 9) + # check the number of points selected from cluster one + assert_equal((labels[selected_ids] == 0).sum(), 1) + # check the number of points selected from cluster two + assert_equal((labels[selected_ids] == 1).sum(), 2) + # check the number of points selected from cluster three + assert_equal((labels[selected_ids] == 2).sum(), 6) + + +def test_maxmin_proportional_selection_imbalance_2(): + """Test MaxMin class with proportional selection with imbalance case 2.""" + # load three-cluster data from file + # 3 from class 0, 11 from class 1, 40 from class 2 + coords_file_path = get_data_file_path("coords_imbalance_case2.txt") + coords = np.genfromtxt(coords_file_path, delimiter=",", skip_header=0) + labels_file_path = get_data_file_path("labels_imbalance_case2.txt") + labels = np.genfromtxt(labels_file_path, delimiter=",", skip_header=0) + + # instantiate the MaxMin class + collector = MaxMin(fun_dist=lambda x: pairwise_distances(x, metric="euclidean"), ref_index=0) + # select 12 points with proportional selection from each cluster + selected_ids = collector.select( + coords, + size=14, + labels=labels, + proportional_selection=True, + ) + + # # make sure all the selected indices are the same with expectation + assert_equal(selected_ids, [0, 3, 9, 6, 14, 36, 53, 17, 44, 23, 28, 50, 52, 49]) + print(f"selected_ids: {selected_ids}") + # check how many points are selected from each cluster + assert_equal(len(selected_ids), 14) + # check the number of points selected from cluster one + assert_equal((labels[selected_ids] == 0).sum(), 1) + # check the number of points selected from cluster two + assert_equal((labels[selected_ids] == 1).sum(), 3) + # check the number of points selected from cluster three + assert_equal((labels[selected_ids] == 2).sum(), 10) + + +def test_maxmin_invalid_input(): + """Testing MaxMin class with invalid input.""" + # case when the distance matrix is not square + x_dist = np.array([[0, 1], [1, 0], [4, 9]]) + with pytest.raises(ValueError): + collector = MaxMin(ref_index=0) + _ = collector.select(x_dist, size=2) + + # case when the distance matrix is not symmetric + x_dist = np.array([[0, 1, 2, 1], [1, 1, 0, 3], [4, 9, 4, 0], [6, 5, 6, 7]]) + with pytest.raises(ValueError): + collector = MaxMin(ref_index=0) + _ = collector.select(x_dist, size=2) + + +def test_maxsum_clustered_data(): + """Testing MaxSum class.""" + # generate random data points belonging to multiple clusters - coordinates and class labels + coords_cluster, class_labels_cluster, coords_cluster_dist = generate_synthetic_data( + n_samples=100, + n_features=2, + n_clusters=3, + pairwise_dist=True, + metric="euclidean", + random_state=42, + ) + + # use MaxSum algorithm to select points from clustered data, instantiating with euclidean distance metric + collector = MaxSum(fun_dist=lambda x: pairwise_distances(x, metric="euclidean"), ref_index=None) + selected_ids = collector.select( + coords_cluster, + size=12, + labels=class_labels_cluster, + proportional_selection=False, + ) + # make sure all the selected indices are the same with expectation + assert_equal(selected_ids, [41, 34, 85, 94, 51, 50, 78, 66, 21, 64, 0, 83]) + + # use MaxSum algorithm to select points from clustered data without instantiating with euclidean distance metric + collector = MaxSum(ref_index=None) + selected_ids = collector.select( + coords_cluster_dist, + size=12, + labels=class_labels_cluster, + proportional_selection=False, + ) + # make sure all the selected indices are the same with expectation + assert_equal(selected_ids, [41, 34, 85, 94, 51, 50, 78, 66, 21, 64, 0, 83]) + + # check that ValueError is raised when number of points requested is greater than number of points in array + with pytest.raises(ValueError): + _ = collector.select_from_cluster( + coords_cluster, + size=101, + labels=class_labels_cluster, + ) + + +def test_maxsum_non_clustered_data(): + """Testing MaxSum class with non-clustered data.""" + # generate random data points belonging to one cluster - coordinates + coords, _, _ = generate_synthetic_data( + n_samples=100, + n_features=2, + n_clusters=1, + pairwise_dist=True, + metric="euclidean", + random_state=42, + ) + # use MaxSum algorithm to select points from non-clustered data, instantiating with euclidean distance metric + collector = MaxSum(fun_dist=lambda x: pairwise_distances(x, metric="euclidean"), ref_index=None) + selected_ids = collector.select(coords, size=12) + # make sure all the selected indices are the same with expectation + assert_equal(selected_ids, [85, 57, 25, 41, 95, 9, 21, 8, 13, 68, 37, 54]) + + # use MaxSum algorithm to select points from non-clustered data, instantiating with euclidean + # distance metric and using "medoid" as the reference point + collector = MaxSum(fun_dist=lambda x: pairwise_distances(x, metric="euclidean"), ref_index=None) + selected_ids = collector.select(coords, size=12) + # make sure all the selected indices are the same with expectation + assert_equal(selected_ids, [85, 57, 25, 41, 95, 9, 21, 8, 13, 68, 37, 54]) + + # use MaxSum algorithm to select points from non-clustered data, instantiating with euclidean + # distance metric and using a list as the reference points + collector = MaxSum( + fun_dist=lambda x: pairwise_distances(x, metric="euclidean"), + ref_index=[85, 57, 25, 41, 95], + ) + selected_ids = collector.select(coords, size=12) + # make sure all the selected indices are the same with expectation + assert_equal(selected_ids, [85, 57, 25, 41, 95, 9, 21, 8, 13, 68, 37, 54]) + + # use MaxSum algorithm to select points from non-clustered data, instantiating with euclidean + # distance metric and using an invalid reference point + with pytest.raises(ValueError): + collector = MaxSum( + fun_dist=lambda x: pairwise_distances(x, metric="euclidean"), ref_index=-1 + ) + selected_ids = collector.select(coords, size=12) + + +def test_maxsum_invalid_input(): + """Testing MaxSum class with invalid input.""" + # case when the distance matrix is not square + x_dist = np.array([[0, 1], [1, 0], [4, 9]]) + with pytest.raises(ValueError): + collector = MaxSum(ref_index=0) + _ = collector.select(x_dist, size=2) + + # case when the distance matrix is not square + x_dist = np.array([[0, 1, 2], [1, 0, 3], [4, 9, 0], [5, 6, 7]]) + with pytest.raises(ValueError): + collector = MaxSum(ref_index=0) + _ = collector.select(x_dist, size=2) + + # case when the distance matrix is not symmetric + x_dist = np.array([[0, 1, 2, 1], [1, 1, 0, 3], [4, 9, 4, 0], [6, 5, 6, 7]]) + with pytest.raises(ValueError): + collector = MaxSum(ref_index=0) + _ = collector.select(x_dist, size=2) + + +def test_maxsum_proportional_selection(): + """Test MaxSum class with proportional selection.""" + # generate the first cluster with 3 points + coords, labels, cluster_one, cluster_two, cluster_three = generate_synthetic_cluster_data() + # instantiate the MaxSum class + collector = MaxSum(fun_dist=lambda x: pairwise_distances(x, metric="euclidean"), ref_index=0) + # select 6 points with proportional selection from each cluster + selected_ids = collector.select( + coords, + size=6, + labels=labels, + proportional_selection=True, + ) + # make sure all the selected indices are the same with expectation + assert_equal(selected_ids, [0, 3, 8, 9, 17, 10]) + # check how many points are selected from each cluster + assert_equal(len(selected_ids), 6) + # check the number of points selected from cluster one + assert_equal((labels[selected_ids] == 0).sum(), 1) + # check the number of points selected from cluster two + assert_equal((labels[selected_ids] == 1).sum(), 2) + # check the number of points selected from cluster three + assert_equal((labels[selected_ids] == 2).sum(), 3) + + +def test_optisim(): + """Testing OptiSim class.""" + # generate random data points belonging to one cluster - coordinates and pairwise distance matrix + coords, _, arr_dist = generate_synthetic_data( + n_samples=100, + n_features=2, + n_clusters=1, + pairwise_dist=True, + metric="euclidean", + random_state=42, + ) + + # generate random data points belonging to multiple clusters - coordinates and class labels + coords_cluster, class_labels_cluster, _ = generate_synthetic_data( + n_samples=100, + n_features=2, + n_clusters=3, + pairwise_dist=True, + metric="euclidean", + random_state=42, + ) + + # use OptiSim algorithm to select points from clustered data + collector = OptiSim(ref_index=0) + selected_ids = collector.select(coords_cluster, size=12, labels=class_labels_cluster) + # make sure all the selected indices are the same with expectation + # assert_equal(selected_ids, [2, 85, 86, 59, 1, 66, 50, 68, 0, 64, 83, 72]) + + # use OptiSim algorithm to select points from non-clustered data + collector = OptiSim(ref_index=0) + selected_ids = collector.select(coords, size=12) + # make sure all the selected indices are the same with expectation + assert_equal(selected_ids, [0, 8, 55, 37, 41, 13, 12, 42, 6, 30, 57, 76]) + + # check if OptiSim gives same results as MaxMin for k=>infinity + collector = OptiSim(ref_index=85, k=999999) + selected_ids_optisim = collector.select(coords, size=12) + collector = MaxMin() + selected_ids_maxmin = collector.select(arr_dist, size=12) + assert_equal(selected_ids_optisim, selected_ids_maxmin) + + # test with invalid ref_index + with pytest.raises(ValueError): + collector = OptiSim(ref_index=10000) + _ = collector.select(coords, size=12) + + +def test_optisim_proportional_selection(): + """Test OptiSim class with proportional selection.""" + # generate the first cluster with 3 points + coords, labels, cluster_one, cluster_two, cluster_three = generate_synthetic_cluster_data() + # instantiate the Optisim class + collector = OptiSim(fun_dist=lambda x: pairwise_distances(x, metric="euclidean"), ref_index=0) + # select 6 points with proportional selection from each cluster + selected_ids = collector.select( + coords, + size=6, + labels=labels, + proportional_selection=True, + ) + # make sure all the selected indices are the same with expectation + assert_equal(selected_ids, [0, 3, 8, 9, 17, 13]) + # check how many points are selected from each cluster + assert_equal(len(selected_ids), 6) + # check the number of points selected from cluster one + assert_equal((labels[selected_ids] == 0).sum(), 1) + # check the number of points selected from cluster two + assert_equal((labels[selected_ids] == 1).sum(), 2) + # check the number of points selected from cluster three + assert_equal((labels[selected_ids] == 2).sum(), 3) + + +def test_directed_sphere_size_error(): + """Test DirectedSphereExclusion error when too many points requested.""" + x = np.array([[1, 9]] * 100) + collector = DISE() + assert_raises(ValueError, collector.select, x, size=105) + + +def test_directed_sphere_same_number_of_pts(): + """Test DirectSphereExclusion with `size` = number of points in dataset.""" + # (0,0) as the reference point + x = np.array([[0, 0], [0, 1], [0, 2], [0, 3]]) + collector = DISE(r0=1, tol=0, ref_index=0) + selected = collector.select(x, size=2) + assert_equal(selected, [0, 2]) + assert_equal(collector.r, 1) + + +def test_directed_sphere_same_number_of_pts_None(): + """Test DirectSphereExclusion with `size` = number of points in dataset with the ref_index None.""" + # None as the reference point + x = np.array([[0, 0], [0, 1], [0, 2], [0, 3], [0, 4]]) + collector = DISE(r0=1, tol=0, ref_index=None) + selected = collector.select(x, size=3) + assert_equal(selected, [2, 0, 4]) + assert_equal(collector.r, 1) + + +def test_directed_sphere_exclusion_select_more_number_of_pts(): + """Test DirectSphereExclusion on points on the line with `size` < number of points in dataset.""" + # (0,0) as the reference point + x = np.array([[0, 0], [0, 1], [0, 2], [0, 3], [0, 4], [0, 5], [0, 6]]) + collector = DISE(r0=0.5, tol=0, ref_index=0) + selected = collector.select(x, size=3) + expected = [0, 3, 6] + assert_equal(selected, expected) + assert_equal(collector.r, 2.0) + + +def test_directed_sphere_exclusion_on_line_with_smaller_radius(): + """Test Direct Sphere Exclusion on points on line with smaller distribution than the radius.""" + # (0,0) as the reference point + x = np.array( + [ + [0, 0], + [0, 1], + [0, 1.1], + [0, 1.2], + [0, 2], + [0, 3], + [0, 3.1], + [0, 3.2], + [0, 4], + [0, 5], + [0, 6], + ] + ) + collector = DISE(r0=0.5, tol=1, ref_index=1) + selected = collector.select(x, size=3) + expected = [1, 5, 9] + assert_equal(selected, expected) + assert_equal(collector.r, 1.0) + + +def test_directed_sphere_on_line_with_larger_radius(): + """Test Direct Sphere Exclusion on points on the line with a too large radius size.""" + # (0,0) as the reference point + x = np.array( + [ + [0, 0], + [0, 1], + [0, 1.1], + [0, 1.2], + [0, 2], + [0, 3], + [0, 3.1], + [0, 3.2], + [0, 4], + [0, 5], + ] + ) + collector = DISE(r0=2.0, tol=0, p=2.0, ref_index=1) + selected = collector.select(x, size=3) + expected = [1, 5, 9] + assert_equal(selected, expected) + assert_equal(collector.r, 1.0) + + +def test_directed_sphere_dist_func(): + """Test Direct Sphere Exclusion with a distance function.""" + # (0,0) as the reference point + x = np.array([[0, 0], [0, 1], [0, 2], [0, 3], [0, 4], [0, 5], [0, 6]]) + collector = DISE( + r0=0.5, + tol=0, + ref_index=0, + fun_dist=lambda x: squareform(pdist(x, metric="minkowski", p=0.1)), + ) + selected = collector.select(x, size=3) + expected = [0, 3, 6] + assert_equal(selected, expected) + assert_equal(collector.r, 2.0) + + +def test_directed_sphere_proportional_selection(): + """Test DISE class with proportional selection.""" + # generate the first cluster with 3 points + coords, labels, cluster_one, cluster_two, cluster_three = generate_synthetic_cluster_data() + # instantiate the DISE class + collector = DISE(fun_dist=lambda x: pairwise_distances(x, metric="euclidean"), ref_index=0) + # select 6 points with proportional selection from each cluster + selected_ids = collector.select( + coords, + size=6, + labels=labels, + proportional_selection=True, + ) + # make sure all the selected indices are the same with expectation + assert_equal(selected_ids, [0, 3, 7, 9, 12, 15]) + # check how many points are selected from each cluster + assert_equal(len(selected_ids), 6) + # check the number of points selected from cluster one + assert_equal((labels[selected_ids] == 0).sum(), 1) + # check the number of points selected from cluster two + assert_equal((labels[selected_ids] == 1).sum(), 2) + # check the number of points selected from cluster three + assert_equal((labels[selected_ids] == 2).sum(), 3) diff --git a/selector/methods/tests/test_partition.py b/selector/methods/tests/test_partition.py index 3e613e2d..32baefb0 100644 --- a/selector/methods/tests/test_partition.py +++ b/selector/methods/tests/test_partition.py @@ -1,185 +1,185 @@ -# -*- coding: utf-8 -*- -# -# The Selector is a Python library of algorithms for selecting diverse -# subsets of data for machine-learning. -# -# Copyright (C) 2022-2024 The QC-Devs Community -# -# This file is part of Selector. -# -# Selector is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 -# of the License, or (at your option) any later version. -# -# Selector is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see -# -# -- -"""Test Partition-Based Selection Methods.""" - -import numpy as np -import pytest -from numpy.testing import assert_equal, assert_raises - -from selector.methods.partition import GridPartition, Medoid -from selector.methods.tests.common import generate_synthetic_data - - -@pytest.mark.parametrize("numb_pts", [4]) -@pytest.mark.parametrize("method", ["equifrequent", "equisized"]) -def test_grid_partitioning_independent_on_simple_example(numb_pts, method): - r"""Test grid partitioning on an example each bin has only one point.""" - # Construct feature array where each molecule is known to be in which bin - # The grid is a uniform grid from 0 to 10 in X-axis and 0 to 11 on y-axis. - x = np.linspace(0, 3, numb_pts) - y = np.linspace(0, 3, numb_pts) - X, Y = np.meshgrid(x, y) - grid = np.array([1.0, 0.0]) + np.vstack([X.ravel(), Y.ravel()]).T - # Make one bin have an extra point - grid = np.vstack((grid, np.array([1.1, 0.0]))) - - # Here the number of cells should be equal to the number of points in each dimension - # excluding the extra point, so that the answer is unique/known. - collector = GridPartition(nbins_axis=4, bin_method=f"{method}_independent") - # Sort the points so that they're comparable to the expected answer. - selected_ids = np.sort(collector.select(grid, size=len(grid) - 1)) - expected = np.arange(len(grid) - 1) - assert_equal(selected_ids, expected) - - -def test_grid_partitioning_equisized_dependent_on_simple_example(): - r"""Test equisized_dependent grid partitioning on example that is different from independent.""" - # Construct feature array where each molecule is known to be in which bin - grid = np.array( - [ - [0.0, 0.0], # Corresponds to bin (0, 0) - [0.0, 4.0], # Corresponds to bin (0, 3) - [1.0, 1.0], # Corresponds to bin (1, 0) - [1.0, 0.9], # Corresponds to bin (1, 0) - [1.0, 2.0], # Corresponds to bin (1, 3) - [2.0, 0.0], # Corresponds to bin (2, 0) - [2.0, 4.0], # Corresponds to bin (2, 3) - [3.0, 0.0], # Corresponds to bin (3, 0) - [3.0, 4.0], # Corresponds to bin (3, 3) - [3.0, 3.9], # Corresponds to bin (3, 3) - ] - ) - - # The number of bins makes it so that it approximately be a single point in each bin - collector = GridPartition(nbins_axis=4, bin_method="equisized_dependent") - # Two bins have an extra point in them and so has more diversity than other bins - # then the two expected molecules should be in those bins. - selected_ids = collector.select(grid, size=2, labels=None) - right_molecules = True - if not (2 in selected_ids or 3 in selected_ids): - right_molecules = False - if not (8 in selected_ids or 9 in selected_ids): - right_molecules = False - assert right_molecules, "The correct points were selected" - - -@pytest.mark.parametrize("numb_pts", [4]) -def test_grid_partitioning_equifrequent_dependent_on_simple_example(numb_pts): - r"""Test equifrequent dependent grid partitioning on an example where each bin has only one point.""" - # Construct feature array where each molecule is known to be in which bin - # The grid is a uniform grid from 0 to 10 in X-axis and 0 to 11 on y-axis. - x = np.linspace(0, 3, numb_pts) - y = np.linspace(0, 3, numb_pts) - X, Y = np.meshgrid(x, y) - grid = np.array([1.0, 0.0]) + np.vstack([X.ravel(), Y.ravel()]).T - # Make one bin have an extra point - grid = np.vstack((grid, np.array([1.1, 0.0]))) - - # Here the number of cells should be equal to the number of points in each dimension - # excluding the extra point, so that the answer is unique/known. - collector = GridPartition(nbins_axis=numb_pts, bin_method="equifrequent_dependent") - # Sort the points so that they're comparable to the expected answer. - selected_ids = np.sort(collector.select(grid, size=len(grid) - 1)) - expected = np.arange(len(grid) - 1) - assert_equal(selected_ids, expected) - - -@pytest.mark.parametrize("numb_pts", [10, 20, 30]) -@pytest.mark.parametrize("method", ["equifrequent", "equisized"]) -def test_bins_from_both_methods_dependent_same_as_independent_on_uniform_grid(numb_pts, method): - r"""Test bins is the same between the two equisized methods on uniform grid in three-dimensions.""" - x = np.linspace(0, 10, numb_pts) - y = np.linspace(0, 11, numb_pts) - X = np.meshgrid(x, y, y) - grid = np.vstack(list(map(np.ravel, X))).T - grid = np.array([1.0, 0.0, 0.0]) + grid - - # Here the number of cells should be equal to the number of points in each dimension - # excluding the extra point, so that the answer is unique/known. - collector_indept = GridPartition(nbins_axis=numb_pts, bin_method=f"{method}_independent") - collector_depend = GridPartition(nbins_axis=numb_pts, bin_method=f"{method}_dependent") - - # Get the bins from the method - bins_indept = collector_indept.get_bins_from_method(grid) - bins_dept = collector_depend.get_bins_from_method(grid) - - # Test the bins are the same - for key in bins_indept.keys(): - assert_equal(bins_dept[key], bins_indept[key]) - - -def test_raises_grid_partitioning(): - r"""Test raises error for grid partitioning.""" - grid = np.random.uniform(0.0, 1.0, size=(10, 3)) - - assert_raises(TypeError, GridPartition, 5.0) # Test number of axis should be integer - assert_raises(TypeError, GridPartition, 5, 5.0) # Test grid method should be string - assert_raises(TypeError, GridPartition, 5, "string", []) # Test random seed should be integer - - # Test the collector grid method is not the correct string - collector = GridPartition(nbins_axis=5, bin_method="string") - assert_raises(ValueError, collector.select_from_cluster, grid, 5) - - collector = GridPartition(nbins_axis=5) - assert_raises(TypeError, collector.select_from_cluster, [5.0], 5) # Test X is numpy array - assert_raises( - TypeError, collector.select_from_cluster, grid, 5.0 - ) # Test number selected should be int - assert_raises(TypeError, collector.select_from_cluster, grid, 5, [5.0]) - - -def test_medoid(): - """Testing Medoid class.""" - coords, _, _ = generate_synthetic_data( - n_samples=100, - n_features=2, - n_clusters=1, - pairwise_dist=True, - metric="euclidean", - random_state=42, - ) - - coords_cluster, class_labels_cluster, _ = generate_synthetic_data( - n_samples=100, - n_features=2, - n_clusters=3, - pairwise_dist=True, - metric="euclidean", - random_state=42, - ) - collector = Medoid() - selected_ids = collector.select(coords_cluster, size=12, labels=class_labels_cluster) - # make sure all the selected indices are the same with expectation - assert_equal(selected_ids, [2, 73, 94, 86, 1, 50, 93, 78, 0, 54, 33, 72]) - - collector = Medoid() - selected_ids = collector.select(coords, size=12) - # make sure all the selected indices are the same with expectation - assert_equal(selected_ids, [0, 95, 57, 41, 25, 9, 8, 6, 66, 1, 42, 82]) - - # test the case where KD-Tree query return is an integer - features = np.array([[1.5, 2.8], [2.3, 3.8], [1.5, 2.8], [4.0, 5.9]]) - selector = Medoid() - selected_ids = selector.select(features, size=2) - assert_equal(selected_ids, [0, 3]) +# -*- coding: utf-8 -*- +# +# The Selector is a Python library of algorithms for selecting diverse +# subsets of data for machine-learning. +# +# Copyright (C) 2022-2024 The QC-Devs Community +# +# This file is part of Selector. +# +# Selector is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 +# of the License, or (at your option) any later version. +# +# Selector is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see +# +# -- +"""Test Partition-Based Selection Methods.""" + +import numpy as np +import pytest +from numpy.testing import assert_equal, assert_raises + +from selector.methods.partition import GridPartition, Medoid +from selector.methods.tests.common import generate_synthetic_data + + +@pytest.mark.parametrize("numb_pts", [4]) +@pytest.mark.parametrize("method", ["equifrequent", "equisized"]) +def test_grid_partitioning_independent_on_simple_example(numb_pts, method): + r"""Test grid partitioning on an example each bin has only one point.""" + # Construct feature array where each molecule is known to be in which bin + # The grid is a uniform grid from 0 to 10 in X-axis and 0 to 11 on y-axis. + x = np.linspace(0, 3, numb_pts) + y = np.linspace(0, 3, numb_pts) + X, Y = np.meshgrid(x, y) + grid = np.array([1.0, 0.0]) + np.vstack([X.ravel(), Y.ravel()]).T + # Make one bin have an extra point + grid = np.vstack((grid, np.array([1.1, 0.0]))) + + # Here the number of cells should be equal to the number of points in each dimension + # excluding the extra point, so that the answer is unique/known. + collector = GridPartition(nbins_axis=4, bin_method=f"{method}_independent") + # Sort the points so that they're comparable to the expected answer. + selected_ids = np.sort(collector.select(grid, size=len(grid) - 1)) + expected = np.arange(len(grid) - 1) + assert_equal(selected_ids, expected) + + +def test_grid_partitioning_equisized_dependent_on_simple_example(): + r"""Test equisized_dependent grid partitioning on example that is different from independent.""" + # Construct feature array where each molecule is known to be in which bin + grid = np.array( + [ + [0.0, 0.0], # Corresponds to bin (0, 0) + [0.0, 4.0], # Corresponds to bin (0, 3) + [1.0, 1.0], # Corresponds to bin (1, 0) + [1.0, 0.9], # Corresponds to bin (1, 0) + [1.0, 2.0], # Corresponds to bin (1, 3) + [2.0, 0.0], # Corresponds to bin (2, 0) + [2.0, 4.0], # Corresponds to bin (2, 3) + [3.0, 0.0], # Corresponds to bin (3, 0) + [3.0, 4.0], # Corresponds to bin (3, 3) + [3.0, 3.9], # Corresponds to bin (3, 3) + ] + ) + + # The number of bins makes it so that it approximately be a single point in each bin + collector = GridPartition(nbins_axis=4, bin_method="equisized_dependent") + # Two bins have an extra point in them and so has more diversity than other bins + # then the two expected molecules should be in those bins. + selected_ids = collector.select(grid, size=2, labels=None) + right_molecules = True + if not (2 in selected_ids or 3 in selected_ids): + right_molecules = False + if not (8 in selected_ids or 9 in selected_ids): + right_molecules = False + assert right_molecules, "The correct points were selected" + + +@pytest.mark.parametrize("numb_pts", [4]) +def test_grid_partitioning_equifrequent_dependent_on_simple_example(numb_pts): + r"""Test equifrequent dependent grid partitioning on an example where each bin has only one point.""" + # Construct feature array where each molecule is known to be in which bin + # The grid is a uniform grid from 0 to 10 in X-axis and 0 to 11 on y-axis. + x = np.linspace(0, 3, numb_pts) + y = np.linspace(0, 3, numb_pts) + X, Y = np.meshgrid(x, y) + grid = np.array([1.0, 0.0]) + np.vstack([X.ravel(), Y.ravel()]).T + # Make one bin have an extra point + grid = np.vstack((grid, np.array([1.1, 0.0]))) + + # Here the number of cells should be equal to the number of points in each dimension + # excluding the extra point, so that the answer is unique/known. + collector = GridPartition(nbins_axis=numb_pts, bin_method="equifrequent_dependent") + # Sort the points so that they're comparable to the expected answer. + selected_ids = np.sort(collector.select(grid, size=len(grid) - 1)) + expected = np.arange(len(grid) - 1) + assert_equal(selected_ids, expected) + + +@pytest.mark.parametrize("numb_pts", [10, 20, 30]) +@pytest.mark.parametrize("method", ["equifrequent", "equisized"]) +def test_bins_from_both_methods_dependent_same_as_independent_on_uniform_grid(numb_pts, method): + r"""Test bins is the same between the two equisized methods on uniform grid in three-dimensions.""" + x = np.linspace(0, 10, numb_pts) + y = np.linspace(0, 11, numb_pts) + X = np.meshgrid(x, y, y) + grid = np.vstack(list(map(np.ravel, X))).T + grid = np.array([1.0, 0.0, 0.0]) + grid + + # Here the number of cells should be equal to the number of points in each dimension + # excluding the extra point, so that the answer is unique/known. + collector_indept = GridPartition(nbins_axis=numb_pts, bin_method=f"{method}_independent") + collector_depend = GridPartition(nbins_axis=numb_pts, bin_method=f"{method}_dependent") + + # Get the bins from the method + bins_indept = collector_indept.get_bins_from_method(grid) + bins_dept = collector_depend.get_bins_from_method(grid) + + # Test the bins are the same + for key in bins_indept.keys(): + assert_equal(bins_dept[key], bins_indept[key]) + + +def test_raises_grid_partitioning(): + r"""Test raises error for grid partitioning.""" + grid = np.random.uniform(0.0, 1.0, size=(10, 3)) + + assert_raises(TypeError, GridPartition, 5.0) # Test number of axis should be integer + assert_raises(TypeError, GridPartition, 5, 5.0) # Test grid method should be string + assert_raises(TypeError, GridPartition, 5, "string", []) # Test random seed should be integer + + # Test the collector grid method is not the correct string + collector = GridPartition(nbins_axis=5, bin_method="string") + assert_raises(ValueError, collector.select_from_cluster, grid, 5) + + collector = GridPartition(nbins_axis=5) + assert_raises(TypeError, collector.select_from_cluster, [5.0], 5) # Test X is numpy array + assert_raises( + TypeError, collector.select_from_cluster, grid, 5.0 + ) # Test number selected should be int + assert_raises(TypeError, collector.select_from_cluster, grid, 5, [5.0]) + + +def test_medoid(): + """Testing Medoid class.""" + coords, _, _ = generate_synthetic_data( + n_samples=100, + n_features=2, + n_clusters=1, + pairwise_dist=True, + metric="euclidean", + random_state=42, + ) + + coords_cluster, class_labels_cluster, _ = generate_synthetic_data( + n_samples=100, + n_features=2, + n_clusters=3, + pairwise_dist=True, + metric="euclidean", + random_state=42, + ) + collector = Medoid() + selected_ids = collector.select(coords_cluster, size=12, labels=class_labels_cluster) + # make sure all the selected indices are the same with expectation + assert_equal(selected_ids, [2, 73, 94, 86, 1, 50, 93, 78, 0, 54, 33, 72]) + + collector = Medoid() + selected_ids = collector.select(coords, size=12) + # make sure all the selected indices are the same with expectation + assert_equal(selected_ids, [0, 95, 57, 41, 25, 9, 8, 6, 66, 1, 42, 82]) + + # test the case where KD-Tree query return is an integer + features = np.array([[1.5, 2.8], [2.3, 3.8], [1.5, 2.8], [4.0, 5.9]]) + selector = Medoid() + selected_ids = selector.select(features, size=2) + assert_equal(selected_ids, [0, 3]) diff --git a/selector/methods/tests/test_similarity.py b/selector/methods/tests/test_similarity.py index b246b619..bf59c7da 100644 --- a/selector/methods/tests/test_similarity.py +++ b/selector/methods/tests/test_similarity.py @@ -1,1610 +1,1610 @@ -# -*- coding: utf-8 -*- -# -# The Selector is a Python library of algorithms for selecting diverse -# subsets of data for machine-learning. -# -# Copyright (C) 2022-2024 The QC-Devs Community -# -# This file is part of Selector. -# -# Selector is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 -# of the License, or (at your option) any later version. -# -# Selector is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see -# -# -- -"""Test similarity.py.""" - -import ast -import csv -import importlib - -import numpy as np -import pytest -from numpy.testing import assert_almost_equal, assert_equal, assert_raises - -from selector.measures.similarity import ( - modified_tanimoto, - pairwise_similarity_bit, - scaled_similarity_matrix, - tanimoto, -) -from selector.methods.similarity import NSimilarity, SimilarityIndex -from selector.methods.tests.common import get_data_file_path - - -def test_pairwise_similarity_bit_raises(): - # check raised error for input feature matrix that is not 2D - assert_raises(ValueError, pairwise_similarity_bit, np.random.random(5), "tanimoto") - assert_raises(ValueError, pairwise_similarity_bit, np.random.random((2, 3, 4)), "tanimoto") - # check raised error for not-available method - assert_raises(ValueError, pairwise_similarity_bit, np.random.random((5, 1)), "tan") - assert_raises(ValueError, pairwise_similarity_bit, np.random.random((5, 1)), tanimoto) - - -def test_tanimoto_raises(): - # check raised error when a or b is not 1D - assert_raises(ValueError, tanimoto, np.random.random((1, 5)), np.random.random(5)) - assert_raises(ValueError, tanimoto, np.random.random(3), np.random.random((1, 4))) - assert_raises(ValueError, tanimoto, np.random.random(4), np.random.random((3, 4))) - assert_raises(ValueError, tanimoto, np.random.random((3, 3)), np.random.random((2, 3))) - # check raised error when a and b don't have the same length - assert_raises(ValueError, tanimoto, np.random.random(3), np.random.random(5)) - assert_raises(ValueError, tanimoto, np.random.random(20), np.random.random(10)) - - -def test_tanimoto(): - """Test the tanimoto function on one pair of points.""" - a = np.array([2, 0, 1]) - b = np.array([2, 0, 0]) - # expected = (2*2 + 0*0 + 1*0) / (2**2 + 1 + 2**2 - 2*2) - assert_equal(tanimoto(a, b), 4 / (5 + 4 - 4)) - - -def test_tanimoto_bitstring(): - """Test the tanimoto function on one pair of points.""" - a = np.array([0, 0, 0, 1, 0, 1, 1]) - b = np.array([1, 1, 0, 0, 0, 1, 1]) - assert_equal(tanimoto(a, b), 2 / 5) - - -def test_tanimoto_matrix(): - """Testing the tanimoto function with predefined feature matrix.""" - x = np.array([[1, 4], [3, 2]]) - s = pairwise_similarity_bit(x, "tanimoto") - expected = np.array([[1, (11 / 19)], [(11 / 19), 1]]) - assert_equal(s, expected) - - -def test_modified_tanimoto(): - a = np.array([1, 1, 0, 0, 1]) - b = np.array([0, 0, 0, 0, 1]) - expected = (1.6 / 9) + (1.4 / 6) - assert_equal(modified_tanimoto(a, b), expected) - - -def test_modified_tanimoto_all_ones(): - """Test the modified tanimoto function when input is all '1' bits""" - a = np.array([1, 1, 1, 1, 1]) - assert_equal(modified_tanimoto(a, a), 1) - - -def test_modified_tanimoto_all_zeroes(): - """Test the modified tanimoto function when input is all '0' bits""" - a = np.zeros(5) - assert_equal(modified_tanimoto(a, a), 1) - - -def test_modified_tanimoto_dimension_error(): - """Test modified tanimoto raises error when input has incorrect dimension.""" - a = np.zeros([7, 5]) - b = np.zeros(5) - assert_raises(ValueError, modified_tanimoto, a, b) - assert_raises(ValueError, modified_tanimoto, b, a) - assert_raises(ValueError, modified_tanimoto, np.ones(3), np.ones(5)) - - -def test_modified_tanimoto_matrix(): - """Testing the modified tanimoto function with predefined feature matrix.""" - x = np.array([[1, 0, 1], [0, 1, 1]]) - s = pairwise_similarity_bit(x, "modified_tanimoto") - expected = np.array([[1, (4 / 27)], [(4 / 27), 1]]) - assert_equal(s, expected) - - -def test_scaled_similarity_matrix(): - """Testing scaled similarity matrix function with a predefined similarity matrix.""" - X = np.array([[4, 2, 3], [0.5, 1, 1.5], [3, 3, 9]]) - s = scaled_similarity_matrix(X) - expected = np.array([[1, 1, 0.5], [0.25, 1, 0.5], [0.5, 1, 1]]) - assert_equal(s, expected) - - -def test_scaled_similarity_matrix_dimension_error(): - """Test scaled similarity matrix raises error when input has incorrect dimension.""" - X = np.array([[1, 0.8, 0.65], [0.8, 1, 0.47]]) - assert_raises(ValueError, scaled_similarity_matrix, X) - - -def test_scaled_similarity_matrix_diagonal_zero_error(): - """Test scaled similarity matrix raises error when diagonal element is zero.""" - X = np.array([[1, 0.8, 0.65], [0.8, 0, 0.47], [0.65, 0.47, 1]]) - assert_raises(ValueError, scaled_similarity_matrix, X) - - -def test_scaled_similarity_matrix_element_negative_error(): - """Test scaled similarity matrix raises error when any element is negative.""" - X = np.array([[1, 0.8, 0.65], [-0.8, 1, 0.47], [0.65, 0.47, 1]]) - assert_raises(ValueError, scaled_similarity_matrix, X) - - -def test_SimilarityIndex_init_raises(): - """Test the SimilarityIndex class for raised errors (initialization).""" - # check raised error wrong similarity index name - with pytest.raises(ValueError): - SimilarityIndex(method="esim", sim_index="ttt") - # check raised error wrong c_threshold - invalid string value - with pytest.raises(ValueError): - SimilarityIndex(method="esim", c_threshold="ttt") - # check raised error wrong c_threshold - invalid type (not int) - with pytest.raises(ValueError): - SimilarityIndex(method="esim", c_threshold=1.1) - - -def test_SimilarityIndex_calculate_counters_raises(): - sim_idx = SimilarityIndex(method="esim") - - # check raised error wrong data type - with pytest.raises(TypeError): - sim_idx._calculate_counters(X=[1, 2, 3]) - - # check raised error - no n_objects with data of length 1 - with pytest.raises(ValueError): - sim_idx._calculate_counters(X=np.array([1, 2, 3])) - - # check raised error - c_threshold bigger than n_objects - sim_idx = SimilarityIndex(method="esim", c_threshold=3) - with pytest.raises(ValueError): - sim_idx._calculate_counters(X=np.array([[1, 2, 3], [4, 5, 6]])) - - # check raised error - invalid c_threshold string value - sim_idx = SimilarityIndex(method="esim") - sim_idx.c_threshold = "ttt" - with pytest.raises(ValueError): - sim_idx._calculate_counters(X=np.array([[1, 2, 3], [4, 5, 6]])) - - # check raised error - invalid weight factor string value - sim_idx = SimilarityIndex(method="esim") - sim_idx.w_factor = "ttt" - with pytest.raises(ValueError): - sim_idx._calculate_counters(X=np.array([[1, 2, 3], [4, 5, 6]])) - - -def test_SimilarityIndex_call_raises(): - """Test the SimilarityIndex class for raised errors (call).""" - sim_idx = SimilarityIndex() - # check raised error wrong data type - with pytest.raises(TypeError): - sim_idx(X=[1, 2, 3]) - # check raised error - no n_objects with data of length 1 - with pytest.raises(ValueError): - sim_idx(X=np.array([1, 2, 3])) - - -def test_SimilarityIndex_calculate_medoid_raises(): - """Test the SimilarityIndex class for raised errors (calculate_medoid).""" - sim_idx = NSimilarity() - - # check raised error wrong data type - with pytest.raises(TypeError): - sim_idx.calculate_medoid(X=[1, 2, 3]) - - # check raised error - no medoid with one dimensional data - with pytest.raises(ValueError): - sim_idx.calculate_medoid(X=np.array([1, 2, 3])) - - # check raised error - no medoid with less than three samples - with pytest.raises(ValueError): - sim_idx.calculate_medoid(X=np.array([[1, 2, 3], [4, 5, 6]])) - - # check raised error - c_threshold bigger than n_objects - sim_idx = NSimilarity(method="esim", c_threshold=4) - with pytest.raises(ValueError): - sim_idx.calculate_medoid(X=np.array([[1, 2, 3], [4, 5, 6], [6, 7, 8]])) - - # check raised error - c_total and data have different number of columns - sim_idx = NSimilarity() - with pytest.raises(ValueError): - sim_idx.calculate_medoid( - X=np.array([[1, 2, 3], [4, 5, 6], [6, 7, 8]]), c_total=np.array([1, 2, 3, 4]) - ) - - -def test_SimilarityIndex_calculate_outlier_raises(): - """Test the SimilarityIndex class for raised errors (calculate_outlier).""" - sim_idx = NSimilarity() - - # check raised error wrong data type - with pytest.raises(TypeError): - sim_idx.calculate_outlier(X=[1, 2, 3]) - - # check raised error - no medoid with one dimensional data - with pytest.raises(ValueError): - sim_idx.calculate_outlier(X=np.array([1, 2, 3])) - - # check raised error - no medoid with less than three samples - with pytest.raises(ValueError): - sim_idx.calculate_outlier(X=np.array([[1, 2, 3], [4, 5, 6]])) - - # check raised error - c_threshold bigger than n_objects - sim_idx = NSimilarity(method="esim", c_threshold=4) - with pytest.raises(ValueError): - sim_idx.calculate_outlier(X=np.array([[1, 2, 3], [4, 5, 6], [6, 7, 8]])) - - # check raised error - c_total and data have different number of columns - sim_idx = NSimilarity() - with pytest.raises(ValueError): - sim_idx.calculate_outlier( - X=np.array([[1, 2, 3], [4, 5, 6], [6, 7, 8]]), c_total=np.array([1, 2, 3, 4]) - ) - - -def test_NSimilarity_init_raises(): - """Test the NSimilarity class for raised errors (initialization).""" - # check raised error wrong similarity index name - with pytest.raises(ValueError): - NSimilarity(similarity_index="ttt") - # check raised error wrong c_threshold - invalid string value - with pytest.raises(ValueError): - NSimilarity(method="esim", c_threshold="ttt") - # check raised error wrong c_threshold - invalid type (not int) - with pytest.raises(ValueError): - NSimilarity(method="esim", c_threshold=1.1) - - -def test_NSimilarity_get_new_index_raises(): - """Test the NSimilarity class for raised errors (get_new_index).""" - # check that data is not scaled between 0 and 1 - with pytest.raises(ValueError): - NSimilarity()._get_new_index( - X=np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]), - num_selected=1, - selected_condensed=np.array([1, 2, 3]), - select_from=np.array([1, 2, 3]), - ) - - -def test_NSimilarity_select_from_cluster_raises(): - """Test the NSimilarity class for raised errors (select_from_cluster).""" - data_array = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) - cluster_ids = np.array([0, 1, 2]) - with pytest.raises(ValueError): - # select more samples than the number of samples in the cluster - NSimilarity().select_from_cluster(X=data_array, size=5) - with pytest.raises(ValueError): - # start from sample index that is not in the cluster - NSimilarity().select_from_cluster(X=data_array, size=2, start=[4]) - with pytest.raises(ValueError): - # start from sample index that is not in the cluster - NSimilarity().select_from_cluster(X=data_array, size=2, start=[4]) - with pytest.raises(ValueError): - # start from invalid string value of start - NSimilarity().select_from_cluster(X=data_array, size=2, start="ttt") - with pytest.raises(ValueError): - # start from invalid type of start - NSimilarity().select_from_cluster(X=data_array, size=2, start=[1.2]) - with pytest.raises(ValueError): - # try to data not scaled between 0 and 1 - NSimilarity(preprocess_data=False).select_from_cluster(X=data_array, size=2) - with pytest.raises(ValueError): - # try to use starting index that is not in the cluster - NSimilarity().select_from_cluster(X=data_array, size=2, start=[4], labels=cluster_ids) - with pytest.raises(ValueError): - # try to use invalid starting index - NSimilarity().select_from_cluster(X=data_array, size=2, start=4.2, labels=cluster_ids) - - -# --------------------------------------------------------------------------------------------- # -# Tests for the function results of the SimilarityIndex and NSimilarity classes. -# --------------------------------------------------------------------------------------------- # -# The following part tests the results of the SimilarityIndex and NSimilarity classes methods -# for a set of binary data. The proper results for the tests are known in advance. - -# Tests for binary data. -# --------------------------------------------------------------------------------------------- # - -# --------------------------------------------------------------------------------------------- # -# Section of the test for the SimilarityIndex class using binary data and esim method. -# --------------------------------------------------------------------------------------------- # - - -def _get_binary_data(): - """Returns a list of binary strings. - - The proper results for the tests are known in advance. - - Returns - ------- - list of lists - A list of binary objects lists. - """ - - # Binary data to perform the tests, it contains 100 lists of 12 elements each - # The proper results for the tests are known in advance. - data = np.array( - [ - [0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1], - [1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1], - [1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0], - [0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1], - [0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1], - [1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0], - [1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1], - [0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0], - [0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1], - [0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1], - [1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0], - [1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1], - [1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0], - [1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1], - [1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0], - [1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1], - [1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0], - [1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0], - [1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1], - [0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1], - [1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0], - [0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1], - [0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0], - [1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1], - [1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1], - [1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1], - [1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0], - [0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0], - [1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0], - [0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0], - [1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1], - [0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0], - [0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1], - [0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0], - [0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1], - [1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0], - [1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0], - [0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0], - [1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1], - [1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0], - [0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1], - [1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0], - [1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0], - [0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0], - [0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0], - [1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1], - [1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1], - [0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0], - [0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0], - [1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1], - [0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0], - [1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0], - [0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0], - [0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1], - [0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0], - [0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1], - [0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0], - [1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1], - [0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0], - [0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0], - [1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0], - [1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0], - [0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0], - [0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0], - [0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0], - [0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0], - [1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0], - [1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0], - [0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1], - [0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0], - [1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0], - [0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1], - [0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1], - [1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0], - [1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1], - [1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0], - [1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0], - [1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1], - [0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0], - [1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0], - [1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0], - [1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1], - [1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0], - [0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1], - [0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1], - [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0], - [0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0], - [0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1], - [1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1], - [0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1], - [0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0], - [0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1], - [1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0], - [1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0], - [1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1], - [1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1], - [1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0], - [0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1], - [0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1], - [0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1], - ] - ) - - return data - - -def _get_ref_similarity_esim_dict(): - """Returns a dictionary with the reference values for the similarity indexes. - - The proper results for the tests are known in advance and are stored in a dictionary. - - Returns - ------- - dict - A dictionary with the reference values for the similarity indexes. The dictionary has the - following structure: - {w_factor: {c_threshold: {n_ary: value}}} where: - w_factor: the weight factor for the similarity index - c_threshold: the threshold value for the similarity index - """ - - # Reference values for the similarity index. - ref_similarity_binary = { - "fraction": { - "None": { - "AC": 0.1597619835634367, - "BUB": 0.06891469248218901, - "CT1": 0.21594387881973748, - "CT2": 0.12273565515991067, - "CT3": 0.09010381444416192, - "CT4": 0.1435977860207451, - "Fai": 0.041666666666666664, - "Gle": 0.07428571428571429, - "Ja": 0.078, - "Ja0": 0.06529411764705882, - "JT": 0.065, - "RT": 0.05692307692307692, - "RR": 0.021666666666666667, - "SM": 0.06166666666666667, - "SS1": 0.052000000000000005, - "SS2": 0.06434782608695652, - }, - "dissimilar": { - "AC": 0.0, - "BUB": 0.0, - "CT1": 0.0, - "CT2": 0.0, - "CT3": 0.0, - "CT4": 0.0, - "Fai": 0.0, - "Gle": 0.0, - "Ja": 0.0, - "Ja0": 0.0, - "JT": 0.0, - "RT": 0.0, - "RR": 0.0, - "SM": 0.0, - "SS1": 0.0, - "SS2": 0.0, - }, - 5: { - "AC": 0.13861833940391668, - "BUB": 0.043638272469757794, - "CT1": 0.173370214880788, - "CT2": 0.02399965239873406, - "CT3": 0.07108193238341105, - "CT4": 0.0791812460476248, - "Fai": 0.03166666666666667, - "Gle": 0.04, - "Ja": 0.05454545454545456, - "Ja0": 0.084, - "JT": 0.022222222222222223, - "RT": 0.028000000000000004, - "RR": 0.016666666666666666, - "SM": 0.04666666666666667, - "SS1": 0.011764705882352941, - "SS2": 0.07, - }, - }, - "power_3": { - "None": { - "AC": 1.5127728116149686e-20, - "BUB": 7.90100730602568e-40, - "CT1": 0.0, - "CT2": 0.0, - "CT3": 0.0, - "CT4": 0.0, - "Fai": 5.6422575986042295e-40, - "Gle": 1.9329988216613272e-39, - "Ja": 2.029648762744394e-39, - "Ja0": 5.978755024266622e-40, - "JT": 1.6913739689536614e-39, - "RT": 5.212247969873465e-40, - "RR": 5.6379132298455384e-40, - "SM": 5.646601967362921e-40, - "SS1": 1.3530991751629292e-39, - "SS2": 5.892106400726526e-40, - }, - "dissimilar": { - "AC": 0.0, - "BUB": 0.0, - "CT1": 0.0, - "CT2": 0.0, - "CT3": 0.0, - "CT4": 0.0, - "Fai": 0.0, - "Gle": 0.0, - "Ja": 0.0, - "Ja0": 0.0, - "JT": 0.0, - "RT": 0.0, - "RR": 0.0, - "SM": 0.0, - "SS1": 0.0, - "SS2": 0.0, - }, - 5: { - "AC": 1.5127727667796592e-20, - "BUB": 6.551485125947553e-40, - "CT1": 0.0, - "CT2": 0.0, - "CT3": 0.0, - "CT4": 0.0, - "Fai": 5.642257358488985e-40, - "Gle": 1.3530991402370754e-39, - "Ja": 1.8451351912323755e-39, - "Ja0": 1.0163882938782278e-39, - "JT": 7.517217445761529e-40, - "RT": 3.387960979594093e-40, - "RR": 5.637913084321148e-40, - "SM": 5.646601632656821e-40, - "SS1": 3.979703353638457e-40, - "SS2": 8.469902448985232e-40, - }, - }, - } - - return ref_similarity_binary - - -def _get_ref_isim_dict(): - """Returns a dictionary with the reference values necessary for testing the isim method. - - The proper results for the tests are known in advance and are stored in a dictionary. - - Returns - ------- - dict - A dictionary with the reference values necessary for all the isim method tests. The - dictionary has the following structure: - {n_ary: { outlier: value, medoid: value, kval2si: {k: value}}} where: - n_ary: the similarity index name used - outlier: the index of the outlier sample - medoid: the index of the medoid sample - kval2si: a dictionary with the k value as key and the similarity index as value - """ - isim_dict = { - "AC": { - "outlier": 49, - "medoid": 96, - "kval2si": { - 1: 0.49917475122243926, - 2: 0.5538883964836272, - 5: 0.5866150284585204, - 10: 0.5974286117693461, - }, - }, - "BUB": { - "outlier": 85, - "medoid": 10, - "kval2si": { - 1: 0.49397989672931264, - 2: 0.5819613020487422, - 5: 0.6335183244648649, - 10: 0.6502407823406905, - }, - }, - "CT1": { - "outlier": 49, - "medoid": 96, - "kval2si": { - 1: 0.9367065121244419, - 2: 0.9261583241959612, - 5: 0.9107923779571723, - 10: 0.902405671341302, - }, - }, - "CT2": { - "outlier": 49, - "medoid": 96, - "kval2si": { - 1: 0.06282178200501828, - 2: 0.12056333324739296, - 5: 0.19665579893673796, - 10: 0.23722036836219337, - }, - }, - "CT3": { - "outlier": 85, - "medoid": 10, - "kval2si": { - 1: 0.870243523865252, - 2: 0.82843367496858, - 5: 0.77434619420322, - 10: 0.7461466827474635, - }, - }, - "CT4": { - "outlier": 85, - "medoid": 10, - "kval2si": { - 1: 0.8945856132657759, - 2: 0.8706848775823933, - 5: 0.8375702929632953, - 10: 0.8197597232141359, - }, - }, - "Fai": { - "outlier": 85, - "medoid": 10, - "kval2si": { - 1: 0.36944444444444446, - 2: 0.4354778372150966, - 5: 0.47461264224551747, - 10: 0.4873954166765502, - }, - }, - "Gle": { - "outlier": 85, - "medoid": 10, - "kval2si": { - 1: 0.48934163365402755, - 2: 0.579696056605444, - 5: 0.6326571892686095, - 10: 0.6498200476852635, - }, - }, - "Ja": { - "outlier": 85, - "medoid": 10, - "kval2si": { - 1: 0.5897241588360109, - 2: 0.6741446014011255, - 5: 0.7209338061721255, - 10: 0.735695295519683, - }, - }, - "Ja0": { - "outlier": 49, - "medoid": 96, - "kval2si": { - 1: 0.7490265158538847, - 2: 0.8082737370566611, - 5: 0.8388469288245588, - 10: 0.8482013298830383, - }, - }, - "JT": { - "outlier": 85, - "medoid": 10, - "kval2si": { - 1: 0.3239260739260739, - 2: 0.4081492974102138, - 5: 0.4626909830536219, - 10: 0.48128402926677866, - }, - }, - "RT": { - "outlier": 49, - "medoid": 96, - "kval2si": { - 1: 0.3321820648822006, - 2: 0.41267273273100585, - 5: 0.4645381672067039, - 10: 0.48220837765022756, - }, - }, - "RR": { - "outlier": 85, - "medoid": 10, - "kval2si": { - 1: 0.2401851851851852, - 2: 0.2867117470582547, - 5: 0.3148435010613659, - 10: 0.3241287740619748, - }, - }, - "SM": { - "outlier": 49, - "medoid": 96, - "kval2si": { - 1: 0.4987037037037037, - 2: 0.5842439273719385, - 5: 0.6343817834296691, - 10: 0.6506620592911254, - }, - }, - "SS1": { - "outlier": 85, - "medoid": 10, - "kval2si": { - 1: 0.19326478915213827, - 2: 0.25639923187909175, - 5: 0.3009746107992553, - 10: 0.3169019346220607, - }, - }, - "SS2": { - "outlier": 49, - "medoid": 96, - "kval2si": { - 1: 0.6655134066477203, - 2: 0.7375681450029299, - 5: 0.7762957099270287, - 10: 0.7883649540846069, - }, - }, - } - return isim_dict - - -def _get_absolute_decimal_places_for_comparison(num1, num2, rtol=1e-4): - """Calculate the absolute number of decimal places needed for comparison of two numbers. - - Calculate the absolute number of decimal places needed for assert_almost_equal of two numbers - with a relative tolerance of rtol. - - Parameters - ---------- - num1 : float - First number. - num2 : float - Second number. - rtol : float - Relative tolerance. - """ - max_num = max(abs(num1), abs(num2)) - - # If both numbers are zero, return 5 decimal places just to avoid division by zero. Both numbers - # are zero (and therefore equal) withing the machine precision. - if max_num == 0: - return 5 - - # Calculate the dynamic tolerance based on the magnitudes of the numbers - tol = rtol * max(abs(num1), abs(num2)) - - return abs(int(np.log10(tol))) - - -# Parameter values for the tests -c_treshold_values = [None, "dissimilar", 5] -w_factor_values = ["fraction", "power_3"] -n_ary_values = [ - "AC", - "BUB", - "CT1", - "CT2", - "CT3", - "CT4", - "Fai", - "Gle", - "Ja", - "Ja0", - "JT", - "RT", - "RR", - "SM", - "SS1", - "SS2", -] - - -@pytest.mark.parametrize("c_threshold", c_treshold_values) -@pytest.mark.parametrize("w_factor", w_factor_values) -@pytest.mark.parametrize("n_ary", n_ary_values) -def test_SimilarityIndex_esim_call(c_threshold, w_factor, n_ary): - """Test the similarity index for binary data. - - Test the similarity index for binary data using the reference values and several combinations - of parameters. - - Parameters - ---------- - c_threshold : float - The threshold value for the similarity index. - w_factor : float - The weight factor for the similarity index. - n_ary : str - The similarity index to use. - """ - - # get the binary data - data, ref_similarity_binary = _get_binary_data(), _get_ref_similarity_esim_dict() - - # create instance of the class SimilarityIndex to test the similarity indexes for binary data - sim_idx = SimilarityIndex( - method="esim", sim_index=n_ary, c_threshold=c_threshold, w_factor=w_factor - ) - - # calculate the similarity index for the binary data - sim_idx_value = sim_idx(data) - - # get the reference value for the similarity index - if c_threshold is None: - c_threshold = "None" - ref_value = ref_similarity_binary[w_factor][c_threshold][n_ary] - - # calculate the absolute tolerance based on the relative tolerance and the numbers magnitude - tol = _get_absolute_decimal_places_for_comparison(sim_idx_value, ref_value) - - # check that the calculated value is equal to the reference value - assert_almost_equal(sim_idx_value, ref_value, decimal=tol) - - -# --------------------------------------------------------------------------------------------- # -# Section of the tests for selection of indexes functions using binary data and esim method. -# --------------------------------------------------------------------------------------------- # - -# Many of the combinations of parameters for the tests are too stringent and the similarity of the -# samples is zero. These cases are not considered because will produce inconsistent results for the -# selection of the new indexes, and the calculation of the medoid and the outlier. - -# Creating the possible combinations of the parameters for the tests. The combinations are stored -# in a list of tuples. Each tuple has the following structure: (w_factor, c_threshold, n_ary) -# where: -# w_factor: the weight factor for the similarity index -# c_threshold: the threshold value for the similarity index -# n_ary: the similarity index to use - - -# The cases where the similarity of the samples is zero are not considered because these will be -# inconsistent with the reference values for the selection of the new indexes, and the calculation -# of the medoid and the outlier. -def _get_esim_test_parameters(): - """Returns the parameters for the tests. - - Returns the parameters for the tests. The parameters are stored in a list of tuples. Each tuple - has the following structure: (w_factor, c_threshold, n_ary) where: - w_factor: the weight factor for the similarity index - c_threshold: the threshold value for the similarity index - n_ary: the similarity index to use - - Returns - ------- - list - A list of tuples with the parameters for the tests. Each tuple has the following structure: - (w_factor, c_threshold, n_ary) where: - w_factor: the weight factor for the similarity index - c_threshold: the threshold value for the similarity index - n_ary: the similarity index to use - """ - # The cases where the similarity of the samples is zero are not considered because these will be - # inconsistent with the reference values for the selection of the new indexes, and the - # calculation of the medoid and the outlier. - test_parameters = [] - for w in w_factor_values: - for c in c_treshold_values: - # small hack to avoid using the None value as a key in the dictionary - c_key = c - if c is None: - c_key = "None" - for n in n_ary_values: - # ignore the cases where the similarity of the samples less than two percent - if not _get_ref_similarity_esim_dict()[w][c_key][n] < 0.02: - test_parameters.append((c, w, n)) - - return test_parameters - - -parameters = _get_esim_test_parameters() - - -def _get_ref_medoid_esim_dict(): - """Returns dictionary with reference medoid index for binary data using esim method. - - The proper results for the tests are known in advance and are stored in a dictionary. - - The dictionary has the following structure: - {w_factor: {c_threshold: {n_ary: value}}} where: - w_factor: the weight factor for the similarity index - c_threshold: the threshold value for the similarity index - - The medoid values are stored for all possible combinations of the following parameter values: - - w_factor: None, dissimilar, 5 - - c_threshold: fraction, power_3 - - n_ary: AC, BUB, CT1, CT2, CT3, CT4, Fai, Gle, Ja, Ja0, JT, RT, RR, SM, SS1, SS2 - - - Returns - ------- - dict - A dictionary with the reference values for the medoid. The dictionary has the - following structure: - {w_factor: {c_threshold: {n_ary: value}}} where: - w_factor: the weight factor for the similarity index - c_threshold: the threshold value for the similarity index - """ - medoid_ref_dict = { - "None": { - "fraction": { - "AC": 96, - "BUB": 69, - "CT1": 96, - "CT2": 80, - "CT3": 1, - "CT4": 23, - "Fai": 96, - "Gle": 69, - "Ja": 69, - "Ja0": 50, - "JT": 69, - "RT": 96, - "RR": 1, - "SM": 96, - "SS1": 23, - "SS2": 50, - }, - "power_3": { - "AC": 96, - "BUB": 48, - "CT1": 0, - "CT2": 0, - "CT3": 0, - "CT4": 0, - "Fai": 96, - "Gle": 69, - "Ja": 69, - "Ja0": 50, - "JT": 69, - "RT": 96, - "RR": 1, - "SM": 96, - "SS1": 69, - "SS2": 50, - }, - }, - "dissimilar": { - "fraction": { - "AC": 0, - "BUB": 0, - "CT1": 0, - "CT2": 0, - "CT3": 0, - "CT4": 0, - "Fai": 0, - "Gle": 0, - "Ja": 0, - "Ja0": 0, - "JT": 0, - "RT": 0, - "RR": 0, - "SM": 0, - "SS1": 0, - "SS2": 0, - }, - "power_3": { - "AC": 0, - "BUB": 0, - "CT1": 0, - "CT2": 0, - "CT3": 0, - "CT4": 0, - "Fai": 0, - "Gle": 0, - "Ja": 0, - "Ja0": 0, - "JT": 0, - "RT": 0, - "RR": 0, - "SM": 0, - "SS1": 0, - "SS2": 0, - }, - }, - 5: { - "fraction": { - "AC": 39, - "BUB": 39, - "CT1": 39, - "CT2": 96, - "CT3": 0, - "CT4": 0, - "Fai": 39, - "Gle": 0, - "Ja": 0, - "Ja0": 39, - "JT": 0, - "RT": 39, - "RR": 0, - "SM": 39, - "SS1": 0, - "SS2": 39, - }, - "power_3": { - "AC": 39, - "BUB": 39, - "CT1": 0, - "CT2": 0, - "CT3": 0, - "CT4": 0, - "Fai": 39, - "Gle": 0, - "Ja": 0, - "Ja0": 39, - "JT": 0, - "RT": 39, - "RR": 0, - "SM": 39, - "SS1": 0, - "SS2": 39, - }, - }, - } - - return medoid_ref_dict - - -@pytest.mark.parametrize("c_threshold, w_factor, n_ary", parameters) -def test_calculate_medoid_esim(c_threshold, w_factor, n_ary): - """Test the function to calculate the medoid for binary data using esim method. - - Test the function to calculate the medoid for binary data using the reference values and several - combinations of parameters. The reference values are obtained using the function - _get_ref_medoid_dict(). - - Parameters - ---------- - c_threshold : float - The threshold value for the similarity index. - w_factor : float - The weight factor for the similarity index. - n_ary : str - The similarity index to use. - """ - - # get the reference binary data - data = _get_binary_data() - # get the reference value for the medoid - ref_medoid_dict = _get_ref_medoid_esim_dict() - - # small hack to avoid using the None value as a key in the dictionary - c_threshold_key = c_threshold - if c_threshold is None: - c_threshold_key = "None" - - ref_medoid = ref_medoid_dict[c_threshold_key][w_factor][n_ary] - - # calculate the medoid for the binary data - sim_idx = NSimilarity( - method="esim", similarity_index=n_ary, c_threshold=c_threshold, w_factor=w_factor - ) - medoid = sim_idx.calculate_medoid(X=data) - - # check that the calculated medoid is equal to the reference medoid - assert_equal(medoid, ref_medoid) - - -# results from the reference code -def _get_ref_outlier_esim_dict(): - """Returns dictionary with reference outlier index for binary data using esim method. - - The proper results for the tests are known in advance and are stored in a dictionary. - - The dictionary has the following structure: - {w_factor: {c_threshold: {n_ary: value}}} where: - w_factor: the weight factor for the similarity index - c_threshold: the threshold value for the similarity index - - The outlier values are stored for all possible combinations of the following parameter values: - - w_factor: None, dissimilar, 5 - - c_threshold: fraction, power_3 - - n_ary: AC, BUB, CT1, CT2, CT3, CT4, Fai, Gle, Ja, Ja0, JT, RT, RR, SM, SS1, SS2 - - - Returns - ------- - dict - A dictionary with the reference values for the outlier. The dictionary has the - following structure: - {w_factor: {c_threshold: {n_ary: value}}} where: - w_factor: the weight factor for the similarity index - c_threshold: the threshold value for the similarity index - """ - oulier_ref_dict = { - "None": { - "fraction": { - "AC": 4, - "BUB": 34, - "CT1": 4, - "CT2": 4, - "CT3": 8, - "CT4": 34, - "Fai": 34, - "Gle": 34, - "Ja": 34, - "Ja0": 49, - "JT": 34, - "RT": 4, - "RR": 8, - "SM": 4, - "SS1": 34, - "SS2": 49, - }, - "power_3": { - "AC": 49, - "BUB": 57, - "CT1": 0, - "CT2": 0, - "CT3": 0, - "CT4": 0, - "Fai": 49, - "Gle": 34, - "Ja": 16, - "Ja0": 80, - "JT": 34, - "RT": 4, - "RR": 8, - "SM": 49, - "SS1": 34, - "SS2": 80, - }, - }, - "dissimilar": { - "fraction": { - "AC": 0, - "BUB": 0, - "CT1": 0, - "CT2": 0, - "CT3": 0, - "CT4": 0, - "Fai": 0, - "Gle": 0, - "Ja": 0, - "Ja0": 0, - "JT": 0, - "RT": 0, - "RR": 0, - "SM": 0, - "SS1": 0, - "SS2": 0, - }, - "power_3": { - "AC": 0, - "BUB": 0, - "CT1": 0, - "CT2": 0, - "CT3": 0, - "CT4": 0, - "Fai": 0, - "Gle": 0, - "Ja": 0, - "Ja0": 0, - "JT": 0, - "RT": 0, - "RR": 0, - "SM": 0, - "SS1": 0, - "SS2": 0, - }, - }, - 5: { - "fraction": { - "AC": 49, - "BUB": 49, - "CT1": 49, - "CT2": 57, - "CT3": 2, - "CT4": 2, - "Fai": 49, - "Gle": 2, - "Ja": 2, - "Ja0": 49, - "JT": 2, - "RT": 49, - "RR": 2, - "SM": 49, - "SS1": 2, - "SS2": 49, - }, - "power_3": { - "AC": 49, - "BUB": 49, - "CT1": 0, - "CT2": 0, - "CT3": 0, - "CT4": 0, - "Fai": 49, - "Gle": 2, - "Ja": 2, - "Ja0": 49, - "JT": 2, - "RT": 49, - "RR": 2, - "SM": 49, - "SS1": 2, - "SS2": 49, - }, - }, - } - - return oulier_ref_dict - - -@pytest.mark.parametrize("c_threshold, w_factor, n_ary", parameters) -def test_calculate_outlier_esim(c_threshold, w_factor, n_ary): - """Test the function to calculate the outlier for binary data using the esim method. - - Test the function to calculate the outlier for binary data using the reference values and - several combinations of parameters. The reference values are obtained using the function - _get_ref_outlier_dict(). - - Parameters - ---------- - c_threshold : float - The threshold value for the similarity index. - w_factor : float - The weight factor for the similarity index. - n_ary : str - The similarity index to use. - """ - - # get the reference binary data - data = _get_binary_data() - # get the reference value for the outlier - ref_outlier_dict = _get_ref_outlier_esim_dict() - - # small hack to avoid using the None value as a key in the dictionary - c_threshold_key = c_threshold - if c_threshold is None: - c_threshold_key = "None" - - ref_outlier = ref_outlier_dict[c_threshold_key][w_factor][n_ary] - - # calculate the outlier for the binary data - sim_idx = NSimilarity( - method="esim", similarity_index=n_ary, c_threshold=c_threshold, w_factor=w_factor - ) - outlier = sim_idx.calculate_outlier(X=data) - - # check that the calculated outlier is equal to the reference outlier - assert_equal(outlier, ref_outlier) - - -# --------------------------------------------------------------------------------------------- # -# Section of the tests for selection of indexes functions using binary data and isim method. -# --------------------------------------------------------------------------------------------- # -# test medoid selection -si_idcs = [ - "AC", - "BUB", - "CT1", - "CT2", - "CT3", - "CT4", - "Fai", - "Gle", - "Ja", - "Ja0", - "JT", - "RT", - "RR", - "SM", - "SS1", - "SS2", -] - - -@pytest.mark.parametrize("sim_idx", si_idcs) -def test_calculate_medoid_isim(sim_idx): - data = _get_binary_data() - isim_dict = _get_ref_isim_dict() - ref_medoid = isim_dict[sim_idx]["medoid"] - sim_idx = NSimilarity(method="isim", similarity_index=sim_idx) - medoid = sim_idx.calculate_medoid(X=data) - assert_equal(medoid, ref_medoid) - - -# test outlier selection -@pytest.mark.parametrize("sim_idx", si_idcs) -def test_calculate_outlier_isim(sim_idx): - data = _get_binary_data() - isim_dict = _get_ref_isim_dict() - ref_medoid = isim_dict[sim_idx]["outlier"] - sim_idx = NSimilarity(method="isim", similarity_index=sim_idx) - medoid = sim_idx.calculate_outlier(X=data) - assert_equal(medoid, ref_medoid) - - -# --------------------------------------------------------------------------------------------- # -# Section of the test for the NSimilarity class using binary data and esim method. -# --------------------------------------------------------------------------------------------- # -def _get_ref_new_index_esim(): - """ - Returns reference data for testing the function to calculate the new index with the esim method. - - Returns the tuple (selected_points, new_indexes_dict) where selected_points is a list of - selected samples given to the function (get_new_index) and new_indexes_dict is a dictionary - with the reference values for the new index to be selected based on the previously selected - indices and the other function parameters. - - Returns - ------- - tuple (list, dict) - A tuple with the reference data for testing the function to calculate the new index. The - tuple has the following structure: - (selected_points, new_indexes_dict) where: - selected_points: a list of selected samples given to the function (get_new_index) - new_indexes_dict: a dictionary with the reference values for the new index to be - selected based on the previously selected indices and the other function - parameters. The dictionary has the following structure: - {w_factor: {c_threshold: {n_ary: value}}} where: - w_factor: the weight factor for the similarity index - c_threshold: the threshold value for the similarity index - n_ary: the similarity index to use - - """ - - # The selected points to be given to the function (get_new_index) - selected_samples = [0, 9, 19, 29, 39, 49, 59, 69, 79, 89, 99] - # The reference values for the new index to be selected based on the previously selected - # indices and the other function parameters. - new_index_dict = { - "None": { - "fraction": { - "AC": 62, - "BUB": 62, - "CT1": 62, - "CT2": 62, - "CT3": 2, - "CT4": 44, - "Fai": 62, - "Gle": 44, - "Ja": 44, - "Ja0": 62, - "JT": 44, - "RT": 62, - "RR": 2, - "SM": 62, - "SS1": 44, - "SS2": 62, - }, - "power_3": { - "AC": 67, - "BUB": 11, - "CT1": 67, - "CT2": 20, - "CT3": 2, - "CT4": 44, - "Fai": 11, - "Gle": 44, - "Ja": 44, - "Ja0": 11, - "JT": 44, - "RT": 67, - "RR": 2, - "SM": 67, - "SS1": 44, - "SS2": 11, - }, - }, - 5: { - "fraction": { - "AC": 2, - "BUB": 2, - "CT1": 2, - "CT2": 2, - "CT3": 2, - "CT4": 2, - "Fai": 2, - "Gle": 2, - "Ja": 2, - "Ja0": 2, - "JT": 2, - "RT": 2, - "RR": 2, - "SM": 2, - "SS1": 2, - "SS2": 2, - }, - "power_3": { - "AC": 2, - "BUB": 2, - "CT1": 2, - "CT2": 2, - "CT3": 2, - "CT4": 2, - "Fai": 2, - "Gle": 2, - "Ja": 2, - "Ja0": 2, - "JT": 2, - "RT": 2, - "RR": 2, - "SM": 2, - "SS1": 2, - "SS2": 2, - }, - }, - } - - return selected_samples, new_index_dict - - -@pytest.mark.parametrize("c_threshold, w_factor, n_ary", parameters) -def test_get_new_index_esim(c_threshold, w_factor, n_ary): - """Test the function get a new sample from the binary data. - - Test the function to get a new sample from the binary data using the reference values and - several combinations of parameters. The reference values are obtained using the function - _get_ref_new_index(). - - Parameters - ---------- - c_threshold : float - The threshold value for the similarity index. - w_factor : float - The weight factor for the similarity index. - n_ary : str - The similarity index to use. - """ - - # get the reference binary data - data = _get_binary_data() - # get the reference value for the outlier - selected_samples, ref_new_index_dict = _get_ref_new_index_esim() - - # columnwise sum of the selected samples - selected_condensed_data = np.sum(np.take(data, selected_samples, axis=0), axis=0) - # indices of the samples to select from - select_from_n = [i for i in range(len(data)) if i not in selected_samples] - # number of samples that are already selected - n = len(selected_samples) - - # small hack to avoid using the None value as a key in the dictionary - c_threshold_key = c_threshold - if c_threshold is None: - c_threshold_key = "None" - - ref_new_index = ref_new_index_dict[c_threshold_key][w_factor][n_ary] - - # calculate the outlier for the binary data - nsi = NSimilarity( - method="esim", similarity_index=n_ary, w_factor=w_factor, c_threshold=c_threshold - ) - - new_index = nsi._get_new_index( - X=data, - selected_condensed=selected_condensed_data, - select_from=select_from_n, - num_selected=n, - ) - - assert_equal(new_index, ref_new_index) - - -# --------------------------------------------------------------------------------------------- # -# Selecting a subset of the parameters generated for the tests -# --------------------------------------------------------------------------------------------- # - -# remove cases where c_threshold is 5. This is not a valid case for the selection of the next point -# if the number of selected samples is less than 5 -parameters = [x for x in parameters if not x[0] == 5] - -# The start parameter can be a list of elements that need to be selected first. -# The case of the three elements included in a selection 1, 2, 3 is tested. -start_values = ["medoid", "outlier", [1, 2, 3]] -# sample size values to test -sample_size_values = [10, 20, 30] - - -# --------------------------------------------------------------------------------------------- # -# Get reference data for testing the selection of the diverse subset -# --------------------------------------------------------------------------------------------- # -# get reference selected data for esim method -def _get_selections_esim_ref_dict(): - """Returns a dictionary with the reference values for the selection of samples. - - The proper results for the tests are known in advance and are stored in a csv file. - The file is read and the values are stored in a dictionary. The dictionary has the following - structure: - {w_factor: {c_threshold: {n_ary: {sample_size: {start: value}}}}} where: - w_factor: the weight factor for the similarity index - c_threshold: the threshold value for the similarity index - n_ary: the similarity index to use - sample_size: the number of samples to select - start: the method to use to select the first(s) sample(s) - """ - - file_path = get_data_file_path("ref_esim_selection_data.csv") - with open(file_path, encoding="utf-8") as file: - reader = csv.reader(file, delimiter=";") - next(reader) # skip header - # initialize the dictionary - data_dict = {} - - for row in reader: - # The first column is the c_threshold - data_dict[row[0]] = data_dict.get(row[0], {}) - # The second column is the w_factor - data_dict[row[0]][row[1]] = data_dict[row[0]].get(row[1], {}) - # The third column is the sample_size - data_dict[row[0]][row[1]][row[2]] = data_dict[row[0]][row[1]].get(row[2], {}) - # The fourth column is the start_idx - data_dict[row[0]][row[1]][row[2]][row[3]] = data_dict[row[0]][row[1]][row[2]].get( - row[3], {} - ) - # The fifth column stores the n_ary and the sixth column stores the reference value - data_dict[row[0]][row[1]][row[2]][row[3]][row[4]] = ast.literal_eval(row[5]) - return data_dict - - -# test selected data for esim method (inv_order=1) and binary data against reference data -@pytest.mark.parametrize("c_threshold, w_factor, n_ary", parameters) -@pytest.mark.parametrize("sample_size", sample_size_values) -@pytest.mark.parametrize("start", start_values) -def test_NSimilarity_esim_select(c_threshold, w_factor, sample_size, n_ary, start): - """ - Test the diversity selection methods based on similarity indexes for binary data. - - Parameters - ---------- - c_threshold : float - The threshold value for the similarity index. - w_factor : float - The weight factor for the similarity index. - sample_size : int - The number of molecules to select. - n_ary : str - The similarity index to use. - start : str - The method to use to select the first(s) sample(s). - - """ - - # get the binary data - data = _get_binary_data() - # get the reference selected data - reference_selected_data = _get_selections_esim_ref_dict() - - # create instance of the class SimilarityIndex to test the similarity indexes for binary data - collector = NSimilarity( - method="esim", - similarity_index=n_ary, - w_factor=w_factor, - c_threshold=c_threshold, - preprocess_data=False, - ) - # select the diverse subset using the similarity index - selected_data = collector.select_from_cluster(data, size=sample_size, start=start) - - # get the reference value for the similarity index - # transform invalid keys to strings - if c_threshold is None: - c_threshold = "None" - # transform sample_size to string (as it is used as a key in the dictionary) - sample_size = str(sample_size) - # lists of initial indexes are not valid keys in the dictionary (non hashable) - if isinstance(start, list): - start = str(start).replace(" ", "") - # get the reference list as a string - ref_list = reference_selected_data[c_threshold][w_factor][sample_size][start][n_ary] - - # check if the selected data has the same size as the reference data - assert_equal(len(selected_data), len(ref_list)) - - # check if the selected data is equal to the reference data - assert all(x in ref_list for x in selected_data) +# -*- coding: utf-8 -*- +# +# The Selector is a Python library of algorithms for selecting diverse +# subsets of data for machine-learning. +# +# Copyright (C) 2022-2024 The QC-Devs Community +# +# This file is part of Selector. +# +# Selector is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 +# of the License, or (at your option) any later version. +# +# Selector is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see +# +# -- +"""Test similarity.py.""" + +import ast +import csv +import importlib + +import numpy as np +import pytest +from numpy.testing import assert_almost_equal, assert_equal, assert_raises + +from selector.measures.similarity import ( + modified_tanimoto, + pairwise_similarity_bit, + scaled_similarity_matrix, + tanimoto, +) +from selector.methods.similarity import NSimilarity, SimilarityIndex +from selector.methods.tests.common import get_data_file_path + + +def test_pairwise_similarity_bit_raises(): + # check raised error for input feature matrix that is not 2D + assert_raises(ValueError, pairwise_similarity_bit, np.random.random(5), "tanimoto") + assert_raises(ValueError, pairwise_similarity_bit, np.random.random((2, 3, 4)), "tanimoto") + # check raised error for not-available method + assert_raises(ValueError, pairwise_similarity_bit, np.random.random((5, 1)), "tan") + assert_raises(ValueError, pairwise_similarity_bit, np.random.random((5, 1)), tanimoto) + + +def test_tanimoto_raises(): + # check raised error when a or b is not 1D + assert_raises(ValueError, tanimoto, np.random.random((1, 5)), np.random.random(5)) + assert_raises(ValueError, tanimoto, np.random.random(3), np.random.random((1, 4))) + assert_raises(ValueError, tanimoto, np.random.random(4), np.random.random((3, 4))) + assert_raises(ValueError, tanimoto, np.random.random((3, 3)), np.random.random((2, 3))) + # check raised error when a and b don't have the same length + assert_raises(ValueError, tanimoto, np.random.random(3), np.random.random(5)) + assert_raises(ValueError, tanimoto, np.random.random(20), np.random.random(10)) + + +def test_tanimoto(): + """Test the tanimoto function on one pair of points.""" + a = np.array([2, 0, 1]) + b = np.array([2, 0, 0]) + # expected = (2*2 + 0*0 + 1*0) / (2**2 + 1 + 2**2 - 2*2) + assert_equal(tanimoto(a, b), 4 / (5 + 4 - 4)) + + +def test_tanimoto_bitstring(): + """Test the tanimoto function on one pair of points.""" + a = np.array([0, 0, 0, 1, 0, 1, 1]) + b = np.array([1, 1, 0, 0, 0, 1, 1]) + assert_equal(tanimoto(a, b), 2 / 5) + + +def test_tanimoto_matrix(): + """Testing the tanimoto function with predefined feature matrix.""" + x = np.array([[1, 4], [3, 2]]) + s = pairwise_similarity_bit(x, "tanimoto") + expected = np.array([[1, (11 / 19)], [(11 / 19), 1]]) + assert_equal(s, expected) + + +def test_modified_tanimoto(): + a = np.array([1, 1, 0, 0, 1]) + b = np.array([0, 0, 0, 0, 1]) + expected = (1.6 / 9) + (1.4 / 6) + assert_equal(modified_tanimoto(a, b), expected) + + +def test_modified_tanimoto_all_ones(): + """Test the modified tanimoto function when input is all '1' bits""" + a = np.array([1, 1, 1, 1, 1]) + assert_equal(modified_tanimoto(a, a), 1) + + +def test_modified_tanimoto_all_zeroes(): + """Test the modified tanimoto function when input is all '0' bits""" + a = np.zeros(5) + assert_equal(modified_tanimoto(a, a), 1) + + +def test_modified_tanimoto_dimension_error(): + """Test modified tanimoto raises error when input has incorrect dimension.""" + a = np.zeros([7, 5]) + b = np.zeros(5) + assert_raises(ValueError, modified_tanimoto, a, b) + assert_raises(ValueError, modified_tanimoto, b, a) + assert_raises(ValueError, modified_tanimoto, np.ones(3), np.ones(5)) + + +def test_modified_tanimoto_matrix(): + """Testing the modified tanimoto function with predefined feature matrix.""" + x = np.array([[1, 0, 1], [0, 1, 1]]) + s = pairwise_similarity_bit(x, "modified_tanimoto") + expected = np.array([[1, (4 / 27)], [(4 / 27), 1]]) + assert_equal(s, expected) + + +def test_scaled_similarity_matrix(): + """Testing scaled similarity matrix function with a predefined similarity matrix.""" + X = np.array([[4, 2, 3], [0.5, 1, 1.5], [3, 3, 9]]) + s = scaled_similarity_matrix(X) + expected = np.array([[1, 1, 0.5], [0.25, 1, 0.5], [0.5, 1, 1]]) + assert_equal(s, expected) + + +def test_scaled_similarity_matrix_dimension_error(): + """Test scaled similarity matrix raises error when input has incorrect dimension.""" + X = np.array([[1, 0.8, 0.65], [0.8, 1, 0.47]]) + assert_raises(ValueError, scaled_similarity_matrix, X) + + +def test_scaled_similarity_matrix_diagonal_zero_error(): + """Test scaled similarity matrix raises error when diagonal element is zero.""" + X = np.array([[1, 0.8, 0.65], [0.8, 0, 0.47], [0.65, 0.47, 1]]) + assert_raises(ValueError, scaled_similarity_matrix, X) + + +def test_scaled_similarity_matrix_element_negative_error(): + """Test scaled similarity matrix raises error when any element is negative.""" + X = np.array([[1, 0.8, 0.65], [-0.8, 1, 0.47], [0.65, 0.47, 1]]) + assert_raises(ValueError, scaled_similarity_matrix, X) + + +def test_SimilarityIndex_init_raises(): + """Test the SimilarityIndex class for raised errors (initialization).""" + # check raised error wrong similarity index name + with pytest.raises(ValueError): + SimilarityIndex(method="esim", sim_index="ttt") + # check raised error wrong c_threshold - invalid string value + with pytest.raises(ValueError): + SimilarityIndex(method="esim", c_threshold="ttt") + # check raised error wrong c_threshold - invalid type (not int) + with pytest.raises(ValueError): + SimilarityIndex(method="esim", c_threshold=1.1) + + +def test_SimilarityIndex_calculate_counters_raises(): + sim_idx = SimilarityIndex(method="esim") + + # check raised error wrong data type + with pytest.raises(TypeError): + sim_idx._calculate_counters(X=[1, 2, 3]) + + # check raised error - no n_objects with data of length 1 + with pytest.raises(ValueError): + sim_idx._calculate_counters(X=np.array([1, 2, 3])) + + # check raised error - c_threshold bigger than n_objects + sim_idx = SimilarityIndex(method="esim", c_threshold=3) + with pytest.raises(ValueError): + sim_idx._calculate_counters(X=np.array([[1, 2, 3], [4, 5, 6]])) + + # check raised error - invalid c_threshold string value + sim_idx = SimilarityIndex(method="esim") + sim_idx.c_threshold = "ttt" + with pytest.raises(ValueError): + sim_idx._calculate_counters(X=np.array([[1, 2, 3], [4, 5, 6]])) + + # check raised error - invalid weight factor string value + sim_idx = SimilarityIndex(method="esim") + sim_idx.w_factor = "ttt" + with pytest.raises(ValueError): + sim_idx._calculate_counters(X=np.array([[1, 2, 3], [4, 5, 6]])) + + +def test_SimilarityIndex_call_raises(): + """Test the SimilarityIndex class for raised errors (call).""" + sim_idx = SimilarityIndex() + # check raised error wrong data type + with pytest.raises(TypeError): + sim_idx(X=[1, 2, 3]) + # check raised error - no n_objects with data of length 1 + with pytest.raises(ValueError): + sim_idx(X=np.array([1, 2, 3])) + + +def test_SimilarityIndex_calculate_medoid_raises(): + """Test the SimilarityIndex class for raised errors (calculate_medoid).""" + sim_idx = NSimilarity() + + # check raised error wrong data type + with pytest.raises(TypeError): + sim_idx.calculate_medoid(X=[1, 2, 3]) + + # check raised error - no medoid with one dimensional data + with pytest.raises(ValueError): + sim_idx.calculate_medoid(X=np.array([1, 2, 3])) + + # check raised error - no medoid with less than three samples + with pytest.raises(ValueError): + sim_idx.calculate_medoid(X=np.array([[1, 2, 3], [4, 5, 6]])) + + # check raised error - c_threshold bigger than n_objects + sim_idx = NSimilarity(method="esim", c_threshold=4) + with pytest.raises(ValueError): + sim_idx.calculate_medoid(X=np.array([[1, 2, 3], [4, 5, 6], [6, 7, 8]])) + + # check raised error - c_total and data have different number of columns + sim_idx = NSimilarity() + with pytest.raises(ValueError): + sim_idx.calculate_medoid( + X=np.array([[1, 2, 3], [4, 5, 6], [6, 7, 8]]), c_total=np.array([1, 2, 3, 4]) + ) + + +def test_SimilarityIndex_calculate_outlier_raises(): + """Test the SimilarityIndex class for raised errors (calculate_outlier).""" + sim_idx = NSimilarity() + + # check raised error wrong data type + with pytest.raises(TypeError): + sim_idx.calculate_outlier(X=[1, 2, 3]) + + # check raised error - no medoid with one dimensional data + with pytest.raises(ValueError): + sim_idx.calculate_outlier(X=np.array([1, 2, 3])) + + # check raised error - no medoid with less than three samples + with pytest.raises(ValueError): + sim_idx.calculate_outlier(X=np.array([[1, 2, 3], [4, 5, 6]])) + + # check raised error - c_threshold bigger than n_objects + sim_idx = NSimilarity(method="esim", c_threshold=4) + with pytest.raises(ValueError): + sim_idx.calculate_outlier(X=np.array([[1, 2, 3], [4, 5, 6], [6, 7, 8]])) + + # check raised error - c_total and data have different number of columns + sim_idx = NSimilarity() + with pytest.raises(ValueError): + sim_idx.calculate_outlier( + X=np.array([[1, 2, 3], [4, 5, 6], [6, 7, 8]]), c_total=np.array([1, 2, 3, 4]) + ) + + +def test_NSimilarity_init_raises(): + """Test the NSimilarity class for raised errors (initialization).""" + # check raised error wrong similarity index name + with pytest.raises(ValueError): + NSimilarity(similarity_index="ttt") + # check raised error wrong c_threshold - invalid string value + with pytest.raises(ValueError): + NSimilarity(method="esim", c_threshold="ttt") + # check raised error wrong c_threshold - invalid type (not int) + with pytest.raises(ValueError): + NSimilarity(method="esim", c_threshold=1.1) + + +def test_NSimilarity_get_new_index_raises(): + """Test the NSimilarity class for raised errors (get_new_index).""" + # check that data is not scaled between 0 and 1 + with pytest.raises(ValueError): + NSimilarity()._get_new_index( + X=np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]), + num_selected=1, + selected_condensed=np.array([1, 2, 3]), + select_from=np.array([1, 2, 3]), + ) + + +def test_NSimilarity_select_from_cluster_raises(): + """Test the NSimilarity class for raised errors (select_from_cluster).""" + data_array = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) + cluster_ids = np.array([0, 1, 2]) + with pytest.raises(ValueError): + # select more samples than the number of samples in the cluster + NSimilarity().select_from_cluster(X=data_array, size=5) + with pytest.raises(ValueError): + # start from sample index that is not in the cluster + NSimilarity().select_from_cluster(X=data_array, size=2, start=[4]) + with pytest.raises(ValueError): + # start from sample index that is not in the cluster + NSimilarity().select_from_cluster(X=data_array, size=2, start=[4]) + with pytest.raises(ValueError): + # start from invalid string value of start + NSimilarity().select_from_cluster(X=data_array, size=2, start="ttt") + with pytest.raises(ValueError): + # start from invalid type of start + NSimilarity().select_from_cluster(X=data_array, size=2, start=[1.2]) + with pytest.raises(ValueError): + # try to data not scaled between 0 and 1 + NSimilarity(preprocess_data=False).select_from_cluster(X=data_array, size=2) + with pytest.raises(ValueError): + # try to use starting index that is not in the cluster + NSimilarity().select_from_cluster(X=data_array, size=2, start=[4], labels=cluster_ids) + with pytest.raises(ValueError): + # try to use invalid starting index + NSimilarity().select_from_cluster(X=data_array, size=2, start=4.2, labels=cluster_ids) + + +# --------------------------------------------------------------------------------------------- # +# Tests for the function results of the SimilarityIndex and NSimilarity classes. +# --------------------------------------------------------------------------------------------- # +# The following part tests the results of the SimilarityIndex and NSimilarity classes methods +# for a set of binary data. The proper results for the tests are known in advance. + +# Tests for binary data. +# --------------------------------------------------------------------------------------------- # + +# --------------------------------------------------------------------------------------------- # +# Section of the test for the SimilarityIndex class using binary data and esim method. +# --------------------------------------------------------------------------------------------- # + + +def _get_binary_data(): + """Returns a list of binary strings. + + The proper results for the tests are known in advance. + + Returns + ------- + list of lists + A list of binary objects lists. + """ + + # Binary data to perform the tests, it contains 100 lists of 12 elements each + # The proper results for the tests are known in advance. + data = np.array( + [ + [0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1], + [1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1], + [1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0], + [0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1], + [0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1], + [1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0], + [1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1], + [0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0], + [0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1], + [0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1], + [1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0], + [1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1], + [1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0], + [1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1], + [1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0], + [1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1], + [1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0], + [1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0], + [1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1], + [0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1], + [1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0], + [0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1], + [0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0], + [1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1], + [1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1], + [1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1], + [1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0], + [0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0], + [1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0], + [0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0], + [1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1], + [0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0], + [0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1], + [0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0], + [0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1], + [1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0], + [1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0], + [0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0], + [1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1], + [1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0], + [0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1], + [1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0], + [1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0], + [0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0], + [0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0], + [1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1], + [1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1], + [0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0], + [0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0], + [1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1], + [0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0], + [1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0], + [0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0], + [0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1], + [0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0], + [0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1], + [0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0], + [1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1], + [0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0], + [0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0], + [1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0], + [1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0], + [0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0], + [0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0], + [0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0], + [0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0], + [1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0], + [1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0], + [0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1], + [0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0], + [1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0], + [0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1], + [0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1], + [1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0], + [1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1], + [1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0], + [1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0], + [1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1], + [0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0], + [1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0], + [1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0], + [1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1], + [1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0], + [0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1], + [0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1], + [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0], + [0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0], + [0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1], + [1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1], + [0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1], + [0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0], + [0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1], + [1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0], + [1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0], + [1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1], + [1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1], + [1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0], + [0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1], + [0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1], + [0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1], + ] + ) + + return data + + +def _get_ref_similarity_esim_dict(): + """Returns a dictionary with the reference values for the similarity indexes. + + The proper results for the tests are known in advance and are stored in a dictionary. + + Returns + ------- + dict + A dictionary with the reference values for the similarity indexes. The dictionary has the + following structure: + {w_factor: {c_threshold: {n_ary: value}}} where: + w_factor: the weight factor for the similarity index + c_threshold: the threshold value for the similarity index + """ + + # Reference values for the similarity index. + ref_similarity_binary = { + "fraction": { + "None": { + "AC": 0.1597619835634367, + "BUB": 0.06891469248218901, + "CT1": 0.21594387881973748, + "CT2": 0.12273565515991067, + "CT3": 0.09010381444416192, + "CT4": 0.1435977860207451, + "Fai": 0.041666666666666664, + "Gle": 0.07428571428571429, + "Ja": 0.078, + "Ja0": 0.06529411764705882, + "JT": 0.065, + "RT": 0.05692307692307692, + "RR": 0.021666666666666667, + "SM": 0.06166666666666667, + "SS1": 0.052000000000000005, + "SS2": 0.06434782608695652, + }, + "dissimilar": { + "AC": 0.0, + "BUB": 0.0, + "CT1": 0.0, + "CT2": 0.0, + "CT3": 0.0, + "CT4": 0.0, + "Fai": 0.0, + "Gle": 0.0, + "Ja": 0.0, + "Ja0": 0.0, + "JT": 0.0, + "RT": 0.0, + "RR": 0.0, + "SM": 0.0, + "SS1": 0.0, + "SS2": 0.0, + }, + 5: { + "AC": 0.13861833940391668, + "BUB": 0.043638272469757794, + "CT1": 0.173370214880788, + "CT2": 0.02399965239873406, + "CT3": 0.07108193238341105, + "CT4": 0.0791812460476248, + "Fai": 0.03166666666666667, + "Gle": 0.04, + "Ja": 0.05454545454545456, + "Ja0": 0.084, + "JT": 0.022222222222222223, + "RT": 0.028000000000000004, + "RR": 0.016666666666666666, + "SM": 0.04666666666666667, + "SS1": 0.011764705882352941, + "SS2": 0.07, + }, + }, + "power_3": { + "None": { + "AC": 1.5127728116149686e-20, + "BUB": 7.90100730602568e-40, + "CT1": 0.0, + "CT2": 0.0, + "CT3": 0.0, + "CT4": 0.0, + "Fai": 5.6422575986042295e-40, + "Gle": 1.9329988216613272e-39, + "Ja": 2.029648762744394e-39, + "Ja0": 5.978755024266622e-40, + "JT": 1.6913739689536614e-39, + "RT": 5.212247969873465e-40, + "RR": 5.6379132298455384e-40, + "SM": 5.646601967362921e-40, + "SS1": 1.3530991751629292e-39, + "SS2": 5.892106400726526e-40, + }, + "dissimilar": { + "AC": 0.0, + "BUB": 0.0, + "CT1": 0.0, + "CT2": 0.0, + "CT3": 0.0, + "CT4": 0.0, + "Fai": 0.0, + "Gle": 0.0, + "Ja": 0.0, + "Ja0": 0.0, + "JT": 0.0, + "RT": 0.0, + "RR": 0.0, + "SM": 0.0, + "SS1": 0.0, + "SS2": 0.0, + }, + 5: { + "AC": 1.5127727667796592e-20, + "BUB": 6.551485125947553e-40, + "CT1": 0.0, + "CT2": 0.0, + "CT3": 0.0, + "CT4": 0.0, + "Fai": 5.642257358488985e-40, + "Gle": 1.3530991402370754e-39, + "Ja": 1.8451351912323755e-39, + "Ja0": 1.0163882938782278e-39, + "JT": 7.517217445761529e-40, + "RT": 3.387960979594093e-40, + "RR": 5.637913084321148e-40, + "SM": 5.646601632656821e-40, + "SS1": 3.979703353638457e-40, + "SS2": 8.469902448985232e-40, + }, + }, + } + + return ref_similarity_binary + + +def _get_ref_isim_dict(): + """Returns a dictionary with the reference values necessary for testing the isim method. + + The proper results for the tests are known in advance and are stored in a dictionary. + + Returns + ------- + dict + A dictionary with the reference values necessary for all the isim method tests. The + dictionary has the following structure: + {n_ary: { outlier: value, medoid: value, kval2si: {k: value}}} where: + n_ary: the similarity index name used + outlier: the index of the outlier sample + medoid: the index of the medoid sample + kval2si: a dictionary with the k value as key and the similarity index as value + """ + isim_dict = { + "AC": { + "outlier": 49, + "medoid": 96, + "kval2si": { + 1: 0.49917475122243926, + 2: 0.5538883964836272, + 5: 0.5866150284585204, + 10: 0.5974286117693461, + }, + }, + "BUB": { + "outlier": 85, + "medoid": 10, + "kval2si": { + 1: 0.49397989672931264, + 2: 0.5819613020487422, + 5: 0.6335183244648649, + 10: 0.6502407823406905, + }, + }, + "CT1": { + "outlier": 49, + "medoid": 96, + "kval2si": { + 1: 0.9367065121244419, + 2: 0.9261583241959612, + 5: 0.9107923779571723, + 10: 0.902405671341302, + }, + }, + "CT2": { + "outlier": 49, + "medoid": 96, + "kval2si": { + 1: 0.06282178200501828, + 2: 0.12056333324739296, + 5: 0.19665579893673796, + 10: 0.23722036836219337, + }, + }, + "CT3": { + "outlier": 85, + "medoid": 10, + "kval2si": { + 1: 0.870243523865252, + 2: 0.82843367496858, + 5: 0.77434619420322, + 10: 0.7461466827474635, + }, + }, + "CT4": { + "outlier": 85, + "medoid": 10, + "kval2si": { + 1: 0.8945856132657759, + 2: 0.8706848775823933, + 5: 0.8375702929632953, + 10: 0.8197597232141359, + }, + }, + "Fai": { + "outlier": 85, + "medoid": 10, + "kval2si": { + 1: 0.36944444444444446, + 2: 0.4354778372150966, + 5: 0.47461264224551747, + 10: 0.4873954166765502, + }, + }, + "Gle": { + "outlier": 85, + "medoid": 10, + "kval2si": { + 1: 0.48934163365402755, + 2: 0.579696056605444, + 5: 0.6326571892686095, + 10: 0.6498200476852635, + }, + }, + "Ja": { + "outlier": 85, + "medoid": 10, + "kval2si": { + 1: 0.5897241588360109, + 2: 0.6741446014011255, + 5: 0.7209338061721255, + 10: 0.735695295519683, + }, + }, + "Ja0": { + "outlier": 49, + "medoid": 96, + "kval2si": { + 1: 0.7490265158538847, + 2: 0.8082737370566611, + 5: 0.8388469288245588, + 10: 0.8482013298830383, + }, + }, + "JT": { + "outlier": 85, + "medoid": 10, + "kval2si": { + 1: 0.3239260739260739, + 2: 0.4081492974102138, + 5: 0.4626909830536219, + 10: 0.48128402926677866, + }, + }, + "RT": { + "outlier": 49, + "medoid": 96, + "kval2si": { + 1: 0.3321820648822006, + 2: 0.41267273273100585, + 5: 0.4645381672067039, + 10: 0.48220837765022756, + }, + }, + "RR": { + "outlier": 85, + "medoid": 10, + "kval2si": { + 1: 0.2401851851851852, + 2: 0.2867117470582547, + 5: 0.3148435010613659, + 10: 0.3241287740619748, + }, + }, + "SM": { + "outlier": 49, + "medoid": 96, + "kval2si": { + 1: 0.4987037037037037, + 2: 0.5842439273719385, + 5: 0.6343817834296691, + 10: 0.6506620592911254, + }, + }, + "SS1": { + "outlier": 85, + "medoid": 10, + "kval2si": { + 1: 0.19326478915213827, + 2: 0.25639923187909175, + 5: 0.3009746107992553, + 10: 0.3169019346220607, + }, + }, + "SS2": { + "outlier": 49, + "medoid": 96, + "kval2si": { + 1: 0.6655134066477203, + 2: 0.7375681450029299, + 5: 0.7762957099270287, + 10: 0.7883649540846069, + }, + }, + } + return isim_dict + + +def _get_absolute_decimal_places_for_comparison(num1, num2, rtol=1e-4): + """Calculate the absolute number of decimal places needed for comparison of two numbers. + + Calculate the absolute number of decimal places needed for assert_almost_equal of two numbers + with a relative tolerance of rtol. + + Parameters + ---------- + num1 : float + First number. + num2 : float + Second number. + rtol : float + Relative tolerance. + """ + max_num = max(abs(num1), abs(num2)) + + # If both numbers are zero, return 5 decimal places just to avoid division by zero. Both numbers + # are zero (and therefore equal) withing the machine precision. + if max_num == 0: + return 5 + + # Calculate the dynamic tolerance based on the magnitudes of the numbers + tol = rtol * max(abs(num1), abs(num2)) + + return abs(int(np.log10(tol))) + + +# Parameter values for the tests +c_treshold_values = [None, "dissimilar", 5] +w_factor_values = ["fraction", "power_3"] +n_ary_values = [ + "AC", + "BUB", + "CT1", + "CT2", + "CT3", + "CT4", + "Fai", + "Gle", + "Ja", + "Ja0", + "JT", + "RT", + "RR", + "SM", + "SS1", + "SS2", +] + + +@pytest.mark.parametrize("c_threshold", c_treshold_values) +@pytest.mark.parametrize("w_factor", w_factor_values) +@pytest.mark.parametrize("n_ary", n_ary_values) +def test_SimilarityIndex_esim_call(c_threshold, w_factor, n_ary): + """Test the similarity index for binary data. + + Test the similarity index for binary data using the reference values and several combinations + of parameters. + + Parameters + ---------- + c_threshold : float + The threshold value for the similarity index. + w_factor : float + The weight factor for the similarity index. + n_ary : str + The similarity index to use. + """ + + # get the binary data + data, ref_similarity_binary = _get_binary_data(), _get_ref_similarity_esim_dict() + + # create instance of the class SimilarityIndex to test the similarity indexes for binary data + sim_idx = SimilarityIndex( + method="esim", sim_index=n_ary, c_threshold=c_threshold, w_factor=w_factor + ) + + # calculate the similarity index for the binary data + sim_idx_value = sim_idx(data) + + # get the reference value for the similarity index + if c_threshold is None: + c_threshold = "None" + ref_value = ref_similarity_binary[w_factor][c_threshold][n_ary] + + # calculate the absolute tolerance based on the relative tolerance and the numbers magnitude + tol = _get_absolute_decimal_places_for_comparison(sim_idx_value, ref_value) + + # check that the calculated value is equal to the reference value + assert_almost_equal(sim_idx_value, ref_value, decimal=tol) + + +# --------------------------------------------------------------------------------------------- # +# Section of the tests for selection of indexes functions using binary data and esim method. +# --------------------------------------------------------------------------------------------- # + +# Many of the combinations of parameters for the tests are too stringent and the similarity of the +# samples is zero. These cases are not considered because will produce inconsistent results for the +# selection of the new indexes, and the calculation of the medoid and the outlier. + +# Creating the possible combinations of the parameters for the tests. The combinations are stored +# in a list of tuples. Each tuple has the following structure: (w_factor, c_threshold, n_ary) +# where: +# w_factor: the weight factor for the similarity index +# c_threshold: the threshold value for the similarity index +# n_ary: the similarity index to use + + +# The cases where the similarity of the samples is zero are not considered because these will be +# inconsistent with the reference values for the selection of the new indexes, and the calculation +# of the medoid and the outlier. +def _get_esim_test_parameters(): + """Returns the parameters for the tests. + + Returns the parameters for the tests. The parameters are stored in a list of tuples. Each tuple + has the following structure: (w_factor, c_threshold, n_ary) where: + w_factor: the weight factor for the similarity index + c_threshold: the threshold value for the similarity index + n_ary: the similarity index to use + + Returns + ------- + list + A list of tuples with the parameters for the tests. Each tuple has the following structure: + (w_factor, c_threshold, n_ary) where: + w_factor: the weight factor for the similarity index + c_threshold: the threshold value for the similarity index + n_ary: the similarity index to use + """ + # The cases where the similarity of the samples is zero are not considered because these will be + # inconsistent with the reference values for the selection of the new indexes, and the + # calculation of the medoid and the outlier. + test_parameters = [] + for w in w_factor_values: + for c in c_treshold_values: + # small hack to avoid using the None value as a key in the dictionary + c_key = c + if c is None: + c_key = "None" + for n in n_ary_values: + # ignore the cases where the similarity of the samples less than two percent + if not _get_ref_similarity_esim_dict()[w][c_key][n] < 0.02: + test_parameters.append((c, w, n)) + + return test_parameters + + +parameters = _get_esim_test_parameters() + + +def _get_ref_medoid_esim_dict(): + """Returns dictionary with reference medoid index for binary data using esim method. + + The proper results for the tests are known in advance and are stored in a dictionary. + + The dictionary has the following structure: + {w_factor: {c_threshold: {n_ary: value}}} where: + w_factor: the weight factor for the similarity index + c_threshold: the threshold value for the similarity index + + The medoid values are stored for all possible combinations of the following parameter values: + - w_factor: None, dissimilar, 5 + - c_threshold: fraction, power_3 + - n_ary: AC, BUB, CT1, CT2, CT3, CT4, Fai, Gle, Ja, Ja0, JT, RT, RR, SM, SS1, SS2 + + + Returns + ------- + dict + A dictionary with the reference values for the medoid. The dictionary has the + following structure: + {w_factor: {c_threshold: {n_ary: value}}} where: + w_factor: the weight factor for the similarity index + c_threshold: the threshold value for the similarity index + """ + medoid_ref_dict = { + "None": { + "fraction": { + "AC": 96, + "BUB": 69, + "CT1": 96, + "CT2": 80, + "CT3": 1, + "CT4": 23, + "Fai": 96, + "Gle": 69, + "Ja": 69, + "Ja0": 50, + "JT": 69, + "RT": 96, + "RR": 1, + "SM": 96, + "SS1": 23, + "SS2": 50, + }, + "power_3": { + "AC": 96, + "BUB": 48, + "CT1": 0, + "CT2": 0, + "CT3": 0, + "CT4": 0, + "Fai": 96, + "Gle": 69, + "Ja": 69, + "Ja0": 50, + "JT": 69, + "RT": 96, + "RR": 1, + "SM": 96, + "SS1": 69, + "SS2": 50, + }, + }, + "dissimilar": { + "fraction": { + "AC": 0, + "BUB": 0, + "CT1": 0, + "CT2": 0, + "CT3": 0, + "CT4": 0, + "Fai": 0, + "Gle": 0, + "Ja": 0, + "Ja0": 0, + "JT": 0, + "RT": 0, + "RR": 0, + "SM": 0, + "SS1": 0, + "SS2": 0, + }, + "power_3": { + "AC": 0, + "BUB": 0, + "CT1": 0, + "CT2": 0, + "CT3": 0, + "CT4": 0, + "Fai": 0, + "Gle": 0, + "Ja": 0, + "Ja0": 0, + "JT": 0, + "RT": 0, + "RR": 0, + "SM": 0, + "SS1": 0, + "SS2": 0, + }, + }, + 5: { + "fraction": { + "AC": 39, + "BUB": 39, + "CT1": 39, + "CT2": 96, + "CT3": 0, + "CT4": 0, + "Fai": 39, + "Gle": 0, + "Ja": 0, + "Ja0": 39, + "JT": 0, + "RT": 39, + "RR": 0, + "SM": 39, + "SS1": 0, + "SS2": 39, + }, + "power_3": { + "AC": 39, + "BUB": 39, + "CT1": 0, + "CT2": 0, + "CT3": 0, + "CT4": 0, + "Fai": 39, + "Gle": 0, + "Ja": 0, + "Ja0": 39, + "JT": 0, + "RT": 39, + "RR": 0, + "SM": 39, + "SS1": 0, + "SS2": 39, + }, + }, + } + + return medoid_ref_dict + + +@pytest.mark.parametrize("c_threshold, w_factor, n_ary", parameters) +def test_calculate_medoid_esim(c_threshold, w_factor, n_ary): + """Test the function to calculate the medoid for binary data using esim method. + + Test the function to calculate the medoid for binary data using the reference values and several + combinations of parameters. The reference values are obtained using the function + _get_ref_medoid_dict(). + + Parameters + ---------- + c_threshold : float + The threshold value for the similarity index. + w_factor : float + The weight factor for the similarity index. + n_ary : str + The similarity index to use. + """ + + # get the reference binary data + data = _get_binary_data() + # get the reference value for the medoid + ref_medoid_dict = _get_ref_medoid_esim_dict() + + # small hack to avoid using the None value as a key in the dictionary + c_threshold_key = c_threshold + if c_threshold is None: + c_threshold_key = "None" + + ref_medoid = ref_medoid_dict[c_threshold_key][w_factor][n_ary] + + # calculate the medoid for the binary data + sim_idx = NSimilarity( + method="esim", similarity_index=n_ary, c_threshold=c_threshold, w_factor=w_factor + ) + medoid = sim_idx.calculate_medoid(X=data) + + # check that the calculated medoid is equal to the reference medoid + assert_equal(medoid, ref_medoid) + + +# results from the reference code +def _get_ref_outlier_esim_dict(): + """Returns dictionary with reference outlier index for binary data using esim method. + + The proper results for the tests are known in advance and are stored in a dictionary. + + The dictionary has the following structure: + {w_factor: {c_threshold: {n_ary: value}}} where: + w_factor: the weight factor for the similarity index + c_threshold: the threshold value for the similarity index + + The outlier values are stored for all possible combinations of the following parameter values: + - w_factor: None, dissimilar, 5 + - c_threshold: fraction, power_3 + - n_ary: AC, BUB, CT1, CT2, CT3, CT4, Fai, Gle, Ja, Ja0, JT, RT, RR, SM, SS1, SS2 + + + Returns + ------- + dict + A dictionary with the reference values for the outlier. The dictionary has the + following structure: + {w_factor: {c_threshold: {n_ary: value}}} where: + w_factor: the weight factor for the similarity index + c_threshold: the threshold value for the similarity index + """ + oulier_ref_dict = { + "None": { + "fraction": { + "AC": 4, + "BUB": 34, + "CT1": 4, + "CT2": 4, + "CT3": 8, + "CT4": 34, + "Fai": 34, + "Gle": 34, + "Ja": 34, + "Ja0": 49, + "JT": 34, + "RT": 4, + "RR": 8, + "SM": 4, + "SS1": 34, + "SS2": 49, + }, + "power_3": { + "AC": 49, + "BUB": 57, + "CT1": 0, + "CT2": 0, + "CT3": 0, + "CT4": 0, + "Fai": 49, + "Gle": 34, + "Ja": 16, + "Ja0": 80, + "JT": 34, + "RT": 4, + "RR": 8, + "SM": 49, + "SS1": 34, + "SS2": 80, + }, + }, + "dissimilar": { + "fraction": { + "AC": 0, + "BUB": 0, + "CT1": 0, + "CT2": 0, + "CT3": 0, + "CT4": 0, + "Fai": 0, + "Gle": 0, + "Ja": 0, + "Ja0": 0, + "JT": 0, + "RT": 0, + "RR": 0, + "SM": 0, + "SS1": 0, + "SS2": 0, + }, + "power_3": { + "AC": 0, + "BUB": 0, + "CT1": 0, + "CT2": 0, + "CT3": 0, + "CT4": 0, + "Fai": 0, + "Gle": 0, + "Ja": 0, + "Ja0": 0, + "JT": 0, + "RT": 0, + "RR": 0, + "SM": 0, + "SS1": 0, + "SS2": 0, + }, + }, + 5: { + "fraction": { + "AC": 49, + "BUB": 49, + "CT1": 49, + "CT2": 57, + "CT3": 2, + "CT4": 2, + "Fai": 49, + "Gle": 2, + "Ja": 2, + "Ja0": 49, + "JT": 2, + "RT": 49, + "RR": 2, + "SM": 49, + "SS1": 2, + "SS2": 49, + }, + "power_3": { + "AC": 49, + "BUB": 49, + "CT1": 0, + "CT2": 0, + "CT3": 0, + "CT4": 0, + "Fai": 49, + "Gle": 2, + "Ja": 2, + "Ja0": 49, + "JT": 2, + "RT": 49, + "RR": 2, + "SM": 49, + "SS1": 2, + "SS2": 49, + }, + }, + } + + return oulier_ref_dict + + +@pytest.mark.parametrize("c_threshold, w_factor, n_ary", parameters) +def test_calculate_outlier_esim(c_threshold, w_factor, n_ary): + """Test the function to calculate the outlier for binary data using the esim method. + + Test the function to calculate the outlier for binary data using the reference values and + several combinations of parameters. The reference values are obtained using the function + _get_ref_outlier_dict(). + + Parameters + ---------- + c_threshold : float + The threshold value for the similarity index. + w_factor : float + The weight factor for the similarity index. + n_ary : str + The similarity index to use. + """ + + # get the reference binary data + data = _get_binary_data() + # get the reference value for the outlier + ref_outlier_dict = _get_ref_outlier_esim_dict() + + # small hack to avoid using the None value as a key in the dictionary + c_threshold_key = c_threshold + if c_threshold is None: + c_threshold_key = "None" + + ref_outlier = ref_outlier_dict[c_threshold_key][w_factor][n_ary] + + # calculate the outlier for the binary data + sim_idx = NSimilarity( + method="esim", similarity_index=n_ary, c_threshold=c_threshold, w_factor=w_factor + ) + outlier = sim_idx.calculate_outlier(X=data) + + # check that the calculated outlier is equal to the reference outlier + assert_equal(outlier, ref_outlier) + + +# --------------------------------------------------------------------------------------------- # +# Section of the tests for selection of indexes functions using binary data and isim method. +# --------------------------------------------------------------------------------------------- # +# test medoid selection +si_idcs = [ + "AC", + "BUB", + "CT1", + "CT2", + "CT3", + "CT4", + "Fai", + "Gle", + "Ja", + "Ja0", + "JT", + "RT", + "RR", + "SM", + "SS1", + "SS2", +] + + +@pytest.mark.parametrize("sim_idx", si_idcs) +def test_calculate_medoid_isim(sim_idx): + data = _get_binary_data() + isim_dict = _get_ref_isim_dict() + ref_medoid = isim_dict[sim_idx]["medoid"] + sim_idx = NSimilarity(method="isim", similarity_index=sim_idx) + medoid = sim_idx.calculate_medoid(X=data) + assert_equal(medoid, ref_medoid) + + +# test outlier selection +@pytest.mark.parametrize("sim_idx", si_idcs) +def test_calculate_outlier_isim(sim_idx): + data = _get_binary_data() + isim_dict = _get_ref_isim_dict() + ref_medoid = isim_dict[sim_idx]["outlier"] + sim_idx = NSimilarity(method="isim", similarity_index=sim_idx) + medoid = sim_idx.calculate_outlier(X=data) + assert_equal(medoid, ref_medoid) + + +# --------------------------------------------------------------------------------------------- # +# Section of the test for the NSimilarity class using binary data and esim method. +# --------------------------------------------------------------------------------------------- # +def _get_ref_new_index_esim(): + """ + Returns reference data for testing the function to calculate the new index with the esim method. + + Returns the tuple (selected_points, new_indexes_dict) where selected_points is a list of + selected samples given to the function (get_new_index) and new_indexes_dict is a dictionary + with the reference values for the new index to be selected based on the previously selected + indices and the other function parameters. + + Returns + ------- + tuple (list, dict) + A tuple with the reference data for testing the function to calculate the new index. The + tuple has the following structure: + (selected_points, new_indexes_dict) where: + selected_points: a list of selected samples given to the function (get_new_index) + new_indexes_dict: a dictionary with the reference values for the new index to be + selected based on the previously selected indices and the other function + parameters. The dictionary has the following structure: + {w_factor: {c_threshold: {n_ary: value}}} where: + w_factor: the weight factor for the similarity index + c_threshold: the threshold value for the similarity index + n_ary: the similarity index to use + + """ + + # The selected points to be given to the function (get_new_index) + selected_samples = [0, 9, 19, 29, 39, 49, 59, 69, 79, 89, 99] + # The reference values for the new index to be selected based on the previously selected + # indices and the other function parameters. + new_index_dict = { + "None": { + "fraction": { + "AC": 62, + "BUB": 62, + "CT1": 62, + "CT2": 62, + "CT3": 2, + "CT4": 44, + "Fai": 62, + "Gle": 44, + "Ja": 44, + "Ja0": 62, + "JT": 44, + "RT": 62, + "RR": 2, + "SM": 62, + "SS1": 44, + "SS2": 62, + }, + "power_3": { + "AC": 67, + "BUB": 11, + "CT1": 67, + "CT2": 20, + "CT3": 2, + "CT4": 44, + "Fai": 11, + "Gle": 44, + "Ja": 44, + "Ja0": 11, + "JT": 44, + "RT": 67, + "RR": 2, + "SM": 67, + "SS1": 44, + "SS2": 11, + }, + }, + 5: { + "fraction": { + "AC": 2, + "BUB": 2, + "CT1": 2, + "CT2": 2, + "CT3": 2, + "CT4": 2, + "Fai": 2, + "Gle": 2, + "Ja": 2, + "Ja0": 2, + "JT": 2, + "RT": 2, + "RR": 2, + "SM": 2, + "SS1": 2, + "SS2": 2, + }, + "power_3": { + "AC": 2, + "BUB": 2, + "CT1": 2, + "CT2": 2, + "CT3": 2, + "CT4": 2, + "Fai": 2, + "Gle": 2, + "Ja": 2, + "Ja0": 2, + "JT": 2, + "RT": 2, + "RR": 2, + "SM": 2, + "SS1": 2, + "SS2": 2, + }, + }, + } + + return selected_samples, new_index_dict + + +@pytest.mark.parametrize("c_threshold, w_factor, n_ary", parameters) +def test_get_new_index_esim(c_threshold, w_factor, n_ary): + """Test the function get a new sample from the binary data. + + Test the function to get a new sample from the binary data using the reference values and + several combinations of parameters. The reference values are obtained using the function + _get_ref_new_index(). + + Parameters + ---------- + c_threshold : float + The threshold value for the similarity index. + w_factor : float + The weight factor for the similarity index. + n_ary : str + The similarity index to use. + """ + + # get the reference binary data + data = _get_binary_data() + # get the reference value for the outlier + selected_samples, ref_new_index_dict = _get_ref_new_index_esim() + + # columnwise sum of the selected samples + selected_condensed_data = np.sum(np.take(data, selected_samples, axis=0), axis=0) + # indices of the samples to select from + select_from_n = [i for i in range(len(data)) if i not in selected_samples] + # number of samples that are already selected + n = len(selected_samples) + + # small hack to avoid using the None value as a key in the dictionary + c_threshold_key = c_threshold + if c_threshold is None: + c_threshold_key = "None" + + ref_new_index = ref_new_index_dict[c_threshold_key][w_factor][n_ary] + + # calculate the outlier for the binary data + nsi = NSimilarity( + method="esim", similarity_index=n_ary, w_factor=w_factor, c_threshold=c_threshold + ) + + new_index = nsi._get_new_index( + X=data, + selected_condensed=selected_condensed_data, + select_from=select_from_n, + num_selected=n, + ) + + assert_equal(new_index, ref_new_index) + + +# --------------------------------------------------------------------------------------------- # +# Selecting a subset of the parameters generated for the tests +# --------------------------------------------------------------------------------------------- # + +# remove cases where c_threshold is 5. This is not a valid case for the selection of the next point +# if the number of selected samples is less than 5 +parameters = [x for x in parameters if not x[0] == 5] + +# The start parameter can be a list of elements that need to be selected first. +# The case of the three elements included in a selection 1, 2, 3 is tested. +start_values = ["medoid", "outlier", [1, 2, 3]] +# sample size values to test +sample_size_values = [10, 20, 30] + + +# --------------------------------------------------------------------------------------------- # +# Get reference data for testing the selection of the diverse subset +# --------------------------------------------------------------------------------------------- # +# get reference selected data for esim method +def _get_selections_esim_ref_dict(): + """Returns a dictionary with the reference values for the selection of samples. + + The proper results for the tests are known in advance and are stored in a csv file. + The file is read and the values are stored in a dictionary. The dictionary has the following + structure: + {w_factor: {c_threshold: {n_ary: {sample_size: {start: value}}}}} where: + w_factor: the weight factor for the similarity index + c_threshold: the threshold value for the similarity index + n_ary: the similarity index to use + sample_size: the number of samples to select + start: the method to use to select the first(s) sample(s) + """ + + file_path = get_data_file_path("ref_esim_selection_data.csv") + with open(file_path, encoding="utf-8") as file: + reader = csv.reader(file, delimiter=";") + next(reader) # skip header + # initialize the dictionary + data_dict = {} + + for row in reader: + # The first column is the c_threshold + data_dict[row[0]] = data_dict.get(row[0], {}) + # The second column is the w_factor + data_dict[row[0]][row[1]] = data_dict[row[0]].get(row[1], {}) + # The third column is the sample_size + data_dict[row[0]][row[1]][row[2]] = data_dict[row[0]][row[1]].get(row[2], {}) + # The fourth column is the start_idx + data_dict[row[0]][row[1]][row[2]][row[3]] = data_dict[row[0]][row[1]][row[2]].get( + row[3], {} + ) + # The fifth column stores the n_ary and the sixth column stores the reference value + data_dict[row[0]][row[1]][row[2]][row[3]][row[4]] = ast.literal_eval(row[5]) + return data_dict + + +# test selected data for esim method (inv_order=1) and binary data against reference data +@pytest.mark.parametrize("c_threshold, w_factor, n_ary", parameters) +@pytest.mark.parametrize("sample_size", sample_size_values) +@pytest.mark.parametrize("start", start_values) +def test_NSimilarity_esim_select(c_threshold, w_factor, sample_size, n_ary, start): + """ + Test the diversity selection methods based on similarity indexes for binary data. + + Parameters + ---------- + c_threshold : float + The threshold value for the similarity index. + w_factor : float + The weight factor for the similarity index. + sample_size : int + The number of molecules to select. + n_ary : str + The similarity index to use. + start : str + The method to use to select the first(s) sample(s). + + """ + + # get the binary data + data = _get_binary_data() + # get the reference selected data + reference_selected_data = _get_selections_esim_ref_dict() + + # create instance of the class SimilarityIndex to test the similarity indexes for binary data + collector = NSimilarity( + method="esim", + similarity_index=n_ary, + w_factor=w_factor, + c_threshold=c_threshold, + preprocess_data=False, + ) + # select the diverse subset using the similarity index + selected_data = collector.select_from_cluster(data, size=sample_size, start=start) + + # get the reference value for the similarity index + # transform invalid keys to strings + if c_threshold is None: + c_threshold = "None" + # transform sample_size to string (as it is used as a key in the dictionary) + sample_size = str(sample_size) + # lists of initial indexes are not valid keys in the dictionary (non hashable) + if isinstance(start, list): + start = str(start).replace(" ", "") + # get the reference list as a string + ref_list = reference_selected_data[c_threshold][w_factor][sample_size][start][n_ary] + + # check if the selected data has the same size as the reference data + assert_equal(len(selected_data), len(ref_list)) + + # check if the selected data is equal to the reference data + assert all(x in ref_list for x in selected_data) diff --git a/selector/methods/utils.py b/selector/methods/utils.py index 6e6be010..20c100ff 100644 --- a/selector/methods/utils.py +++ b/selector/methods/utils.py @@ -1,118 +1,118 @@ -# -*- coding: utf-8 -*- -# -# The Selector is a Python library of algorithms for selecting diverse -# subsets of data for machine-learning. -# -# Copyright (C) 2022-2024 The QC-Devs Community -# -# This file is part of Selector. -# -# Selector is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 -# of the License, or (at your option) any later version. -# -# Selector is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see -# -# -- -"""Module for Selection Utilities.""" - -import warnings - -import numpy as np - -__all__ = [ - "optimize_radius", -] - - -def optimize_radius(obj, X, size, cluster_ids=None): - """Algorithm that uses sphere exclusion for selecting points from cluster. - - Iteratively searches for the optimal radius to obtain the correct number - of selected samples. If the radius cannot converge to return `size` points, - the function returns the closest number of samples to `size` as possible. - - Parameters - ---------- - obj: object - Instance of `DirectedSphereExclusion` or `OptiSim` selection class. - X: ndarray of shape (n_samples, n_features) - Feature matrix of `n_samples` samples in `n_features` dimensional space. - size: int - Number of sample points to select (i.e. size of the subset). - cluster_ids: np.ndarray - Indices of points that form a cluster. - - Returns - ------- - selected: list - List of indices of selected samples. - """ - if X.shape[0] < size: - raise RuntimeError( - f"Size of samples to be selected is greater than existing the number of samples; " - f"{size} > {X.shape[0]}." - ) - # set the limits on # of selected points according to the tolerance percentage - error = size * obj.tol - lower_size = round(size - error) - upper_size = round(size + error) - - # select `upper_size` number of samples - if obj.r is not None: - # use initial sphere radius - selected = obj.algorithm(X, upper_size) - else: - # calculate a sphere radius based on maximum of n_features range - # np.ptp returns range of values (maximum - minimum) along an axis - obj.r = max(np.ptp(X, axis=0)) / size * 3 - selected = obj.algorithm(X, upper_size) - - # return selected if the correct number of samples chosen - if len(selected) == size: - return selected - - # optimize radius to select the correct number of samples - # first, set a sensible range for optimizing r value within that range - if len(selected) > size: - # radius should become bigger, b/c too many samples were selected - bounds = [obj.r, np.inf] - else: - # radius should become smaller, b/c too few samples were selected - bounds = [0, obj.r] - - n_iter = 0 - while (len(selected) < lower_size or len(selected) > upper_size) and n_iter < obj.n_iter: - # change sphere radius based on the defined bound - if bounds[1] == np.inf: - # make sphere radius larger by a factor of 2 - obj.r = bounds[0] * 2 - else: - # make sphere radius smaller by a factor of 1/2 - obj.r = (bounds[0] + bounds[1]) / 2 - - # re-select samples with the new radius - selected = obj.algorithm(X, upper_size) - - # adjust lower/upper bounds of radius range - if len(selected) > size: - bounds[0] = obj.r - else: - bounds[1] = obj.r - n_iter += 1 - - # cannot find radius that produces desired number of selected points - if n_iter >= obj.n_iter and len(selected) != size: - warnings.warn( - f"Optimal radius finder failed to converge, selected {len(selected)} points instead " - f"of requested {size}." - ) - - return selected +# -*- coding: utf-8 -*- +# +# The Selector is a Python library of algorithms for selecting diverse +# subsets of data for machine-learning. +# +# Copyright (C) 2022-2024 The QC-Devs Community +# +# This file is part of Selector. +# +# Selector is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 +# of the License, or (at your option) any later version. +# +# Selector is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see +# +# -- +"""Module for Selection Utilities.""" + +import warnings + +import numpy as np + +__all__ = [ + "optimize_radius", +] + + +def optimize_radius(obj, X, size, cluster_ids=None): + """Algorithm that uses sphere exclusion for selecting points from cluster. + + Iteratively searches for the optimal radius to obtain the correct number + of selected samples. If the radius cannot converge to return `size` points, + the function returns the closest number of samples to `size` as possible. + + Parameters + ---------- + obj: object + Instance of `DirectedSphereExclusion` or `OptiSim` selection class. + X: ndarray of shape (n_samples, n_features) + Feature matrix of `n_samples` samples in `n_features` dimensional space. + size: int + Number of sample points to select (i.e. size of the subset). + cluster_ids: np.ndarray + Indices of points that form a cluster. + + Returns + ------- + selected: list + List of indices of selected samples. + """ + if X.shape[0] < size: + raise RuntimeError( + f"Size of samples to be selected is greater than existing the number of samples; " + f"{size} > {X.shape[0]}." + ) + # set the limits on # of selected points according to the tolerance percentage + error = size * obj.tol + lower_size = round(size - error) + upper_size = round(size + error) + + # select `upper_size` number of samples + if obj.r is not None: + # use initial sphere radius + selected = obj.algorithm(X, upper_size) + else: + # calculate a sphere radius based on maximum of n_features range + # np.ptp returns range of values (maximum - minimum) along an axis + obj.r = max(np.ptp(X, axis=0)) / size * 3 + selected = obj.algorithm(X, upper_size) + + # return selected if the correct number of samples chosen + if len(selected) == size: + return selected + + # optimize radius to select the correct number of samples + # first, set a sensible range for optimizing r value within that range + if len(selected) > size: + # radius should become bigger, b/c too many samples were selected + bounds = [obj.r, np.inf] + else: + # radius should become smaller, b/c too few samples were selected + bounds = [0, obj.r] + + n_iter = 0 + while (len(selected) < lower_size or len(selected) > upper_size) and n_iter < obj.n_iter: + # change sphere radius based on the defined bound + if bounds[1] == np.inf: + # make sphere radius larger by a factor of 2 + obj.r = bounds[0] * 2 + else: + # make sphere radius smaller by a factor of 1/2 + obj.r = (bounds[0] + bounds[1]) / 2 + + # re-select samples with the new radius + selected = obj.algorithm(X, upper_size) + + # adjust lower/upper bounds of radius range + if len(selected) > size: + bounds[0] = obj.r + else: + bounds[1] = obj.r + n_iter += 1 + + # cannot find radius that produces desired number of selected points + if n_iter >= obj.n_iter and len(selected) != size: + warnings.warn( + f"Optimal radius finder failed to converge, selected {len(selected)} points instead " + f"of requested {size}." + ) + + return selected diff --git a/tox.ini b/tox.ini index ca12ec95..95b30b91 100644 --- a/tox.ini +++ b/tox.ini @@ -1,280 +1,280 @@ -[gh-actions] -python = - 3.9: py39 - 3.10: py310 - # 3.8: py38, rst_linux, rst_mac, readme, linters, coverage-report, qa - # 3.11: py311, rst_linux, rst_mac, readme, linters, coverage-report, qa - 3.11: py311, rst_linux, rst_mac, readme, coverage-report - # 3.9: py39 - # 3.10: py310 - 3.12: py312 - 3.13: py313 - -[tox] -# todo: add back the linters and qa -# envlist = py39, py310, py311, rst_linux, rst_mac, readme, rst, linters, coverage-report, qa -envlist = py39, py310, py311, py312, py313, rst_linux, rst_mac, readme, rst, coverage-report - -[testenv] -; conda_deps = -; rdkit -; conda_channels = rdkit -deps = - -r{toxinidir}/requirements_dev.txt -commands = - # coverage run --rcfile=tox.ini -m pytest tests - python -m pip install --upgrade pip - # pip install -r requirements.txt - # pip install . - python -m pytest -c pyproject.toml --cov-config=.coveragerc --cov-report=xml --color=yes selector - -# pytest --cov-config=.coveragerc --cov=selector/test -# can run it if needed -# coverage report -m -# prevent exit when error is encountered -ignore_errors = true - -[testenv:readme] -skip_install = true -deps = - readme_renderer - twine - wheel - -r{toxinidir}/requirements.txt - -r{toxinidir}/requirements_dev.txt -commands = - # https://github.com/pypa/twine/issues/977 - python -m pip install importlib_metadata>=7.2.1 build - python -m build --no-isolation - twine check dist/* - -[testenv:rst_linux] -platform = - linux -skip_install = true -deps = - doc8 - rstcheck==3.3.1 -commands = - doc8 --config tox.ini book/content/ -# ignore code-block related error because -# the Sphinx support in rstcheck is minimal. This results in false positives -# rstcheck uses Docutils to parse reStructuredText files and extract code blocks -# fixme: check updates on the following website in the future -# coala.gitbooks.io/projects/content/en/projects/rstcheck-with-better-sphinx-suppor.html - rstcheck --recursive book/content/ --report error \ - --ignore-directives automodule,autoclass,autofunction,bibliography,code-block \ - --ignore-roles cite,mod,class,lineno --ignore-messages code-block - -[testenv:rst_mac] -platform = - darwin -skip_install = true -deps = {[testenv:rst_linux]deps} -commands = {[testenv:rst_linux]commands} - -[testenv:linters] -deps = - flake8 - flake8-docstrings - flake8-import-order>=0.9 - flake8-colors - pep8-naming - pylint==2.13.9 - # black - bandit -commands = - flake8 selector/ selector/tests setup.py - pylint selector --rcfile=tox.ini --disable=similarities - # black -l 100 --check ./ - # black -l 100 --diff ./ - # Use bandit configuration file - bandit -r selector -c .bandit.yml - -ignore_errors = true - -[testenv:coverage-report] -deps = coverage>=4.2 -skip_install = true -commands = -# coverage combine --rcfile=tox.ini - coverage report - -[testenv:qa] -deps = - {[testenv]deps} - {[testenv:linters]deps} - {[testenv:coverage-report]deps} -commands = - {[testenv]commands} - {[testenv:linters]commands} -# {[testenv:coverage-report]commands} -ignore_errors = true - -# pytest configuration -[pytest] -addopts = --cache-clear - --showlocals - -v - -r a - --cov-report term-missing - --cov selector -# Do not run tests in the build folder -norecursedirs = build - -# flake8 configuration -[flake8] -exclude = - __init__.py, - .tox, - .git, - __pycache__, - build, - dist, - *.pyc, - *.egg-info, - .cache, - .eggs, - _version.py, - -max-line-length = 100 -import-order-style = google -ignore = -# E121 : continuation line under-indented for hanging indent - E121, -# E123 : closing bracket does not match indentation of opening bracket’s line - E123, -# E126 : continuation line over-indented for hanging indent - E126, -# E226 : missing whitespace around arithmetic operator - E226, -# E241 : multiple spaces after ‘,’ -# E242 : tab after ‘,’ - E24, -# E704 : multiple statements on one line (def) - E704, -# W503 : line break occurred before a binary operator - W503, -# W504 : Line break occurred after a binary operator - W504, -# D202: No blank lines allowed after function docstring - D202, -# E203: Whitespace before ':' - E203, -# E731: Do not assign a lambda expression, use a def - E731, -# D401: First line should be in imperative mood: 'Do', not 'Does' - D401, - -per-file-ignores = -# F401: Unused import -# this is used to define the data typing - selector/utils.py: F401, -# E1101: rdkit.Chem has no attribute xxx -# D403: first word of the first line should be properly capitalized - selector/feature.py: E1101, D403 - -# doc8 configuration -[doc8] -# Ignore target directories and autogenerated files -ignore-path = book/content/_build/, build/, selector.egg-info/, selector.egg-info, .*/ -# File extensions to use -extensions = .rst, .txt -# Maximal line length should be 100 -max-line-length = 100 -# Disable some doc8 checks: -# D000: Check RST validity (cannot handle the "linenos" directive) -# D002: Trailing whitespace -# D004: Found literal carriage return -# Both D002 and D004 can be problematic in Windows platform, line ending is `\r\n`, -# but in Linux and MacOS, it's "\n" -# Known issue of doc8, https://bugs.launchpad.net/doc8/+bug/1756704 -# ignore = D000,D002,D004 -ignore = D000 - -# pylint configuration -[MASTER] -# This is a known issue of pylint with recognizing numpy members -# https://github.com/PyCQA/pylint/issues/779 -# https://stackoverflow.com/questions/20553551/how-do-i-get-pylint-to-recognize-numpy-members -extension-pkg-whitelist=numpy - -[FORMAT] -# Maximum number of characters on a single line. -max-line-length=100 - -[MESSAGES CONTROL] -# disable pylint warnings -disable= -# attribute-defined-outside-init (W0201): -# Attribute %r defined outside __init__ Used when an instance attribute is -# defined outside the __init__ method. - W0201, -# too-many-instance-attributes (R0902): -# Too many instance attributes (%s/%s) Used when class has too many instance -# attributes, try to reduce this to get a simpler (and so easier to use) -# class. - R0902, -# too many branches (R0912) - R0912, -# too-many-arguments (R0913): -# Too many arguments (%s/%s) Used when a function or method takes too many -# arguments. - R0913, -# Too many local variables (r0914) - R0914, -# Too many statements (R0915) - R0915, -# fixme (W0511): -# Used when a warning note as FIXME or XXX is detected. - W0511, -# bad-continuation (C0330): -# Wrong hanging indentation before block (add 4 spaces). - C0330, -# wrong-import-order (C0411): -# %s comes before %s Used when PEP8 import order is not respected (standard -# imports first, then third-party libraries, then local imports) - C0411, -# arguments-differ (W0221): -# Parameters differ from %s %r method Used when a method has a different -# number of arguments than in the implemented interface or in an overridden -# method. - W0221, -# unecessary "else" after "return" (R1705) - R1705, -# Value XX is unsubscriptable (E1136). this is a open issue of pylint -# https://github.com/PyCQA/pylint/issues/3139 - E1136, -# Used when a name doesn't doesn't fit the naming convention associated to its type -# (constant, variable, class…). - C0103, -# Unnecessary pass statement - W0107, -# Module 'rdkit.Chem' has no 'ForwardSDMolSupplier' member (no-member) - E1101, -# todo: fix this one later and this is a temporary solution -# E0401: Unable to import xxx (import-error) - E0401, -# R1721: Unnecessary use of a comprehension - R1721, -# I1101: Module xxx has no yyy member (no-member) - I1101, -# R0903: Too few public methods (too-few-public-methods) - R0903, -# R1702: Too many nested blocks (too-many-nested-blocks) - R1702, - -[SIMILARITIES] -min-similarity-lines=5 - -# coverage configuration -[run] -branch = True -parallel = True -source = selector - -[paths] -source = - selector - .tox/*/lib/python*/site-packages/selector - .tox/pypy*/site-packages/selector +[gh-actions] +python = + 3.9: py39 + 3.10: py310 + # 3.8: py38, rst_linux, rst_mac, readme, linters, coverage-report, qa + # 3.11: py311, rst_linux, rst_mac, readme, linters, coverage-report, qa + 3.11: py311, rst_linux, rst_mac, readme, coverage-report + # 3.9: py39 + # 3.10: py310 + 3.12: py312 + 3.13: py313 + +[tox] +# todo: add back the linters and qa +# envlist = py39, py310, py311, rst_linux, rst_mac, readme, rst, linters, coverage-report, qa +envlist = py39, py310, py311, py312, py313, rst_linux, rst_mac, readme, rst, coverage-report + +[testenv] +; conda_deps = +; rdkit +; conda_channels = rdkit +deps = + -r{toxinidir}/requirements_dev.txt +commands = + # coverage run --rcfile=tox.ini -m pytest tests + python -m pip install --upgrade pip + # pip install -r requirements.txt + # pip install . + python -m pytest -c pyproject.toml --cov-config=.coveragerc --cov-report=xml --color=yes selector + +# pytest --cov-config=.coveragerc --cov=selector/test +# can run it if needed +# coverage report -m +# prevent exit when error is encountered +ignore_errors = true + +[testenv:readme] +skip_install = true +deps = + readme_renderer + twine + wheel + -r{toxinidir}/requirements.txt + -r{toxinidir}/requirements_dev.txt +commands = + # https://github.com/pypa/twine/issues/977 + python -m pip install importlib_metadata>=7.2.1 build + python -m build --no-isolation + twine check dist/* + +[testenv:rst_linux] +platform = + linux +skip_install = true +deps = + doc8 + rstcheck==3.3.1 +commands = + doc8 --config tox.ini book/content/ +# ignore code-block related error because +# the Sphinx support in rstcheck is minimal. This results in false positives +# rstcheck uses Docutils to parse reStructuredText files and extract code blocks +# fixme: check updates on the following website in the future +# coala.gitbooks.io/projects/content/en/projects/rstcheck-with-better-sphinx-suppor.html + rstcheck --recursive book/content/ --report error \ + --ignore-directives automodule,autoclass,autofunction,bibliography,code-block \ + --ignore-roles cite,mod,class,lineno --ignore-messages code-block + +[testenv:rst_mac] +platform = + darwin +skip_install = true +deps = {[testenv:rst_linux]deps} +commands = {[testenv:rst_linux]commands} + +[testenv:linters] +deps = + flake8 + flake8-docstrings + flake8-import-order>=0.9 + flake8-colors + pep8-naming + pylint==2.13.9 + # black + bandit +commands = + flake8 selector/ selector/tests setup.py + pylint selector --rcfile=tox.ini --disable=similarities + # black -l 100 --check ./ + # black -l 100 --diff ./ + # Use bandit configuration file + bandit -r selector -c .bandit.yml + +ignore_errors = true + +[testenv:coverage-report] +deps = coverage>=4.2 +skip_install = true +commands = +# coverage combine --rcfile=tox.ini + coverage report + +[testenv:qa] +deps = + {[testenv]deps} + {[testenv:linters]deps} + {[testenv:coverage-report]deps} +commands = + {[testenv]commands} + {[testenv:linters]commands} +# {[testenv:coverage-report]commands} +ignore_errors = true + +# pytest configuration +[pytest] +addopts = --cache-clear + --showlocals + -v + -r a + --cov-report term-missing + --cov selector +# Do not run tests in the build folder +norecursedirs = build + +# flake8 configuration +[flake8] +exclude = + __init__.py, + .tox, + .git, + __pycache__, + build, + dist, + *.pyc, + *.egg-info, + .cache, + .eggs, + _version.py, + +max-line-length = 100 +import-order-style = google +ignore = +# E121 : continuation line under-indented for hanging indent + E121, +# E123 : closing bracket does not match indentation of opening bracket’s line + E123, +# E126 : continuation line over-indented for hanging indent + E126, +# E226 : missing whitespace around arithmetic operator + E226, +# E241 : multiple spaces after ‘,’ +# E242 : tab after ‘,’ + E24, +# E704 : multiple statements on one line (def) + E704, +# W503 : line break occurred before a binary operator + W503, +# W504 : Line break occurred after a binary operator + W504, +# D202: No blank lines allowed after function docstring + D202, +# E203: Whitespace before ':' + E203, +# E731: Do not assign a lambda expression, use a def + E731, +# D401: First line should be in imperative mood: 'Do', not 'Does' + D401, + +per-file-ignores = +# F401: Unused import +# this is used to define the data typing + selector/utils.py: F401, +# E1101: rdkit.Chem has no attribute xxx +# D403: first word of the first line should be properly capitalized + selector/feature.py: E1101, D403 + +# doc8 configuration +[doc8] +# Ignore target directories and autogenerated files +ignore-path = book/content/_build/, build/, selector.egg-info/, selector.egg-info, .*/ +# File extensions to use +extensions = .rst, .txt +# Maximal line length should be 100 +max-line-length = 100 +# Disable some doc8 checks: +# D000: Check RST validity (cannot handle the "linenos" directive) +# D002: Trailing whitespace +# D004: Found literal carriage return +# Both D002 and D004 can be problematic in Windows platform, line ending is `\r\n`, +# but in Linux and MacOS, it's "\n" +# Known issue of doc8, https://bugs.launchpad.net/doc8/+bug/1756704 +# ignore = D000,D002,D004 +ignore = D000 + +# pylint configuration +[MASTER] +# This is a known issue of pylint with recognizing numpy members +# https://github.com/PyCQA/pylint/issues/779 +# https://stackoverflow.com/questions/20553551/how-do-i-get-pylint-to-recognize-numpy-members +extension-pkg-whitelist=numpy + +[FORMAT] +# Maximum number of characters on a single line. +max-line-length=100 + +[MESSAGES CONTROL] +# disable pylint warnings +disable= +# attribute-defined-outside-init (W0201): +# Attribute %r defined outside __init__ Used when an instance attribute is +# defined outside the __init__ method. + W0201, +# too-many-instance-attributes (R0902): +# Too many instance attributes (%s/%s) Used when class has too many instance +# attributes, try to reduce this to get a simpler (and so easier to use) +# class. + R0902, +# too many branches (R0912) + R0912, +# too-many-arguments (R0913): +# Too many arguments (%s/%s) Used when a function or method takes too many +# arguments. + R0913, +# Too many local variables (r0914) + R0914, +# Too many statements (R0915) + R0915, +# fixme (W0511): +# Used when a warning note as FIXME or XXX is detected. + W0511, +# bad-continuation (C0330): +# Wrong hanging indentation before block (add 4 spaces). + C0330, +# wrong-import-order (C0411): +# %s comes before %s Used when PEP8 import order is not respected (standard +# imports first, then third-party libraries, then local imports) + C0411, +# arguments-differ (W0221): +# Parameters differ from %s %r method Used when a method has a different +# number of arguments than in the implemented interface or in an overridden +# method. + W0221, +# unecessary "else" after "return" (R1705) + R1705, +# Value XX is unsubscriptable (E1136). this is a open issue of pylint +# https://github.com/PyCQA/pylint/issues/3139 + E1136, +# Used when a name doesn't doesn't fit the naming convention associated to its type +# (constant, variable, class…). + C0103, +# Unnecessary pass statement + W0107, +# Module 'rdkit.Chem' has no 'ForwardSDMolSupplier' member (no-member) + E1101, +# todo: fix this one later and this is a temporary solution +# E0401: Unable to import xxx (import-error) + E0401, +# R1721: Unnecessary use of a comprehension + R1721, +# I1101: Module xxx has no yyy member (no-member) + I1101, +# R0903: Too few public methods (too-few-public-methods) + R0903, +# R1702: Too many nested blocks (too-many-nested-blocks) + R1702, + +[SIMILARITIES] +min-similarity-lines=5 + +# coverage configuration +[run] +branch = True +parallel = True +source = selector + +[paths] +source = + selector + .tox/*/lib/python*/site-packages/selector + .tox/pypy*/site-packages/selector diff --git a/updateheaders.py b/updateheaders.py index 14275347..e96e3e2a 100644 --- a/updateheaders.py +++ b/updateheaders.py @@ -1,137 +1,137 @@ -# -*- coding: utf-8 -*- -# -# The Selector is a Python library of algorithms for selecting diverse -# subsets of data for machine-learning. -# -# Copyright (C) 2022-2024 The QC-Devs Community -# -# This file is part of Selector. -# -# Selector is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 3 -# of the License, or (at your option) any later version. -# -# Selector is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see -# -# -- - - -import os -from fnmatch import fnmatch -from glob import glob - - -def strip_header(lines, closing): - # search for the header closing line, i.e. '# --\n' - counter = 0 - found = False - for line in lines: - counter += 1 - if line == closing: - found = True - break - if found: - del lines[:counter] - # If the header closing is not found, we assume it is not present. - # add a header closing line - lines.insert(0, closing) - - -def fix_python(fn, lines, header_lines): - # check if a shebang is present - do_shebang = lines[0].startswith("#!") - # remove the current header - strip_header(lines, "# --\n") - # add a pylint line for test files: - # if os.path.basename(fn).startswith('test_'): - # if not lines[1].startswith('#pylint: skip-file'): - # lines.insert(1, '#pylint: skip-file\n') - # add new header (insert in reverse order) - for hline in header_lines[::-1]: - lines.insert(0, ("# " + hline).strip() + "\n") - - if not hline.startswith("# -*- coding: utf-8 -*-"): - # add a source code encoding line - lines.insert(0, "# -*- coding: utf-8 -*-\n") - - if do_shebang: - lines.insert(0, "#!/usr/bin/env python\n") - - -def fix_c(fn, lines, header_lines): - # check for an exception line - for line in lines: - if "no_update_headers" in line: - return - # remove the current header - strip_header(lines, "//--\n") - # add new header (insert must be in reverse order) - for hline in header_lines[::-1]: - lines.insert(0, ("// " + hline).strip() + "\n") - - -def fix_rst(fn, lines, header_lines): - # check for an exception line - for line in lines: - if "no_update_headers" in line: - return - # remove the current header - strip_header(lines, " : --\n") - # add an empty line after header if needed - if len(lines[1].strip()) > 0: - lines.insert(1, "\n") - # add new header (insert must be in reverse order) - for hline in header_lines[::-1]: - lines.insert(0, (" : " + hline).rstrip() + "\n") - # add comment instruction - lines.insert(0, "..\n") - - -def iter_subdirs(root): - for dn, _, _ in os.walk(root): - yield dn - - -def main(): - source_dirs = [".", "book", "notebooks", "selector"] + list(iter_subdirs("selector")) - - fixers = [ - ("*.py", fix_python), - ("*.pxd", fix_python), - ("*.pyx", fix_python), - ("*.txt", fix_python), - ("*.c", fix_c), - ("*.cpp", fix_c), - ("*.h", fix_c), - ("*.rst", fix_rst), - ] - - f = open("HEADER") - header_lines = f.readlines() - f.close() - - for sdir in source_dirs: - print("Scanning:", sdir) - for fn in glob(sdir + "/*.*"): - if not os.path.isfile(fn): - continue - for pattern, fixer in fixers: - if fnmatch(fn, pattern): - print(" Fixing:", fn) - with open(fn) as f: - lines = f.readlines() - fixer(fn, lines, header_lines) - with open(fn, "w") as f: - f.writelines(lines) - break - - -if __name__ == "__main__": - main() +# -*- coding: utf-8 -*- +# +# The Selector is a Python library of algorithms for selecting diverse +# subsets of data for machine-learning. +# +# Copyright (C) 2022-2024 The QC-Devs Community +# +# This file is part of Selector. +# +# Selector is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 3 +# of the License, or (at your option) any later version. +# +# Selector is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see +# +# -- + + +import os +from fnmatch import fnmatch +from glob import glob + + +def strip_header(lines, closing): + # search for the header closing line, i.e. '# --\n' + counter = 0 + found = False + for line in lines: + counter += 1 + if line == closing: + found = True + break + if found: + del lines[:counter] + # If the header closing is not found, we assume it is not present. + # add a header closing line + lines.insert(0, closing) + + +def fix_python(fn, lines, header_lines): + # check if a shebang is present + do_shebang = lines[0].startswith("#!") + # remove the current header + strip_header(lines, "# --\n") + # add a pylint line for test files: + # if os.path.basename(fn).startswith('test_'): + # if not lines[1].startswith('#pylint: skip-file'): + # lines.insert(1, '#pylint: skip-file\n') + # add new header (insert in reverse order) + for hline in header_lines[::-1]: + lines.insert(0, ("# " + hline).strip() + "\n") + + if not hline.startswith("# -*- coding: utf-8 -*-"): + # add a source code encoding line + lines.insert(0, "# -*- coding: utf-8 -*-\n") + + if do_shebang: + lines.insert(0, "#!/usr/bin/env python\n") + + +def fix_c(fn, lines, header_lines): + # check for an exception line + for line in lines: + if "no_update_headers" in line: + return + # remove the current header + strip_header(lines, "//--\n") + # add new header (insert must be in reverse order) + for hline in header_lines[::-1]: + lines.insert(0, ("// " + hline).strip() + "\n") + + +def fix_rst(fn, lines, header_lines): + # check for an exception line + for line in lines: + if "no_update_headers" in line: + return + # remove the current header + strip_header(lines, " : --\n") + # add an empty line after header if needed + if len(lines[1].strip()) > 0: + lines.insert(1, "\n") + # add new header (insert must be in reverse order) + for hline in header_lines[::-1]: + lines.insert(0, (" : " + hline).rstrip() + "\n") + # add comment instruction + lines.insert(0, "..\n") + + +def iter_subdirs(root): + for dn, _, _ in os.walk(root): + yield dn + + +def main(): + source_dirs = [".", "book", "notebooks", "selector"] + list(iter_subdirs("selector")) + + fixers = [ + ("*.py", fix_python), + ("*.pxd", fix_python), + ("*.pyx", fix_python), + ("*.txt", fix_python), + ("*.c", fix_c), + ("*.cpp", fix_c), + ("*.h", fix_c), + ("*.rst", fix_rst), + ] + + f = open("HEADER") + header_lines = f.readlines() + f.close() + + for sdir in source_dirs: + print("Scanning:", sdir) + for fn in glob(sdir + "/*.*"): + if not os.path.isfile(fn): + continue + for pattern, fixer in fixers: + if fnmatch(fn, pattern): + print(" Fixing:", fn) + with open(fn) as f: + lines = f.readlines() + fixer(fn, lines, header_lines) + with open(fn, "w") as f: + f.writelines(lines) + break + + +if __name__ == "__main__": + main() From 88318482855495a48614134ac0020568c74e78a0 Mon Sep 17 00:00:00 2001 From: Harendra kumar Date: Sun, 29 Mar 2026 22:38:23 +0530 Subject: [PATCH 2/6] Remove unwanted file README.md --- README.md | 94 ------------------------------------------------------- 1 file changed, 94 deletions(-) delete mode 100644 README.md diff --git a/README.md b/README.md deleted file mode 100644 index 38f898b0..00000000 --- a/README.md +++ /dev/null @@ -1,94 +0,0 @@ -
- - Logo -
- -[![This project supports Python 3.9+](https://img.shields.io/badge/Python-3.9+-blue.svg)](https://python.org/downloads) -[![GPLv3 License](https://img.shields.io/badge/License-GPL%20v3-yellow.svg)](https://opensource.org/licenses/) -[![CI Tox](https://github.com/theochem/Selector/actions/workflows/ci_tox.yaml/badge.svg?branch=main)](https://github.com/theochem/Selector/actions/workflows/ci_tox.yaml) -[![codecov](https://codecov.io/gh/theochem/Selector/graph/badge.svg?token=0UJixrJfNJ)](https://codecov.io/gh/theochem/Selector) - -The `Selector` library provides methods for selecting a diverse subset of a (molecular) dataset. - -## Citation - -Please use the following citation in any publication using the `selector` library: - -```md -@article{selector_library, -author = {Meng, Fanwang and Martínez González, Marco and Chuiko, Valerii and Tehrani, Alireza and Al Nabulsi, Abdul Rahman and Broscius, Abigail and Khaleel, Hasan and López-P{\'e}rez, Kenneth and Miranda-Quintana, Ramón Alain and Ayers, Paul W. and Heidar-Zadeh, Farnaz}, -title = {Selector: A General Python Library for Diverse Subset Selection}, -journal = {Journal of Chemical Information and Modeling}, -volume = {0}, -number = {0}, -pages = {null}, -year = {0}, -doi = {10.1021/acs.jcim.5c01499}, -note ={PMID: 41591801}, -URL = {https://doi.org/10.1021/acs.jcim.5c01499} -} -``` - -## Web Server - -We have a web server for the `selector` library at https://huggingface.co/spaces/QCDevs/Selector. -For small and prototype datasets, you can use the web server to select a diverse subset of your -dataset and compute the diversity metrics, where you can download the selected subset and the -computed diversity metrics. - -## Installation - -It is recommended to install `selector` within a virtual environment. To create a virtual -environment, we can use the `venv` module (Python 3.9+, -https://docs.python.org/3/tutorial/venv.html), `miniconda` (https://conda.io/projects/conda/en/latest/user-guide/tasks/manage-environments.html), or -`pipenv` (https://pipenv.pypa.io/en/latest/). - -### Installing from PyPI - -To install `selector` with `pip`, we can install the latest stable release from the Python Package Index (PyPI) as follows: - -```bash -# install the stable release -pip install qc-selector -``` - -### Installing from The Prebuild Wheel Files - -To download the prebuilt wheel files, visit the [PyPI page](https://pypi.org/project/qc-selector/) -and [GitHub releases](https://github.com/theochem/Selector/tags). - -```bash -# download the wheel file first to your local machine -# then install the wheel file -pip install file_path/qc_selector-0.1.0-py3-none-any.whl - -``` - -### Installing from the Source Code - -In addition, we can install the latest development version from the GitHub repository as follows: - -```bash -# install the latest development version -pip install git+https://github.com/theochem/Selector.git -``` - -We can also clone the repository to access the latest development version, test it and install it as follows: - -```bash -# clone the repository -git clone git@github.com:theochem/Selector.git - -# change into the working directory -cd Selector -# run the tests -python -m pytest . - -# install the package -pip install . - -``` - -## More - -See https://selector.qcdevs.org for full details. From afd8be14cc0776040235e8e064b47619d459e059 Mon Sep 17 00:00:00 2001 From: mademind122333-jp Date: Mon, 30 Mar 2026 22:51:53 +0530 Subject: [PATCH 3/6] examples --- README.md | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 00000000..529afe8a --- /dev/null +++ b/README.md @@ -0,0 +1,105 @@ +
+ + Logo +
+ +[![This project supports Python 3.9+](https://img.shields.io/badge/Python-3.9+-blue.svg)](https://python.org/downloads) +[![GPLv3 License](https://img.shields.io/badge/License-GPL%20v3-yellow.svg)](https://opensource.org/licenses/) +[![CI Tox](https://github.com/theochem/Selector/actions/workflows/ci_tox.yaml/badge.svg?branch=main)](https://github.com/theochem/Selector/actions/workflows/ci_tox.yaml) +[![codecov](https://codecov.io/gh/theochem/Selector/graph/badge.svg?token=0UJixrJfNJ)](https://codecov.io/gh/theochem/Selector) + +The `Selector` library provides methods for selecting a diverse subset of a (molecular) dataset. + +## Citation + +Please use the following citation in any publication using the `selector` library: + +```md +@article{selector_library, +author = {Meng, Fanwang and Martínez González, Marco and Chuiko, Valerii and Tehrani, Alireza and Al Nabulsi, Abdul Rahman and Broscius, Abigail and Khaleel, Hasan and López-P{\'e}rez, Kenneth and Miranda-Quintana, Ramón Alain and Ayers, Paul W. and Heidar-Zadeh, Farnaz}, +title = {Selector: A General Python Library for Diverse Subset Selection}, +journal = {Journal of Chemical Information and Modeling}, +volume = {0}, +number = {0}, +pages = {null}, +year = {0}, +doi = {10.1021/acs.jcim.5c01499}, +note ={PMID: 41591801}, +URL = {https://doi.org/10.1021/acs.jcim.5c01499} +} +``` + +## Web Server + +We have a web server for the `selector` library at https://huggingface.co/spaces/QCDevs/Selector. +For small and prototype datasets, you can use the web server to select a diverse subset of your +dataset and compute the diversity metrics, where you can download the selected subset and the +computed diversity metrics. + +## Installation + +It is recommended to install `selector` within a virtual environment. To create a virtual +environment, we can use the `venv` module (Python 3.9+, +https://docs.python.org/3/tutorial/venv.html), `miniconda` (https://conda.io/projects/conda/en/latest/user-guide/tasks/manage-environments.html), or +`pipenv` (https://pipenv.pypa.io/en/latest/). + +### Installing from PyPI + +To install `selector` with `pip`, we can install the latest stable release from the Python Package Index (PyPI) as follows: + +```bash +# install the stable release +pip install qc-selector +``` + +### Installing from The Prebuild Wheel Files + +To download the prebuilt wheel files, visit the [PyPI page](https://pypi.org/project/qc-selector/) +and [GitHub releases](https://github.com/theochem/Selector/tags). + +```bash +# download the wheel file first to your local machine +# then install the wheel file +pip install file_path/qc_selector-0.1.0-py3-none-any.whl + +``` +from selector import optisim_selection +import numpy as np + +# Example dataset: 1000 points with 5 features +points = np.random.rand(1000, 5) + +# Select 50 diverse points using OptiSim +selected_points = optisim_selection(points, n_select=50) + +print("Number of selected points:", len(selected_points)) + + +### Installing from the Source Code + +In addition, we can install the latest development version from the GitHub repository as follows: + +```bash +# install the latest development version +pip install git+https://github.com/theochem/Selector.git +``` + +We can also clone the repository to access the latest development version, test it and install it as follows: + +```bash +# clone the repository +git clone git@github.com:theochem/Selector.git + +# change into the working directory +cd Selector +# run the tests +python -m pytest . + +# install the package +pip install . + +``` + +## More + +See https://selector.qcdevs.org for full details. From cdc08e01060337f6cae67d8f63afc67221d649ca Mon Sep 17 00:00:00 2001 From: mademind122333-jp Date: Mon, 30 Mar 2026 21:20:48 +0530 Subject: [PATCH 4/6] Added test.txt on my-feature-branch --- test.txt | Bin 0 -> 64 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 test.txt diff --git a/test.txt b/test.txt new file mode 100644 index 0000000000000000000000000000000000000000..da0ba17e46e7bfbec0f2331e0ff417f205ad2ee4 GIT binary patch literal 64 zcmezWFN7hLp_rkBA(J7GA)P^iAsEQd0pet!SUy7$P$U^h=K*;|Ks8AWrC_xn5ncu^ F1_1pv4U_-? literal 0 HcmV?d00001 From ca89239b08d0880b835d04fa68a311fce44c3010 Mon Sep 17 00:00:00 2001 From: mademind122333-jp Date: Mon, 30 Mar 2026 21:23:20 +0530 Subject: [PATCH 5/6] Added test.txt on my-feature-branch --- test.txt | Bin 64 -> 48 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/test.txt b/test.txt index da0ba17e46e7bfbec0f2331e0ff417f205ad2ee4..fcc92c93ace9677268331079d5b53658b0703dd5 100644 GIT binary patch delta 23 ecmZ=T5d8nom!XnDfgz0{lc9*An4x5%qC5ao Date: Mon, 30 Mar 2026 22:07:16 +0530 Subject: [PATCH 6/6] =?UTF-8?q?README=20=E0=A4=AE=E0=A5=87=E0=A4=82=20?= =?UTF-8?q?=E0=A4=AC=E0=A4=A6=E0=A4=B2=E0=A4=BE=E0=A4=B5=20=E0=A4=95?= =?UTF-8?q?=E0=A4=BF=E0=A4=AF=E0=A4=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tatus | 931 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 931 insertions(+) create mode 100644 tatus diff --git a/tatus b/tatus new file mode 100644 index 00000000..1ac63f1d --- /dev/null +++ b/tatus @@ -0,0 +1,931 @@ +48a161f (HEAD -> my-feature-branch) Added test.txt on my-feature-branch +acc3304 Added test.txt on my-feature-branch +918920c (main) my first contributtion +5183815 (origin/main, origin/HEAD) Reverted to macos from macOS +1ebbc7f Fix: workflow issues to ensure github actions run reliably +74f9ae5 Fix: Restrict jupyter-book version to restore website deployment +1d500a0 Fix: Typo in documentation of get_initial_selection function +a536369 (tag: v0.1.4) Update numpy version +e96c937 Fix numpy.trapz, deprecated since NumPy 2.0 +ddfeb9b Add reference information +8e244f4 (tag: v0.1.3) Clean up the image classification example +a0cd5c3 Fix the title of the Jupyter notebook +9f42054 Use Python 3.12 +2377868 Add support of Python 3.14 +00c90be Update Jupyter book configurations +356f009 Add example of image classification +d9bf372 Add subset selection example with class labels +9c3cd6c (tag: v0.1.2) Update docstrings and documentation (#281) +48864dd (tag: v0.1.1a1, tag: v0.1.1) Add checking that binary matrix is not suitable for hypershpere overlap (#280) +6e0da09 Fix outdated docstrings (#279) +ba3969e Fix imports (#278) +06ea0d4 (tag: v0.1.0) Update README.md (#277) +913dc88 Add missing dependencies (#276) +c04a253 (origin/add_dist) Add link to webserver (#275) +2367dae (tag: v0.0.3) Fix ref_index of `OptiSim` (#272) +282d6e3 Hyperlink Update in Tutorial Notebooks (#271) +2eb1d7f (tag: v0.0.2post1) Add support of selecting different from subsets proportionately (#270) +90acdfe Clean up the distance function kwargs for `DISE` (#269) +d080d9c Remove unused GitHub Action file for building documentation website (#267) +6c6889f Update TOC in website (#266) +d4498a6 (tag: v0.0.2b12) Update README.md (#265) +19c8cf7 (tag: v0.0.2b11) Fix the building reference index when `ref_index` is None in `DISE` (#264) +198e004 Update the Jupyter Book (#263) +c678c55 Fix the rendering problem (#262) +ba03647 Clean up Package PyPI release (#261) +5663b0b Add PyPI release GitHub Action YAML file (#259) +e7d0f78 Clean up notebooks (#257) +86f7b20 Add tutorial notebook for diversity measures (#250) +0c6189b Add support of distance function and flexible reference index for `DISE` (#249) +7f0a03b Add init to measures & similarity measures. (#254) +a7c7e63 Update package structure (#251) +5a7e001 Quick Start Notebook (#186) +8db346b Rename X --> x +ad8fe15 Use lower case argument names following numpy +ca82329 Fix typos +545f829 Add docstrings for the divergences of MacOS and Ubuntu systems +6b6174b Add testing for the case when KD-Tree query gives an integer +2af583e Use stable sorting in numpy +dc6bebf Fix the KD-Tree query return +e1804a4 Rename the instance name to avoid ambiguity +68fec6a Fix failing tests for `DISE` +e3a67c9 Exclude neighbours of the ref_index in DISE algorithm +11806d0 Update the usage of diversity calculations in `partition` module +2a66aeb Update the documentation for `diversity` module +d95de42 Rename "hypersphere overlap of subset" to "hypersphere_overlap" +773cf2f Update `scipy` and `pytest` version in pyproject.toml +ca8ee49 Use version 4.5.0 for codecov +8639cae Fix the failing codecov upload +be49d65 (origin/tmp) Fix the numerical stability issue of log det function +8b46637 Fix the errors when only some feature columns are constants for `wdud` (#225) +556b911 Fix failing `CodeCov` report (#231) +e26f375 Make sim-based methods consistent with rest of algorithms +3d8f34a Minor changes to the distance-based methods +259b517 Refactor sim.py module +ffcb234 Rename arguments in partition.py +d931154 Follow the practice of adding dependencies +fb55443 Add missing dependencies when building +344d9bc Add `build` as a dependency +03a40c9 Use `--no-isolation` +543e938 Fix missing `-m` tag +d29ce17 Fix error with `twine` +ee8ed84 Fix the error of building packages with `setup.py` +eb6cd91 Relocate the file needed for testing +8a68fb1 Relocate the testing module for similarity based methods +fe51b62 Rename simlarity.py to sim.py +2590395 Cleaning up +cf45879 Add black fixes +141f846 Make small fixes to docstrings +0c991a7 Calculate medoid and outlier with inv_order = 1 +b28d0d7 Add select_outlier test +7aa3333 Add select_medoid test +e1fdcd8 Add reference data for isim +50b4550 Rename esim tests and improve tests documentation +529b56e Refactor tests to comply with new nsimilarity api +e0eca7c Add isim method to SimilarityIndex +a04cd6a Refactor NSimilarity init +4ef3135 Add new environment token to fix the failing updating coverage report (#217) +c34e2b4 Fix the failing testing because of the architecture change of MacOS (#214) +55bf0b9 Merge pull request #204 from FanwangM/cleaning +dbc2202 Cleaning up +3051475 Merge pull request #199 from Dhrumil07/scaled_similarity_support +b9c1ee6 Merge branch 'theochem:main' into scaled_similarity_support +28edfe3 minor changes (reformatting) +ecc6b75 Merge pull request #203 from FanwangM/update_setup +85b0aba Update description +0ce2e26 Merge pull request #201 from FanwangM/fix_codecov2 +84c6b93 Merge pull request #200 from theochem/pre-commit-ci-update-config +9b7db91 Use `setup-python` v5 +e6d805b reformatting code and fixing pre-commit errors +10caa84 reformatting the code +7a4e446 adding a log message for binary similarity matrices +9abce1a [pre-commit.ci] pre-commit autoupdate +155a79e added the tests for scaled_similarity_matrix method +87ca793 added scaled_similarity_matrix method +9468665 Merge pull request #198 from Dhrumil07/fixing_documentation +01ce9f0 fixing the spelling errors in documentation +8be0c0f Merge pull request #195 from FanwangM/fix_codecov +369b053 Upgrade codecov-action version +867a9d3 Merge pull request #193 from FanwangM/README +3f5f7e6 Update installation instruction +bcb6dfa Merge pull request #190 from theochem/pre-commit-ci-update-config +6a9d901 [pre-commit.ci] pre-commit autoupdate +c5ecf0b Merge pull request #187 from theochem/fix_hypersphere_overlap_of_subset +b7fc00c Add fix to hypersphere_overlap_of_subset +b652992 Minor fixes +8418c6f Make diversity docstring consistent +0b85329 Reset r to r0 when sampling from multiple cluster +183e253 Bugfix in DISE because labels were not used +d8c7fff Rename cluster_id to labels in DISE +4a225f4 Check labels and X have the same size +a9cf0c6 Update condition for warning in optimize_radius +2935f62 Make OptiSim and DISE args consistent +b43ce7f Improve Distance-Based methods checks & docstring +ac63fe4 Merge pull request #185 from FanwangM/readme +0de2c9b Remove duplicated line +97cf67d Merge pull request #184 from FanwangM/clean_doc +27eadc3 Remove readthedocs.yml because we are using jupyter-book now +1be2af2 Fix the rst file paths +259f82a Remove doc folder as it's useless for the jupyter-book +43f06ed Merge pull request #182 from FanwangM/fix_website +9da5bc0 Add token arugments to codecov-action +aad4b67 Update conf.py for sphinx +8d0795c Add codecov related files to .gitignore +c8201f4 Use secrets in GitHub and remove the explicit token for codecov +7399045 Fix duplicated lines +2032261 Update Python version constrain +702d2b0 Update the timestamp from 2022 to 2023 +57034a0 Fix the order of dependencies in requirements.txt +f407926 Remove padelpy from requirements_dev.txt +b29aa97 Fix reference in dosctring +3375abd Update contents for pyproject.toml +2bebce9 Update the package information for the jupyter book +629f760 Merge pull request #181 from FanwangM/updates_docs +88114e5 Clean up unwanted strings when fixing merge conflicts +476fbd6 Fix missing coverage report +4a9eab6 Fix failing tests with running pytest as module +7a2d3bd Update the configuration of pytest +1e757c9 Fix testing folder name for flake8 +f9a46b6 Remove molecule loader +9c43699 Update updateheaders.py +7ded582 Clean up following pre-commit +cf83769 Update contents of book following pre-commit +6a485ed Update doc content following pre-commit +3c190e1 Add pyproject.toml draft +d2a0cc8 Rename `DiverseSelector` to `selector` for updateheaders.py +e15cc19 Update contents of README.md for package renaming +25941d9 Add back the checking of website yaml file +3799c77 Remove versioneer.py +d832b1f Rename `DiverseSelector` to `selector` +8ac8714 Remove autopepe8 from pre-commit config +12b0688 Remove skipped folders +aba1b7a Merge pull request #180 from FanwangM/fix_testing +33f6f87 Rename `DiverseSelector` to `selector` +bb8e77c Rename `DiverseSelector` to `selector` +200db51 Rename `DiverseSelector` to `selector` +55889b1 Remote _version.py +ded2813 Rename package and remove versioner +7218f6b Rename `DiverseSelector` to `selector` +84313c1 Update testing folder name for tox +311266a Remove versioner +5a7ba58 Rename methods/dissimilarity.py to methods/distance.py +262d083 Rename GridPartitioning to GridPartition +7b0e76f Rename distance.py to similarity.py +6b41d68 Rename DirectedSphereExclusion to DISE +4080403 Move DirectedSphereExclusion +3ac5a85 Update HEADER +c9d9991 Rename DiverseSelector to selector +3507a33 Move files in test to tests +65b6dda Remove data files for testing molecules +cfa6d5d Remove unused random_seed +f242f3f Merge pull request #177 from FanwangM/fix_shannon_entropy +ac8af8a Merge pull request #168 from FanwangM/pre_commit_fix +b1537b4 Merge pull request #161 from theochem/new_similarity_methods +ea825dd Merge pull request #162 from Ali-Tehrani/grid_partition +17b8aa8 Merge branch 'main' into grid_partition +d48b622 Fix test_partition.py conflicts +fb037ec Comment to clarify the choice of interpolation x +91d1431 Remove testing for `entropy()` +6e736ec Remove the `entropy()` function +4eb670d Merge pull request #179 from RichRick1/website +e30f530 deleted the notebook folder from doc +f0851ae Merge pull request #178 from FanwangM/converter +6acba2e Fix failing test due to the similarity matrix is not symmetric +693255f Add symmetric check for 2D arrays +0355767 Polish the docstrings for `sim_to_dist()` function +5c198a9 Add scaling factor for converters +f563117 Add more variants of Shannon entropy and testing +c5c466a Remove redundant empty lines +00a234c Fix diversity and update testing +138104b Fix the implementation Shannon entropy +391c6b3 Add testing example for Shannon entropy diversity +0d890b3 Fix the problem when p_i equals zero +9c74867 Merge pull request #175 from FanwangM/notebooks +ce8abf9 Polish the installazation notebook +75bc451 Merge pull request #174 from FanwangM/fix_permission2 +9c6f24d Only run the build on push events +69f9e6a Add write access to contents +ea22b94 Merge pull request #173 from FanwangM/fix_permission +b910bb1 Disable the website build on push operation +d0026ea Add write permission to gh-pages for `GITHUB_TOKEN` +3bc9c02 Merge pull request #172 from FanwangM/fix_web3 +8bc1cd4 Add link of source website providing hints +e1b58a4 Fix the problem of pushing website with GitHub Actions +92effc1 Merge pull request #170 from FanwangM/fix_ghpages +0300d3d Update website deployment GitHub Action +2344c1f Merge pull request #169 from RichRick1/website +b0de69f fixed logo +3eff238 updated logo +acada77 rebuild the book +ca8ca3c fixed landing page +aa0288e updated installation page +f471197 Update excluded folder settings +1ec0a22 Fix `bandit` in pre-commit config +79e4964 Fix black arguments in pre-commit hooks +9818e81 Add metadata in setup.cfg +a4e97c6 Skip several documentation related folders +2733dab Reorder the dependencies +ffdb3eb Use end-of-file-fixer only for Python files +91cbe34 Disable `autofix_prs` for pre-commit ci +65775b5 Disable flake8 linter for now +1bd9d57 Add .pre-commit-hooks.yaml +2ded61a Update .pre-commit-config.yaml +f696e71 Remove .lgtm.yml +3c984a4 Add the testing folder of methods to codecovm.yml +2087180 Update codecov.yml to fix the coverage calculations +91f5f30 Update folder name in .coveragerc +9ab7507 Merge pull request #166 from FanwangM/quick_fix +168ae7f Remove testpath in tox.ini +2ce5986 Fix test paths +1d33448 Merge pull request #165 from FanwangM/fix_testing +4519e6c Only publish the website when in main branch +84ff7c7 Add .pre-commit-config.yaml +8ab158f Add .pre-commit-config.yaml +e5c175a Fix value check +eeac3e1 Remove unnecessary check +fc65196 Improve docstring +b0e74cb Change weight factor functions to private methods +ba30f16 Add one liner docstrings to SI dict functions +f3243b2 Correct tests for the new methods api +ad106e6 Clean calculate_outlier +6a8569d Clean calculate_medoid +f39ac1f Clean __call__ method +39d5983 Drop .pre-commit-config.yaml +389ead6 Clean _calculate_counters method +59aeb38 Clean SimilarityIndex docstring +17aff2d Fix package directory for coverage report +ce013c8 Temporarily stop linter checkings +e5649e3 Fix `scipy` version +496691c Add pre-commit +44f1b8d Add pre-commit configuration +988e04b Disable linter checking for now +bdca990 Merge pull request #164 from FanwangM/add_pyproject +1b4680f Enable Python 3.10 +076c501 Remove duplicated dependencies in tox.ini +4076bf5 Use Python 3.9, 3.10 and 3.11 +d338bc0 Use Python 3.11 for testing +2b58908 Downgrade `scipy` version +a351b9c Update CI configurations +87c6052 Upgrade `pip` before using it in CI +7009c26 Fix `scipy` version because of the change of `scipy` testing +799c757 Fix `pytest` 7.4.0 for temporary solution because of ImportPathMismatchError from `pytest` +b2155cd Add `hypothesis` as required by pytest for Python 3.8 +8d22364 Fix testing folder path +fe312ba Fix test directory +6db0f8e Remove molecules module +7584e63 (origin/molecular_features) Rename test to tests +b4b6566 Fix black issues of converter module +a7d9402 Update README.md +05e6d8d Remove unused import and fix balck issues +8f8341f Update __all__ of distance.py module +d0d83cc Refresh common module and fix black violations +ab1847b Remove empty test_clustering.py file +208a926 Refactor dissimilarity module of selectors +a80f685 Change methods/base.py arg names & fix black issues +6ea40df Remove repeated implementation of partition_points_to_bins_equifrequent +fd20c2f Polish GridPartitioning class +c43ed7d Fix black violations of test_partition.py +96d4014 Fix hypersphere arg to match correct naming +60556e5 Fix bug in compute_hypersphere +a954a2c Fix diversity to be a list of tuples +8cbc218 Remove redundant utils.py module +a87c600 Merge pull request #150 from maximilianvz/polish_dissimilarity +a60e1f3 Merge branch 'main' into polish_dissimilarity +7b8b68d Add support of `explicit_diversity_index` for computing the diversity +9764f7e Update the calculation of diversity with fixed function of `compute_diversity` +b9ca746 Update doc typos +cc7a9ae Add and fix whitespaces +dd27ce0 Refactor getting the bins to a seperate method +f80dc97 Add tests for grid partioning +ed880bc Refactor all methods in Grid partitioning +5c7a53a Remove max_dim and refactor cells variable +de79fc5 Improve docs to grid partitioning +64c2600 Remove cluster ids and projection onto PCA +2f0600f Fix to compute diversity in grid partitioning +b26fac0 Merge pull request #163 from FanwangM/polish_diversity +d10686e Update GitHub Action versions +7bf5088 Replace white spaces with underscore for diversity measurement methods +011b3b3 Merge pull request #138 from theochem/fix_diversity +5b9f1e8 Fix failing tests +2127fba Merge branch 'main' into fix_diversity +0e26edc Reformat docstrings +4e0f5e0 Merge pull request #158 from xychem/fix_optisim +06fdb1b Get tests to 100% coverage +5fa00d3 Adjust tolerance and enforce subset selection +f7232cd Merge pull request #139 from theochem/sim2dist +c262999 Check raises in the NSimilarity class +efc1693 Join related checks for correct paremeters +d805500 Improve raises for SimilarityIndex class +f7b386d Add checks to calculate_medoid +b93eddb Change variable name to be consistent +4e1a6dc Add tests for init and _calculate_counters raises +3ab9f1d Rename ref_similarity_data.txt to ref_similarity_data.csv +4e9baf9 Add linters fixes to tests +187d50b Add linters fixes +3994f5b fix type-hint error +f53c758 Fix __init__.py +ad2a7a2 Check for valid function parameter values +76ab608 Add type hinting to functions +09fc019 Improve `select_from_cluster` of `NSimilarity` +ce75946 Add black fixes to simmilarity tests +6c809bf Fix tests location +f4920ea Add type hints to _get_new_index +9daeb46 Add type hints to Nsimilarity.__init__ +d159947 Improve styling and format +a751625 Format fixes +c5183d5 Black and Format fixes +3190fc4 Add select_from_cluster method and test +3280fc6 Implement get_new_index and test +82f8b7e Add member function _scale_data +a6e41ca Add class NSimilarity +e00f3f2 Code calculate_outlier member function and test +be8fc4f Code calculate_medoid member function and test +91870c6 Select proper parameter combinations for tests +a4fd03e Code _call method of Similarity index and add test +68db9dd Add utility functions for calculating indexes +2707feb Code _calculate_counters class method +931c573 Create SimilarityIndex class +c17b346 Merge pull request #160 from FanwangM/updated_readme +9e189d2 Update README.md +df8e626 Merge pull request #157 from theochem/improve_notebook +ecbab18 Small improvement to text +bbe5031 Improve Jupyter Notebook Tutorial +bc4c2fd Merge pull request #155 from theochem/debug_DirectedSphereExclusion +eefe251 Fix small bug on OptiSim class +4eb3c15 Debug DirectedSphereExclusion +32a8733 Fix tolerance value +d0b9c79 Merge pull request #153 from RichRick1/book +717452a Improve while loop for coverage +cf07b24 Update website_auto.yml +f660144 Update website_auto.yml +35c4e70 Change "Notes" to "References" +c2619ed Fix parameter description spacing +14fe90f Update website_auto.yml +0357cb7 Update website_auto.yml +b54df4a Update requirements.txt +c504952 Update website_auto.yml +c7b7eb7 Create website_auto.yml +322fe51 build book +640500e added autodeploy +c5dfee5 added autodeploy +7aaea32 Merge pull request #151 from RichRick1/book +8b1cff6 Merge branch 'main' into book +265b8b2 addresses issues +7aeec91 Merge pull request #147 from theochem/test_notebook +64eedbe fixed the text +9f0b4a2 added logo +6886e48 added logo +af4ffb8 added the interactive colab launching +c8412e7 updated book +161bf2c Fix typo +a5bd987 Polish documentation and variable names +9ec93c8 created book template +4af52e1 move nearest average tanimoto to diversity.py, add tests +7ffe23c Small fixes for the examples to work +2f715c0 Add black fixes +573a5c3 Fix Directed Sphere Exclusion example (in notebook) +2630575 Fix grid partitioning example (notebook) +517875e Fix maxsum example +5a5f1d7 Fix MinMax selection with clusters example +808d468 Fix example Grid Partitioning Method +6da8c9c Fix Directed Sphere Exclusion example +f90bc75 Fix OptiSim example +89dc2ee Fix Brute Strength - MaxMin example +a39237b Generate synthetic data using sklearn +2a8ac47 Merge pull request #142 from theochem/directed_spheres +ee0592b Merge branch 'main' into directed_spheres +f62cea9 Fix long line +d5c1fbc Finalize DirectedSphereExclusion implementation +49ec003 add cs as explicit_diversity_index argument, update docs +59e2af6 Fix failed tests, wrong imports, and black updates +1291c47 Merge pull request #137 from theochem/polish_dist +594c3d1 Fix coverage configuration +4d29f11 Update docstring, black fixes, & error messages +68b938e Finalize test_distance.py and apply black +7bcb291 Make Parameters docstring match sklearn +74f9764 Finalize nearest_average_tanimoto function +563fb46 Finalize tanimoto function +dc92f44 Finalize pairwise_similarity_bit function +be63b09 address pull request comments, clean docs +c715aa9 optimize nearest_average_tanimoto, add comments to modified_tanimoto +791701c add testing, docs to modified_tanimoto +4c645e4 remove compute_distance_matrix, add tanimoto tests +d338ed4 Merge pull request #146 from FanwangM/fix_failed_refactor +2f31904 Rename `total_diversity_volume` --> `hypersphere_overlap_of_subset` +b90f19d Merge pull request #145 from FanwangM/fix_coverage_1 +b5cc6a1 Fix the coverage report by excluding all test folders +c5da650 add error checking to shannon entropy +47ee5be fix gini coeff error checking +0a4984a clean up variable naming, add test coverage +6a48b92 address pull request comments +b797a2e Update github workflows to use v3 of Actions +8510e77 Merge pull request #140 from maximilianvz/update_dissimilarity +1f8090b Merge branch 'main' into update_dissimilarity +d8ef2cc add n_iter as user specified argument +7250e73 rename predict_radius, add comments, docs +bb24152 optimize Directed_Spheres, add comments, tests +1ebf549 add comments to DirectedSphereExclusion, predict_radius +e23c83d optimize covariance function, edit code style +29cd197 refactor utils to converter module +797ac7a add divide by zero error checking +fd0cac9 Remove dist_to_similarity(), and int passed as 'metric' +5be6a69 add gravity(), co_occur() +ef65c76 add single value as input +23b6ebc add error check and blackspace +4d71c66 add more conversion methods +4c2e209 add gaussian() +4be2e53 add reciprocal(), exponential() +8501187 expand documentation +491b01a added testing coverage +7624616 improve entropy run time and fix math notation +6a479ae fix failing tests due to references to total_diversity_volume +3079206 remove redundant arguments +795f557 replace references to total_diversity_volume +868da8c rename hypersphere_overlap arguments +77354e2 remove redundant arguments +6bd272f rename gini_coefficient arguments +6255721 Move feature generation functionality to molecules module +393a857 fix total_diversity_volume, rename to hypersphere_overlap_of_subset +2d2fbba Reformat blackspace +66601a3 fix wdud implementation, add wdud tests +fac6e60 fix shannon_entropy failing tests +dd56668 fix logdet documentation +a4c767d fix logdet documentation +56a7ff3 add error message to shannon_entropy +dc4b15e document Wasserstein Distance function +50214e6 fix shannon_entropy implementation +ebaf13a fix logdet to use mol x feature matrix as input +6068f01 fix spelling, add latex documentation +af1a5b7 fix variable overwriting in entropy() +e9c21bc remove explicit_diversity_index +f3c510b Fixed conversion of strings to callables issue (#129) +b0afcaf Add reference for MaxMin algorithm +9449eeb Add comments to (test_)dissimilarity.py +7992c9c Update base.py +6ce94c9 Remove clustering module from __init__ +f292666 Remove methods/clustering.py +76c9adc Move base.py module to methods/base.py +7be2723 Merge pull request #127 from theochem/refactor_selectors +c419e71 Refactor selectors.py by splitting it into smaller modules +d84b2c8 Fix installation problem and add missing dependencies +7305ceb Merge pull request #102 from FanwangM/notebooks +9beb93f Merge branch 'main' into notebooks +498247e Merge pull request #120 from alnaba1/perf +3beba2e Add multiprocessing +a7803b6 Fix linters +6741662 Fix linters +e48a49e Merge branch 'main' into perf +dfc820d Fix build error +ca5be4f Fix bug +79502f5 Optimize selectors +c7327fc Optimize selectors +0130fb1 Improve DISE/OptiSim performance +79a46f3 Merge pull request #118 from alnaba1/optisim +b8e914c Add tester and docstring +492443c Add source +e64d32a Fix tester issue +dca6da9 Update tester +995cb69 Improve Optisim Performance +ed6516d Merge pull request #117 from theochem/badge_clean +6327388 Clean Python version badge +8483509 Merge pull request #115 from FanwangM/fix_imports +e011c6c Add __all__ in `selectors.py` +876f852 Merge pull request #114 from alnaba1/restructure +22bdebd Fix error with KNN +652f052 linters +367f0fb Remove redundancy +f2039bf Fix linters +6a54fcc Fix linters +cd7b6f3 Merge branch 'main' into restructure +20931b2 Restructure and improve sphere exclusion/kdtree +8f60145 Merge pull request #110 from alnaba1/kdtree +e8d0695 Fix linters +39ebf95 Fix linters +b971ed5 linters +998f74f Add tests for KDTree, fix bug +5b0324b Finalize KDTree +caad6eb Fix linters +d2c4786 Add documentation +add7068 tox +7eebf77 Fixing tox +a3556ec KDTree performance improvements +60975b8 Improve KDTree selection and efficiency +8370f87 Merge pull request #111 from alnaba1/radius +b2407f9 Fix radius bug +4a55e7d Fix small radius bug +711d3a8 Add warning when radius predictor fails +46351a6 Improve behavior when given radius +bc59028 KDTree based selector prototype +5efa6ac Update practical example notebook +1ae09f9 Add `__all__` for selector module +364dee8 Minor fix of Jupyter notebooks +765e681 Add synthetic data demo +ec25daf Merge pull request #97 from FanwangMeng/stratified +edc3e66 Clean up features module +f37e1ab Add tests for feature augmentation +01036e0 Add feature augmenting function +9bd1377 Merge pull request #107 from alnaba1/maxsum +7da55f4 Add MaxSum class and tester +83aacf3 Merge pull request #106 from alnaba1/bug_fix +9cd7da3 Fix dimensionality bug grid partitioning +9b53c6b Merge pull request #105 from FanwangMeng/rst_config2 +88fe7fd Update rst checking configuration wrt rstcheck new release +cdeeff9 Merge pull request #101 from fwmeng88/add_docs +23536f9 Fix duplicated display of `Methods` section in documentation +715bd6b Merge pull request #100 from fwmeng88/add_docs +e1540e7 Update readthedocs.yml +a4f5eb0 Merge pull request #99 from fwmeng88/add_docs +0eaa4e7 Add working doc skleton +963c71a Fix documentation of `features.py` +f228ecd Clean up utils.py +797d550 Update base class documentation cofiguration +9ed463b Add documentation skeleton +02727f5 Delete requirements.yaml +772f0be Merge branch 'main' of https://github.com/theochem/DiverseSelector into main +6054aaf Make documentation uppercase +028eaca Merge pull request #98 from alnaba1/selector_fix +5293879 Fix linters +4416d6e Merge branch 'main' of https://github.com/theochem/DiverseSelector into main +3f1b653 Add tolerance for radius predictor, references +5351c00 Merge pull request #96 from alnaba1/selector_fix +190ad12 Fix undefined `ExplicitBitVector` +596c938 Use numpy for arr_range +3de7d27 Fix linters +89f1d5d Fix grid partitioning, refactor, add documentation +e18651a Merge pull request #95 from fwmeng88/fix_feature +aa9df22 Fix pylint errors +cf48392 Fix pylint +0b07de4 Merge pull request #94 from fwmeng88/fix_feature +be983e9 Ignore pylint C0415: Import outside toplevel +2022fc8 Fix pyline and flake8 errors +e7b44c5 Clean up `features.py` +ce2c8f4 Fix failing error of feature calculations by fixing the order of molecules +0ee1ee7 Remove unused function `compute_features` +b31f52c Fix CSV file name +dd3d593 Merge pull request #93 from RichRick1/clean +048e11e fixed the case with less small amount of molecules in a cluster +fcb3014 Import mordred & padelpy inside the functions +9556d7c Add random_seed arg to initializer +d76e598 Merge pull request #92 from RichRick1/clean +5c0c5cd add and fixed tests +f9f27b6 Merge pull request #91 from fwmeng88/fix_feature +d09edf0 Add comments to select method of SelectionBase +a13855b Fix testing for features +19f1552 Merge pull request #90 from RichRick1/clean +e01e8f5 Merge branch 'main' into clean +db9f648 Bugfix optisim and sphereexclusion +c74b61a Fix formatting and bug in `rdkit_desc` +aac32e8 fixed func +468b3f4 fixing style +bbcc2bf Delete extra csv +71ca2b4 Merge pull request #89 from RichRick1/main +280f65c add files for testing +da99828 Merge pull request #1 from RichRick1/refactor +9495647 rebasing +e3e5010 rebasing +ebb6031 rebasing +d962b46 fixing rebase +9bc0143 Remove redundant else statements to simplify code +be81e41 Remove n_mols and arr_dist attributes +20ac58b Remove unused imports +95655ea Update README.md +61f9f79 fixing rebase +add1fbb Fix testing +6d58404 Remove private function and move contents to main function +a62d249 Minor updates to features.py +a9d7cc8 Refactor feature module +e9d3e1a Rename feature.py --> features.py +fc8a442 add untracked file +322e160 fixed tests +33480a7 renamed test file +1f62c00 Merge pull request #87 from FarnazH/minor_cleanup +92e6cb0 compute distance with function +143cd66 Remove redundant else statements to simplify code +fad5a33 Remove n_mols and arr_dist attributes +41e89f2 Remove unused imports +bf7c55e Update README.md +61d49d2 Format all modules with black +7b72d0c deleted useless files +bceb09d Merge pull request #82 from fwmeng88/refactor_features +23ebc36 Merge branch 'main' into refactor_features +7faddde reneame uppercase +05032d3 Merge pull request #85 from RichRick1/refactor +e47aac2 add ability to add random seed and init compound +c86050b Fix testing +813bdbc fixed test for MinMax selector +bfe9cba Delete useless files +98dd72c delete useless test +5f37e7e deleted the compute_diversity methods +512557d Remove private function and move contents to main function +bb70cc0 rewrite the test +fe4f723 change string +96612e6 change the default for MaxMin +b9f7576 Fix import orders +c204b62 Fix imports and __all__ listing +6f69993 Clean up imports +8f3da4d Split `metric.py` into two modules +bd22914 Minor updates to features.py +c177e5d added Grig Partitioning +34d7ac9 Merge pull request #83 from RichRick1/refactor +5d2af51 fix test +a3811c6 write the explaining for MinMax +f8dcc76 rewrite api +15bff97 Merge pull request #84 from fwmeng88/div_calc +b89bdfd Fix import orders +62276d6 Fix imports and __all__ listing +2c796d9 rewrite function usage +c7a361e Clean up imports +889d50a Split `metric.py` into two modules +bd46731 Merge branch 'main' into refactor +69d71be rewrite the abstract class +aa5530b Clean up +eb03802 Refactor calculations of diversity and distance matrix +1eabb9c Add wrapper to compute diversity +8c4fa68 fixing doc +9931729 fixing issues +a3698a8 fixing doc +d975126 fixing documentation +2c973d8 fixing documentation +44c77f7 fixing documentation +bab125e fixing documentation +bdc60a4 fixing the requirement +58f56be fixed the requirement +21abb23 add gini coefficient for diversity calculation +66c335d change requirement +894e7da add tests +295cb7f impoved finding max, min value of the matrix +f981614 fixed documentation +65f3a45 add saving and calculating diversity of the subset +ec8631b Merge pull request #79 from fwmeng88/div_calc +756e19d Clean up +7f2852d Refactor calculations of diversity and distance matrix +0ecd2a5 Add wrapper to compute diversity +90884ae Refactor feature module +d10eec4 Rename feature.py --> features.py +cc48036 Merge pull request #78 from RichRick1/base +fec1838 rewrite API +4112066 fixing doc +93c1125 fixing issues +34ecca5 fixing doc +35b1330 fixing documentation +e204fd8 fixing documentation +239d58a fixing documentation +a9f0e62 fixing documentation +728dfc2 fixing the requirement +3fd9f89 fixed the requirement +6161c3b add gini coefficient for diversity calculation +0f1149c change requirement +4fbbdd8 add tests +629c09b impoved finding max, min value of the matrix +fe13114 fixed documentation +994e027 add saving and calculating diversity of the subset +498c298 Merge pull request #76 from Ali-Tehrani/gini +d6b091a Merge pull request #77 from fwmeng88/code_conduct +818bffc Use QC-Dev code of conduct +f1fddbc Fix so feature is the probability dist in gini +72e0d57 Merge pull request #75 from Ali-Tehrani/gini +61c4519 Add test raise to gini and raise error +dd75133 Add tests for gini coefficients +50012e8 Add gini coefficient +a77b7f6 Merge pull request #66 from RichRick1/demo +a40f497 Fix import order +87625ee Break long lines +786cfb3 fixed an issue with real data +7fd2611 checked code +a21fa48 Merge pull request #64 from fwmeng88/demo +6bc1e5b Rename feature --> features +35b36c2 Merge pull request #60 from Khaleeh/Notes +0c2822f Merge pull request #61 from RichRick1/doc_new +16fbe1c fixing documentation +fb4375c fixed documentation +d196d66 Add references +e538a0a Merge pull request #58 from fwmeng88/bug_fix +8e9ed5e Use the latest version of codecode-action +428e9f0 Break long line +6ce91e5 Fix failing test by correcting the argument name +20d0a13 Add checking if `self.features` is numpy array +31ae46f Rearrange argument names to make it logically clear +830e37a Rename test file for dissimilarity based method +bfc3b17 Rename principalcomponents --> principal_components +6f42be2 Fix redefinition of `self.arr_dist` +72b0ac7 Fix bug of redefining `self.features` and `self.arr_dist` +5787d2a Clean up and fix function names +c4f52c5 Fix bug of `self.features` not defined +3528085 Fix indention +99b63b9 Add maxsplit option to avoid ambiguity +0d07750 Fix flake8 errors +7392897 Separate feature calculation module from diversity selection +4b43f36 Make feature calculations independent +2d99f77 Merge pull request #49 from fwmeng88/codecov_update +9d04578 Update configuration when computing the coverage +7a2cf58 Add versioneer.py to ingore list +1c6ecfa Add data folder to ignore list +0ba7765 Update codecov.yml +073d90e Merge pull request #32 from alnaba1/dissimilarity +956917c Fix linters, disable R1702 +69d41f2 Fix most linters +ae6336d Add gridpartitioning algorithm, documentation. +deeeefb Replace self.features_norm with self.features +a28fe84 Change select method structure, fix linters +c572133 Fix select wrapper, dissimilarity test +decc04e Add alternative to pairwise_dist for cheap dissim algorithms +d27b8a7 Add prototype bruteforce, DISE, optisim dissim methods +8a30cd3 Merge pull request #45 from Khaleeh/Add_metrics +dada2b1 Fix data type in type checking and docstring +0f73e9d Fix type checking for `euc_bit` +5ad6df6 Add a complete function for wdud method +5a7fcf3 Move `euc_bit` function to `metric.py` +d149ccb FIx pylint errors and add ignore to tox.ini +1796ba4 Fix pylint and pep8 errors +de1d6ba Fix docstring +48cf523 Fix pylint/pep8 errors and add docstring +c7c7a7e Add tests and minor fixes +096553a Add tests and minor fixes +38d9f5b Fix pylint and pep8 errors +7389d8a Fix WDUD method +b3485c2 Minor diversity Fixes +953a92d Add total diversity volume and WDUD +a7d4532 Add log detrminate fucntion and shannon entropy +be97168 Add explicit diveristy index +84b3b41 Add gini coefficint and entropy diversity methods +48a9e2d Fix pylint errors +267686f Add sklearn supported metrics +0e430fb Add tests for metrics module +7e8bd9e Add cosine and dice +6653d0a Add bit supported cosine, dice, and euclidean +8a9110c Add Modified Tanimoto +a1cc179 Add distance/similarity conversion and Tanimoto +2cde4b4 Add sklearn pairwise distance +9e80824 Merge pull request #43 from RichRick1/clustering +b46c544 Merge pull request #44 from fwmeng88/feature_testing +2cf9a4a Add __init__.py and _version.py to ignore list +570b12b Add testing for generating descriptors +c974e82 Add test for invalid test +19559bb Add dependencies installation +f81357e Fix import orders +371e955 Use `str` function to support PosixPath +c798d9d Add test for RDKit, morgan, feature loader +195de13 Fix: RemoveHs --> removeHs +a29168c Use upper case as fingerprint checking +58f7be1 Add test for SECFP6 and ECFP6 fingerprints +3a14bdc Fix import orders +b73689d Use `importlib_resources` to mange file path in `common.py` +2275f74 Disable Py3.9, Py3.10 because of `networkx` in `mordred` +8716e7b Disable Py39 because of `networkx` in `mordred` +e6783fd Remove testing on py39 +8b676b4 Fix the version of `networkx` +b1ee933 Fix the version of `RDKit` +084c361 renamed file +4a4f093 fixed docstring typo +258a1fc change documentation style +f9c2793 Fix indention of tox.ini +31571ef Fix test path in tox.ini +9511bca Fix file path of input SDF +a423457 Fix file path if testing data +f4c130e Refactor descriptor calculations with `padelpy` +c2ca82d Fix path of testing CSV files +699afe9 Add testing benchmarking data +1eef2c0 Add RDKit fragment descriptors +28c515f Add testing for RDKit descriptor +722592f fixed varibale name +f9ab009 delete return statement +fd940d2 fixing code style +fb13598 fixing code style +5411b72 fixing tox errors +971fdaf Add testing for mordred and padel descriptor calculations +57e9c44 created DiverseSelector class and tests +443f00c Add **kwargs for descriptor generation +12e6999 Add testing for mordred descriptors +1e49164 Merge pull request #42 from fwmeng88/feature_testing +adae322 Add `arr_dist` option +e322381 Fix missing `feature` in base class +518879e Merge pull request #40 from fwmeng88/py310 +f99efa3 Add badge for Python 3.10 +b7be543 Merge pull request #39 from fwmeng88/py310 +4b36ee9 Bump version for `checkout` and `setup-python` for GitHub actions +7616cef Enable Python 3.10.x for CI +428b10d Enable Python 3.10 +1e6fee6 Merge pull request #38 from fwmeng88/refactor_test +9c08d2c Fix synthetic data generation by adding the labels +b7688a1 Fix duplicated number of molecules arguments +1e4f679 Move synthetic data to `commonm.py` +c01f7a9 Remove useless sample file +e401dba Merge pull request #34 from fwmeng88/fix_testing +34ddbbb Fix missing depedencides for `code_cov` +4a4b650 Use updated version of `networkx` +5ab2aa0 Fix file path +393fe57 Merge pull request #31 from RichRick1/test +a64e6f4 Use absolute path for the package +13b4425 Fix test by correcting the indices +2872178 Follow pytest convention +cb768b0 Remove __init__.py in testing folder +0c082a6 Fix testing imports +a62adb6 wrote test for DissimilaritySelector +8fbb448 add possibility to specify the dissimilatiry matrix by user +d0fc6bf Merge pull request #33 from fwmeng88/fix_imports +025e41b Ignore unnecessary checkings +f983a77 Fix import in `__init__.py` +2aafea0 Fix docstrings +27a405a Add dependencies in tox environments +cb87c65 Fix pylint errors +ef7265a Fix flake8 errors +6fed9cc Remove __init__.py in testing folder +af45499 Use updated version of `rdkit-pypi` +c117ffc Fix `scikit-learn` package name +5938ba2 Refactor feature computation module +006e017 Add pandas depedencides +d4a786a Fix import path of utils module +8cac237 Merge pull request #27 from RichRick1/API +c638d4a fixed import +22be3ee visualizaion of MinMax algorithm +fedbca6 add MinMax implementation +c931ae1 fixed load_data and _normilize_desk methods +668222f Proposed changes to API +1883213 Merge pull request #26 from fwmeng88/api_draft +8d77c89 Add DSCS draft +93abece Merge pull request #24 from fwmeng88/api_draft +191ada9 Add outline of diversity calculation functions +43bf93f Refactor the base classes +8f65fec Merge pull request #23 from fwmeng88/api_draft +f5347d7 Update dependency list +21044ce Add `get_features()` function in `utils.py` +6b92cec Refactor `FingerprintGenerator` class +1b4d805 Fix docstrings of `DescriptorGenerator` +d5f28b9 Add docstrings for `DescriptorGenerator` class +99f1f8d Refactor descriptor generation as a class +c96ece3 Fix column names of rdkit fragment descriptor +0ca5a4a Add `descriptor_generator()` wrapper +6a5cba0 Clean up rdkit descriptors +300aefa Clean up mordred descriptors +770b6d7 Add initial feature generation functions +d1d5348 Add feature data loading module +cb0aeba Add molecular loader +8a26d2c Merge pull request #21 from RichRick1/SelectorAPI +0ac26c2 Merge pull request #22 from fwmeng88/api_draft +eb811d4 Add other modules +9c94dbd rewrite API +f145b5c Merge pull request #18 from fwmeng88/api_draft +6c812aa Add abstract base class for clustering based methods +d4cbd3a Use abstract base class for DBCS +f8b9998 Add W0107 to pyline disable list +0ab14d3 Add enhanced sampling method for clustering base +af273da Add diversity property to class +a7cab6a Add utils and DBCS +edb789d Merge pull request #16 from fwmeng88/contributing +cb1e6a5 Add contribution link in README.md +76492bc Add package information for development +3fa8abb Merge pull request #15 from fwmeng88/codecov +dee5cf0 Turn off codecov analysis on push events +6fc74ed Merge pull request #14 from fwmeng88/codecov +ac413d7 Add ignored files +c37b179 Add CI for codecov +04852ad Not use Roberto at this moment +6193d59 Merge pull request #12 from fwmeng88/skeleton +b51158c Update order of OS +e3c9e6f Rename yaml configuration file to codecov.yml +9ba7e06 Update display settings +2fee193 Merge pull request #10 from fwmeng88/skeleton +063942d Add badges +2a28e35 Merge pull request #9 from fwmeng88/skeleton +1390abd Add D401 for flake8 +0d851ef Fix docstring style for testing sample file +110549a Move CODE_OF_CONDUCT.md +8f51f38 Fix docstring style 2 +ef16a71 Fix docstring style +71959e3 Fix import order +5e34de0 Fix pylint errors/warnings +f5e5871 Add _version.py to ignore list of flake8 +049ac43 Fix pylineter errors +1df802d Fix flake8 errors +5031372 Add setup.cfg +38ace8a Remove Python 3.10 support temporarily +749893d Rename title +ee49c0b Remove architecture requirements +222ba5d Merge pull request #8 from fwmeng88/skeleton +b6229ff Add more template information +bfbda9e Add contribution guideline +da54644 Add CI related configuration +3c9ec7f Add Python 3.10 and fix pytest testing +d85b925 Add pytest-cov in requirements.txt +2e00e81 Remove Python 3.6 as it has came end of life +08be650 Add doc for sphinx +97c25c1 Add main package +e0d92e2 Add devtools +edf7041 Add .lgtm.yml for static code analysis +1fbb049 Add CODE_OF_CONDUCT.md +ad4e6ac Add versioneer.py +cc14e43 Add .codecov.yml draft +de87166 Add requirements.txt +f718b4c Add readthedocs.yml +1764d73 Add MANIFEST.in +5d6f3d5 Add roberto configuration file +e03d23d Add .coveragerc +f5e71fa Add .bandit.yml +ac52956 Add tox.ini +c3cba7c Add Sphinx documentation folders to .gitignore +86341d5 Add editor junk to .gitignore +f1d48f7 Add headers +8a7240b Add LICENSE +1c031c8 Add setup.py +97d42f1 Rename title of README.md +7a4e535 Initial commit