diff --git a/.gitignore b/.gitignore
index fc613289..ca16d0a6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -159,4 +159,5 @@ dmypy.json
# Local stuff
dummy/
tmp_model/
-plots/
\ No newline at end of file
+plots/
+demo/
diff --git a/demo/DemoClassification.ipynb b/demo/DemoClassification.ipynb
deleted file mode 100644
index dfb35697..00000000
--- a/demo/DemoClassification.ipynb
+++ /dev/null
@@ -1,714 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {
- "collapsed": false
- },
- "source": [
- "# PSyKE's demo\n",
- "\n",
- "Some imports."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "id": "6b710e7c",
- "metadata": {},
- "outputs": [],
- "source": [
- "from sklearn.model_selection import train_test_split\n",
- "from sklearn.datasets import load_iris\n",
- "import pandas as pd\n",
- "\n",
- "from sklearn.neighbors import KNeighborsClassifier\n",
- "from sklearn.metrics import accuracy_score, f1_score\n",
- "\n",
- "from psyke import Extractor, Clustering, EvaluableModel\n",
- "from psyke.extraction.hypercubic.strategy import AdaptiveStrategy\n",
- "from psyke.extraction.hypercubic import Grid, FeatureRanker\n",
- "from psyke.tuning.orchid import OrCHiD\n",
- "from psyke.utils.logic import pretty_theory\n",
- "from psyke.utils import Target"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "collapsed": false,
- "pycharm": {
- "name": "#%% md\n"
- }
- },
- "source": [
- "Import iris dataset separating features and class."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "id": "f8e46c49",
- "metadata": {},
- "outputs": [],
- "source": [
- "x, y = load_iris(return_X_y=True, as_frame=True)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "collapsed": false
- },
- "source": [
- "Rename of the features."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 6,
- "id": "38d5afb0",
- "metadata": {},
- "outputs": [],
- "source": [
- "x.columns = ['SepalLength', 'SepalWidth', 'PetalLength', 'PetalWidth']"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "collapsed": false
- },
- "source": [
- "Replace integer indices with the corresponding string class."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "id": "4f807185",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": " target\n0 setosa\n1 setosa\n2 setosa\n3 setosa\n4 setosa\n.. ...\n145 virginica\n146 virginica\n147 virginica\n148 virginica\n149 virginica\n\n[150 rows x 1 columns]",
- "text/html": "
\n\n
\n \n \n | \n target | \n
\n \n \n \n 0 | \n setosa | \n
\n \n 1 | \n setosa | \n
\n \n 2 | \n setosa | \n
\n \n 3 | \n setosa | \n
\n \n 4 | \n setosa | \n
\n \n ... | \n ... | \n
\n \n 145 | \n virginica | \n
\n \n 146 | \n virginica | \n
\n \n 147 | \n virginica | \n
\n \n 148 | \n virginica | \n
\n \n 149 | \n virginica | \n
\n \n
\n
150 rows × 1 columns
\n
"
- },
- "execution_count": 7,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "y = pd.DataFrame(y).replace({\"target\": {0: 'setosa', 1: 'versicolor', 2: 'virginica'}})\n",
- "y"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "collapsed": false
- },
- "source": [
- "The final dataset:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 8,
- "id": "7ac49b4e",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": " SepalLength SepalWidth PetalLength PetalWidth iris\n0 5.1 3.5 1.4 0.2 setosa\n1 4.9 3.0 1.4 0.2 setosa\n2 4.7 3.2 1.3 0.2 setosa\n3 4.6 3.1 1.5 0.2 setosa\n4 5.0 3.6 1.4 0.2 setosa\n.. ... ... ... ... ...\n145 6.7 3.0 5.2 2.3 virginica\n146 6.3 2.5 5.0 1.9 virginica\n147 6.5 3.0 5.2 2.0 virginica\n148 6.2 3.4 5.4 2.3 virginica\n149 5.9 3.0 5.1 1.8 virginica\n\n[150 rows x 5 columns]",
- "text/html": "\n\n
\n \n \n | \n SepalLength | \n SepalWidth | \n PetalLength | \n PetalWidth | \n iris | \n
\n \n \n \n 0 | \n 5.1 | \n 3.5 | \n 1.4 | \n 0.2 | \n setosa | \n
\n \n 1 | \n 4.9 | \n 3.0 | \n 1.4 | \n 0.2 | \n setosa | \n
\n \n 2 | \n 4.7 | \n 3.2 | \n 1.3 | \n 0.2 | \n setosa | \n
\n \n 3 | \n 4.6 | \n 3.1 | \n 1.5 | \n 0.2 | \n setosa | \n
\n \n 4 | \n 5.0 | \n 3.6 | \n 1.4 | \n 0.2 | \n setosa | \n
\n \n ... | \n ... | \n ... | \n ... | \n ... | \n ... | \n
\n \n 145 | \n 6.7 | \n 3.0 | \n 5.2 | \n 2.3 | \n virginica | \n
\n \n 146 | \n 6.3 | \n 2.5 | \n 5.0 | \n 1.9 | \n virginica | \n
\n \n 147 | \n 6.5 | \n 3.0 | \n 5.2 | \n 2.0 | \n virginica | \n
\n \n 148 | \n 6.2 | \n 3.4 | \n 5.4 | \n 2.3 | \n virginica | \n
\n \n 149 | \n 5.9 | \n 3.0 | \n 5.1 | \n 1.8 | \n virginica | \n
\n \n
\n
150 rows × 5 columns
\n
"
- },
- "execution_count": 8,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "dataset = x.join(y)\n",
- "dataset.columns = [*dataset.columns[:-1], 'iris']\n",
- "dataset"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "collapsed": false
- },
- "source": [
- "Split between train and test set in a reproducible way."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 9,
- "id": "03fc5e2c",
- "metadata": {},
- "outputs": [],
- "source": [
- "train, test = train_test_split(dataset, test_size=0.25, random_state=1)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "collapsed": false
- },
- "source": [
- "We use as predictor a KNN and we train it."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 10,
- "id": "aa8a3128",
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Accuracy: 1.00\n",
- "F1: 1.00\n"
- ]
- }
- ],
- "source": [
- "#predictor = MLPClassifier(alpha=1, max_iter=1000)\n",
- "predictor = KNeighborsClassifier(n_neighbors=5)\n",
- "#predictor = DecisionTreeClassifier()\n",
- "predictor.fit(train.iloc[:, :-1], train.iloc[:, -1])\n",
- "print(f'Accuracy: {accuracy_score(predictor.predict(test.iloc[:, :-1]), test.iloc[:, -1]):.2f}')\n",
- "print(f'F1: {f1_score(predictor.predict(test.iloc[:, :-1]), test.iloc[:, -1], average=\"weighted\"):.2f}')"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 11,
- "outputs": [],
- "source": [
- "def print_scores(scores):\n",
- " print(f'Classification accuracy = {scores[EvaluableModel.ClassificationScore.ACCURACY][0]:.2f} (data), '\n",
- " f'{scores[EvaluableModel.ClassificationScore.ACCURACY][1]:.2f} (BB)\\n'\n",
- " f'F1 = {scores[EvaluableModel.ClassificationScore.F1][0]:.2f} (data), '\n",
- " f'{scores[EvaluableModel.ClassificationScore.F1][1]:.2f} (BB)')\n",
- "\n",
- "def get_scores(extractor, test, predictor):\n",
- " return extractor.score(test, predictor, True, True, EvaluableModel.Task.CLASSIFICATION,\n",
- " [EvaluableModel.ClassificationScore.ACCURACY, EvaluableModel.ClassificationScore.F1])"
- ],
- "metadata": {
- "collapsed": false,
- "pycharm": {
- "name": "#%%\n"
- }
- }
- },
- {
- "cell_type": "code",
- "execution_count": 12,
- "metadata": {
- "collapsed": false,
- "pycharm": {
- "name": "#%%\n"
- }
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "ITER performance (5 rules with 97.37% coverage):\n",
- "Classification accuracy = 0.97 (data), 0.97 (BB)\n",
- "F1 = 0.97 (data), 0.97 (BB)\n",
- "\n",
- "ITER extracted rules:\n",
- "\n",
- "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, setosa) :-\n",
- " SepalLength in [4.29, 7.70], SepalWidth in [1.99, 4.40], PetalLength in [0.99, 3.17], PetalWidth in [0.09, 2.10].\n",
- "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, versicolor) :-\n",
- " SepalLength in [4.29, 7.70], SepalWidth in [1.99, 4.40], PetalLength in [3.17, 5.82], PetalWidth in [0.09, 1.74].\n",
- "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, versicolor) :-\n",
- " SepalLength in [4.29, 7.70], SepalWidth in [1.99, 4.40], PetalLength in [0.99, 4.05], PetalWidth in [2.10, 2.50].\n",
- "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, virginica) :-\n",
- " SepalLength in [4.29, 7.70], SepalWidth in [1.99, 4.40], PetalLength in [5.82, 6.90], PetalWidth in [0.09, 2.50].\n",
- "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, virginica) :-\n",
- " SepalLength in [4.29, 7.70], SepalWidth in [1.99, 4.40], PetalLength in [4.05, 5.82], PetalWidth in [1.74, 2.50].\n"
- ]
- }
- ],
- "source": [
- "it = Extractor.iter(predictor, min_update=0.15, min_examples=150, threshold=0.1, max_iterations=600, n_points=1)\n",
- "theory_from_iter = it.extract(train)\n",
- "scores, completeness = get_scores(it, test, predictor)\n",
- "print(f'ITER performance ({it.n_rules} rules with {completeness * 100:.2f}% coverage):')\n",
- "print_scores(scores)\n",
- "print('\\nITER extracted rules:\\n\\n' + pretty_theory(theory_from_iter))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "collapsed": false
- },
- "source": [
- "We create a GridEx extractor to extract prolog rules from the same KNN."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 13,
- "metadata": {
- "collapsed": false,
- "pycharm": {
- "name": "#%%\n"
- }
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "GridEx performance (3 rules with 94.74% coverage):\n",
- "Classification accuracy = 0.92 (data), 0.92 (BB)\n",
- "F1 = 0.92 (data), 0.92 (BB)\n",
- "\n",
- "GridEx extracted rules:\n",
- "\n",
- "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, setosa) :-\n",
- " PetalLength in [0.99, 2.47].\n",
- "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, versicolor) :-\n",
- " PetalLength in [3.21, 4.68].\n",
- "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, virginica) :-\n",
- " PetalLength in [4.68, 6.90].\n"
- ]
- }
- ],
- "source": [
- "ranked = FeatureRanker(x.columns).fit(predictor, x).rankings()\n",
- "gridEx = Extractor.gridex(predictor, Grid(1, AdaptiveStrategy(ranked, [(0.85, 8)])), threshold=.1, min_examples=1)\n",
- "theory_from_gridEx = gridEx.extract(train)\n",
- "scores, completeness = get_scores(gridEx, test, predictor)\n",
- "print(f'GridEx performance ({gridEx.n_rules} rules with {completeness * 100:.2f}% coverage):')\n",
- "print_scores(scores)\n",
- "print('\\nGridEx extracted rules:\\n\\n' + pretty_theory(theory_from_gridEx))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "collapsed": false
- },
- "source": [
- "We create an extractor that uses the CART algorithm and we extract prolog rules from our trained KNN."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 14,
- "metadata": {
- "collapsed": false,
- "pycharm": {
- "name": "#%%\n"
- }
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "CART performance (3 rules with 100.00% coverage):\n",
- "Classification accuracy = 0.97 (data), 0.97 (BB)\n",
- "F1 = 0.97 (data), 0.97 (BB)\n",
- "\n",
- "CART extracted rules:\n",
- "\n",
- "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, setosa) :-\n",
- " PetalLength =< 2.6.\n",
- "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, versicolor) :-\n",
- " PetalLength =< 4.75.\n",
- "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, virginica).\n"
- ]
- }
- ],
- "source": [
- "cart = Extractor.cart(predictor, simplify=True)\n",
- "theory_from_cart = cart.extract(train)\n",
- "scores, completeness = get_scores(cart, test, predictor)\n",
- "print(f'CART performance ({cart.n_rules} rules with {completeness * 100:.2f}% coverage):')\n",
- "print_scores(scores)\n",
- "print('\\nCART extracted rules:\\n\\n' + pretty_theory(theory_from_cart))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "collapsed": false,
- "pycharm": {
- "name": "#%% md\n"
- }
- },
- "source": [
- "We use the CReEPy clustering-based extractor to perform the extraction."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 15,
- "outputs": [],
- "source": [
- "def print_clustering_scores(scores):\n",
- " print(f'ARI = {scores[EvaluableModel.ClusteringScore.ARI][0]:.2f}\\n'\n",
- " f'AMI = {scores[EvaluableModel.ClusteringScore.AMI][0]:.2f}\\n'\n",
- " f'V-measure = {scores[EvaluableModel.ClusteringScore.V][0]:.2f}\\n'\n",
- " f'FMI = {scores[EvaluableModel.ClusteringScore.FMI][0]:.2f}')\n",
- "\n",
- "def get_clustering_scores(clustering, test):\n",
- " return clustering.score(test, None, False, True, EvaluableModel.Task.CLASSIFICATION,\n",
- " [EvaluableModel.ClusteringScore.ARI, EvaluableModel.ClusteringScore.AMI,\n",
- " EvaluableModel.ClusteringScore.V, EvaluableModel.ClusteringScore.FMI])\n",
- "\n",
- "def print_scores_short(scores):\n",
- " print(f'Classification accuracy = {scores[EvaluableModel.ClassificationScore.ACCURACY][0]:.2f}')\n",
- "\n",
- "def get_scores_short(extractor, test):\n",
- " return extractor.score(test, None, False, True, EvaluableModel.Task.CLASSIFICATION,\n",
- " [EvaluableModel.ClassificationScore.ACCURACY, EvaluableModel.ClassificationScore.F1])"
- ],
- "metadata": {
- "collapsed": false,
- "pycharm": {
- "name": "#%%\n"
- }
- }
- },
- {
- "cell_type": "code",
- "execution_count": 16,
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Algorithm.ExACT. Depth: 1. Threshold = 1.00. Predictive loss = 0.30, 2 rules\n",
- "Algorithm.ExACT. Depth: 1. Threshold = 0.02. Predictive loss = 0.30, 2 rules\n",
- "Algorithm.ExACT. Depth: 1. Threshold = 0.06. Predictive loss = 0.30, 2 rules\n",
- "Algorithm.ExACT. Depth: 1. Threshold = 0.11. Predictive loss = 0.30, 2 rules\n",
- "Algorithm.ExACT. Depth: 1. Threshold = 0.15. Predictive loss = 0.30, 2 rules\n",
- "Algorithm.ExACT. Depth: 1. Threshold = 0.20. Predictive loss = 0.30, 2 rules\n",
- "\n",
- "Algorithm.ExACT. Depth: 2. Threshold = 1.00. Predictive loss = 0.30, 2 rules\n",
- "Algorithm.ExACT. Depth: 2. Threshold = 0.02. Predictive loss = 0.27, 3 rules\n",
- "Algorithm.ExACT. Depth: 2. Threshold = 0.06. Predictive loss = 0.27, 3 rules\n",
- "Algorithm.ExACT. Depth: 2. Threshold = 0.11. Predictive loss = 0.27, 3 rules\n",
- "Algorithm.ExACT. Depth: 2. Threshold = 0.15. Predictive loss = 0.27, 3 rules\n",
- "Algorithm.ExACT. Depth: 2. Threshold = 0.20. Predictive loss = 0.27, 3 rules\n",
- "\n",
- "****************************************\n",
- "* Best Algorithm.ExACT\n",
- "****************************************\n",
- "* Predictive loss = 0.27, 3 rules\n",
- "* Threshold = 0.02\n",
- "* Depth = 2\n",
- "****************************************\n",
- "\n",
- "****************************************\n",
- "* Best Predictive loss\n",
- "****************************************\n",
- "* Predictive loss = 0.27, 3 rules\n",
- "* Threshold = 0.02\n",
- "* Depth = 2\n",
- "****************************************\n",
- "\n",
- "****************************************\n",
- "* Best N rules\n",
- "****************************************\n",
- "* Predictive loss = 0.30, 2 rules\n",
- "* Threshold = 1.00\n",
- "* Depth = 2\n",
- "****************************************\n",
- "\n"
- ]
- }
- ],
- "source": [
- "orchid = OrCHiD(dataframe=train, algorithm=OrCHiD.Algorithm.ExACT, output=Target.CLASSIFICATION,\n",
- " max_mae_increase=1.2, min_rule_decrease=0.9, readability_tradeoff=0.1, patience=5, max_depth=3)\n",
- "orchid.search()\n",
- "(_, _, depth, threshold) = orchid.get_best()[0]"
- ],
- "metadata": {
- "collapsed": false,
- "pycharm": {
- "name": "#%%\n"
- }
- }
- },
- {
- "cell_type": "code",
- "execution_count": 17,
- "metadata": {
- "collapsed": false,
- "pycharm": {
- "name": "#%%\n"
- }
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "ExACT performance (3 clusters with 97.37% coverage):\n",
- "ARI = 0.53\n",
- "AMI = 0.62\n",
- "V-measure = 0.64\n",
- "FMI = 0.69\n",
- "Classification accuracy = 0.78\n",
- "\n",
- "Output is virginica if:\n",
- " SepalLength is in [4.90, 7.70]\n",
- " SepalWidth is in [2.20, 3.80]\n",
- " PetalLength is in [4.50, 6.90]\n",
- " PetalWidth is in [1.40, 2.50]\n",
- "Output is versicolor if:\n",
- " SepalLength is in [4.90, 7.70]\n",
- " SepalWidth is in [2.00, 3.80]\n",
- " PetalLength is in [3.30, 6.90]\n",
- " PetalWidth is in [1.00, 2.50]\n",
- "Output is setosa if:\n",
- " SepalLength is in [4.30, 7.70]\n",
- " SepalWidth is in [2.00, 4.40]\n",
- " PetalLength is in [1.00, 6.90]\n",
- " PetalWidth is in [0.10, 2.50]\n"
- ]
- }
- ],
- "source": [
- "exact = Clustering.exact(depth=depth, error_threshold=threshold, output=Target.CLASSIFICATION)\n",
- "exact.fit(train)\n",
- "scores, completeness = get_clustering_scores(exact, test)\n",
- "print(f'ExACT performance ({exact.n_rules} clusters with {completeness * 100:.2f}% coverage):')\n",
- "print_clustering_scores(scores)\n",
- "scores, _ = get_scores_short(exact, test)\n",
- "print_scores_short(scores)\n",
- "print()\n",
- "exact.explain()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 18,
- "metadata": {
- "collapsed": false,
- "pycharm": {
- "name": "#%%\n"
- }
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "CReEPy performance (3 rules with 100.00% coverage):\n",
- "Classification accuracy = 0.95 (data), 0.95 (BB)\n",
- "F1 = 0.95 (data), 0.95 (BB)\n",
- "\n",
- "CReEPy extracted rules:\n",
- "\n",
- "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, virginica) :-\n",
- " PetalLength in [4.79, 6.90].\n",
- "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, versicolor) :-\n",
- " PetalLength in [3.29, 6.90].\n",
- "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, setosa).\n"
- ]
- }
- ],
- "source": [
- "creepy = Extractor.creepy(predictor, depth=2, error_threshold=0.1, output=Target.CLASSIFICATION,\n",
- " ranks=ranked, ignore_threshold=.99, clustering=Clustering.exact)\n",
- "theory_from_creepy = creepy.extract(train)\n",
- "scores, completeness = get_scores(creepy, test, predictor)\n",
- "print(f'CReEPy performance ({creepy.n_rules} rules with {completeness * 100:.2f}% coverage):')\n",
- "print_scores(scores)\n",
- "print('\\nCReEPy extracted rules:\\n\\n' + pretty_theory(theory_from_creepy))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 19,
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Algorithm.CREAM. Depth: 1. Threshold = 1.00. Predictive loss = 0.30, 2 rules\n",
- "Algorithm.CREAM. Depth: 1. Threshold = 0.02. Predictive loss = 0.30, 2 rules\n",
- "Algorithm.CREAM. Depth: 1. Threshold = 0.06. Predictive loss = 0.30, 2 rules\n",
- "Algorithm.CREAM. Depth: 1. Threshold = 0.11. Predictive loss = 0.30, 2 rules\n",
- "Algorithm.CREAM. Depth: 1. Threshold = 0.15. Predictive loss = 0.30, 2 rules\n",
- "Algorithm.CREAM. Depth: 1. Threshold = 0.20. Predictive loss = 0.30, 2 rules\n",
- "\n",
- "Algorithm.CREAM. Depth: 2. Threshold = 1.00. Predictive loss = 0.30, 2 rules\n",
- "Algorithm.CREAM. Depth: 2. Threshold = 0.02. Predictive loss = 0.07, 3 rules\n",
- "Algorithm.CREAM. Depth: 2. Threshold = 0.06. Predictive loss = 0.07, 3 rules\n",
- "Algorithm.CREAM. Depth: 2. Threshold = 0.11. Predictive loss = 0.07, 3 rules\n",
- "Algorithm.CREAM. Depth: 2. Threshold = 0.15. Predictive loss = 0.07, 3 rules\n",
- "Algorithm.CREAM. Depth: 2. Threshold = 0.20. Predictive loss = 0.07, 3 rules\n",
- "\n",
- "****************************************\n",
- "* Best Algorithm.CREAM\n",
- "****************************************\n",
- "* Predictive loss = 0.07, 3 rules\n",
- "* Threshold = 0.02\n",
- "* Depth = 2\n",
- "****************************************\n",
- "\n",
- "****************************************\n",
- "* Best Predictive loss\n",
- "****************************************\n",
- "* Predictive loss = 0.07, 3 rules\n",
- "* Threshold = 0.02\n",
- "* Depth = 2\n",
- "****************************************\n",
- "\n",
- "****************************************\n",
- "* Best N rules\n",
- "****************************************\n",
- "* Predictive loss = 0.30, 2 rules\n",
- "* Threshold = 1.00\n",
- "* Depth = 2\n",
- "****************************************\n",
- "\n"
- ]
- }
- ],
- "source": [
- "orchid = OrCHiD(dataframe=train, algorithm=OrCHiD.Algorithm.CREAM, output=Target.CLASSIFICATION,\n",
- " max_mae_increase=1.2, min_rule_decrease=0.9, readability_tradeoff=0.1, patience=5, max_depth=3)\n",
- "orchid.search()\n",
- "(_, _, depth, threshold) = orchid.get_best()[0]"
- ],
- "metadata": {
- "collapsed": false,
- "pycharm": {
- "name": "#%%\n"
- }
- }
- },
- {
- "cell_type": "code",
- "execution_count": 20,
- "metadata": {
- "collapsed": false,
- "pycharm": {
- "name": "#%%\n"
- }
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "CREAM performance (3 clusters with 97.37% coverage):\n",
- "ARI = 0.85\n",
- "AMI = 0.82\n",
- "V-measure = 0.83\n",
- "FMI = 0.90\n",
- "Classification accuracy = 0.95\n",
- "\n",
- "Output is setosa if:\n",
- " SepalLength is in [4.30, 5.70]\n",
- " SepalWidth is in [2.30, 4.40]\n",
- " PetalLength is in [1.00, 1.90]\n",
- " PetalWidth is in [0.10, 0.60]\n",
- "Output is versicolor if:\n",
- " SepalLength is in [4.90, 7.00]\n",
- " SepalWidth is in [2.00, 3.40]\n",
- " PetalLength is in [3.30, 5.10]\n",
- " PetalWidth is in [1.00, 1.80]\n",
- "Output is virginica if:\n",
- " SepalLength is in [4.30, 7.70]\n",
- " SepalWidth is in [2.00, 4.40]\n",
- " PetalLength is in [1.00, 6.90]\n",
- " PetalWidth is in [0.10, 2.50]\n"
- ]
- }
- ],
- "source": [
- "cream = Clustering.cream(depth=depth, error_threshold=threshold, output=Target.CLASSIFICATION)\n",
- "cream.fit(train)\n",
- "scores, completeness = get_clustering_scores(cream, test)\n",
- "print(f'CREAM performance ({cream.n_rules} clusters with {completeness * 100:.2f}% coverage):')\n",
- "print_clustering_scores(scores)\n",
- "scores, _ = get_scores_short(cream, test)\n",
- "print_scores_short(scores)\n",
- "print()\n",
- "cream.explain()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 21,
- "metadata": {
- "collapsed": false,
- "pycharm": {
- "name": "#%%\n"
- }
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "CReEPy performance (3 rules with 100.00% coverage):\n",
- "Classification accuracy = 0.95 (data), 0.95 (BB)\n",
- "F1 = 0.95 (data), 0.95 (BB)\n",
- "\n",
- "CReEPy extracted rules:\n",
- "\n",
- "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, setosa) :-\n",
- " PetalLength in [0.99, 1.90].\n",
- "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, versicolor) :-\n",
- " PetalLength in [3.29, 5.00].\n",
- "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, virginica).\n"
- ]
- }
- ],
- "source": [
- "creepy = Extractor.creepy(predictor, depth=2, error_threshold=0.1, output=Target.CLASSIFICATION,\n",
- " ranks=ranked, ignore_threshold=.99, clustering=Clustering.cream)\n",
- "theory_from_creepy = creepy.extract(train)\n",
- "scores, completeness = get_scores(creepy, test, predictor)\n",
- "print(f'CReEPy performance ({creepy.n_rules} rules with {completeness * 100:.2f}% coverage):')\n",
- "print_scores(scores)\n",
- "print('\\nCReEPy extracted rules:\\n\\n' + pretty_theory(theory_from_creepy))"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3 (ipykernel)",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.9.7"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
-}
\ No newline at end of file
diff --git a/demo/DemoClassificationDisc.ipynb b/demo/DemoClassificationDisc.ipynb
deleted file mode 100644
index c240351b..00000000
--- a/demo/DemoClassificationDisc.ipynb
+++ /dev/null
@@ -1,452 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "source": [
- "# PSyKE's demo\n",
- "\n",
- "Some imports."
- ],
- "metadata": {
- "collapsed": false
- }
- },
- {
- "cell_type": "code",
- "execution_count": 10,
- "id": "6b710e7c",
- "metadata": {},
- "outputs": [],
- "source": [
- "from psyke.utils.dataframe import get_discrete_features_supervised, get_discrete_dataset\n",
- "from sklearn.model_selection import train_test_split\n",
- "from sklearn.datasets import load_iris\n",
- "import pandas as pd\n",
- "\n",
- "from sklearn.neighbors import KNeighborsClassifier\n",
- "from sklearn.tree import DecisionTreeClassifier\n",
- "from psyke.extraction.cart.predictor import CartPredictor\n",
- "\n",
- "from psyke import Extractor, EvaluableModel\n",
- "from psyke.utils.logic import pretty_theory"
- ]
- },
- {
- "cell_type": "markdown",
- "source": [
- "Import iris dataset separating features and class."
- ],
- "metadata": {
- "collapsed": false,
- "pycharm": {
- "name": "#%% md\n"
- }
- }
- },
- {
- "cell_type": "code",
- "execution_count": 11,
- "id": "f8e46c49",
- "metadata": {},
- "outputs": [],
- "source": [
- "x, y = load_iris(return_X_y=True, as_frame=True)"
- ]
- },
- {
- "cell_type": "markdown",
- "source": [
- "Rename of the features."
- ],
- "metadata": {
- "collapsed": false
- }
- },
- {
- "cell_type": "code",
- "execution_count": 12,
- "id": "38d5afb0",
- "metadata": {},
- "outputs": [],
- "source": [
- "x.columns = ['SepalLength', 'SepalWidth', 'PetalLength', 'PetalWidth']"
- ]
- },
- {
- "cell_type": "markdown",
- "source": [
- "The original features' dataset is discretized using the equal frequency method. Each feature is mapped in a 3 (can be an arbitrary integer) new one-hot encoded sub-features representing 3 real intervals. So from the original 4 features we have a new 12 features dataset. S, M and L stand for small, medium and large."
- ],
- "metadata": {
- "collapsed": false
- }
- },
- {
- "cell_type": "code",
- "execution_count": 13,
- "id": "423ff1b4",
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "SepalLength = {'SepalLength_0' if SepalLength ∈ ]-∞, 5.39], 'SepalLength_1' if SepalLength ∈ [5.39, 6.26[, 'SepalLength_2' if SepalLength ∈ ]6.26, ∞[}\n",
- "\n",
- "SepalWidth = {'SepalWidth_0' if SepalWidth ∈ ]-∞, 2.87], 'SepalWidth_1' if SepalWidth ∈ [2.87, 3.20[, 'SepalWidth_2' if SepalWidth ∈ ]3.20, ∞[}\n",
- "\n",
- "PetalLength = {'PetalLength_0' if PetalLength ∈ ]-∞, 2.27], 'PetalLength_1' if PetalLength ∈ [2.27, 4.87[, 'PetalLength_2' if PetalLength ∈ ]4.87, ∞[}\n",
- "\n",
- "PetalWidth = {'PetalWidth_0' if PetalWidth ∈ ]-∞, 0.65], 'PetalWidth_1' if PetalWidth ∈ [0.65, 1.64[, 'PetalWidth_2' if PetalWidth ∈ ]1.64, ∞[}\n",
- "\n"
- ]
- }
- ],
- "source": [
- "iris_features = get_discrete_features_supervised(x.join(y))\n",
- "\n",
- "for descrete_feature in iris_features:\n",
- " print(str(descrete_feature), end='\\n\\n')"
- ]
- },
- {
- "cell_type": "markdown",
- "source": [
- "Reassign features' data to the discretized one."
- ],
- "metadata": {
- "collapsed": false
- }
- },
- {
- "cell_type": "code",
- "execution_count": 14,
- "id": "ffc1852e",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": " PetalLength_0 PetalLength_1 PetalLength_2 PetalWidth_0 PetalWidth_1 \\\n0 1 0 0 1 0 \n1 1 0 0 1 0 \n2 1 0 0 1 0 \n3 1 0 0 1 0 \n4 1 0 0 1 0 \n.. ... ... ... ... ... \n145 0 0 1 0 0 \n146 0 0 1 0 0 \n147 0 0 1 0 0 \n148 0 0 1 0 0 \n149 0 0 1 0 0 \n\n PetalWidth_2 SepalLength_0 SepalLength_1 SepalLength_2 SepalWidth_0 \\\n0 0 1 0 0 0 \n1 0 1 0 0 0 \n2 0 1 0 0 0 \n3 0 1 0 0 0 \n4 0 1 0 0 0 \n.. ... ... ... ... ... \n145 1 0 0 1 0 \n146 1 0 0 1 1 \n147 1 0 0 1 0 \n148 1 0 1 0 0 \n149 1 0 1 0 0 \n\n SepalWidth_1 SepalWidth_2 \n0 0 1 \n1 1 0 \n2 1 0 \n3 1 0 \n4 0 1 \n.. ... ... \n145 1 0 \n146 0 0 \n147 1 0 \n148 0 1 \n149 1 0 \n\n[150 rows x 12 columns]",
- "text/html": "\n\n
\n \n \n | \n PetalLength_0 | \n PetalLength_1 | \n PetalLength_2 | \n PetalWidth_0 | \n PetalWidth_1 | \n PetalWidth_2 | \n SepalLength_0 | \n SepalLength_1 | \n SepalLength_2 | \n SepalWidth_0 | \n SepalWidth_1 | \n SepalWidth_2 | \n
\n \n \n \n 0 | \n 1 | \n 0 | \n 0 | \n 1 | \n 0 | \n 0 | \n 1 | \n 0 | \n 0 | \n 0 | \n 0 | \n 1 | \n
\n \n 1 | \n 1 | \n 0 | \n 0 | \n 1 | \n 0 | \n 0 | \n 1 | \n 0 | \n 0 | \n 0 | \n 1 | \n 0 | \n
\n \n 2 | \n 1 | \n 0 | \n 0 | \n 1 | \n 0 | \n 0 | \n 1 | \n 0 | \n 0 | \n 0 | \n 1 | \n 0 | \n
\n \n 3 | \n 1 | \n 0 | \n 0 | \n 1 | \n 0 | \n 0 | \n 1 | \n 0 | \n 0 | \n 0 | \n 1 | \n 0 | \n
\n \n 4 | \n 1 | \n 0 | \n 0 | \n 1 | \n 0 | \n 0 | \n 1 | \n 0 | \n 0 | \n 0 | \n 0 | \n 1 | \n
\n \n ... | \n ... | \n ... | \n ... | \n ... | \n ... | \n ... | \n ... | \n ... | \n ... | \n ... | \n ... | \n ... | \n
\n \n 145 | \n 0 | \n 0 | \n 1 | \n 0 | \n 0 | \n 1 | \n 0 | \n 0 | \n 1 | \n 0 | \n 1 | \n 0 | \n
\n \n 146 | \n 0 | \n 0 | \n 1 | \n 0 | \n 0 | \n 1 | \n 0 | \n 0 | \n 1 | \n 1 | \n 0 | \n 0 | \n
\n \n 147 | \n 0 | \n 0 | \n 1 | \n 0 | \n 0 | \n 1 | \n 0 | \n 0 | \n 1 | \n 0 | \n 1 | \n 0 | \n
\n \n 148 | \n 0 | \n 0 | \n 1 | \n 0 | \n 0 | \n 1 | \n 0 | \n 1 | \n 0 | \n 0 | \n 0 | \n 1 | \n
\n \n 149 | \n 0 | \n 0 | \n 1 | \n 0 | \n 0 | \n 1 | \n 0 | \n 1 | \n 0 | \n 0 | \n 1 | \n 0 | \n
\n \n
\n
150 rows × 12 columns
\n
"
- },
- "execution_count": 14,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "x = get_discrete_dataset(x, iris_features)\n",
- "x"
- ]
- },
- {
- "cell_type": "markdown",
- "source": [
- "Replace integer indices with the corresponding string class."
- ],
- "metadata": {
- "collapsed": false
- }
- },
- {
- "cell_type": "code",
- "execution_count": 15,
- "id": "4f807185",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": " target\n0 setosa\n1 setosa\n2 setosa\n3 setosa\n4 setosa\n.. ...\n145 virginica\n146 virginica\n147 virginica\n148 virginica\n149 virginica\n\n[150 rows x 1 columns]",
- "text/html": "\n\n
\n \n \n | \n target | \n
\n \n \n \n 0 | \n setosa | \n
\n \n 1 | \n setosa | \n
\n \n 2 | \n setosa | \n
\n \n 3 | \n setosa | \n
\n \n 4 | \n setosa | \n
\n \n ... | \n ... | \n
\n \n 145 | \n virginica | \n
\n \n 146 | \n virginica | \n
\n \n 147 | \n virginica | \n
\n \n 148 | \n virginica | \n
\n \n 149 | \n virginica | \n
\n \n
\n
150 rows × 1 columns
\n
"
- },
- "execution_count": 15,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "y = pd.DataFrame(y).replace({\"target\": {0: 'setosa', 1: 'versicolor', 2: 'virginica'}})\n",
- "y"
- ]
- },
- {
- "cell_type": "markdown",
- "source": [
- "The final dataset:"
- ],
- "metadata": {
- "collapsed": false
- }
- },
- {
- "cell_type": "code",
- "execution_count": 16,
- "id": "7ac49b4e",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": " PetalLength_0 PetalLength_1 PetalLength_2 PetalWidth_0 PetalWidth_1 \\\n0 1 0 0 1 0 \n1 1 0 0 1 0 \n2 1 0 0 1 0 \n3 1 0 0 1 0 \n4 1 0 0 1 0 \n.. ... ... ... ... ... \n145 0 0 1 0 0 \n146 0 0 1 0 0 \n147 0 0 1 0 0 \n148 0 0 1 0 0 \n149 0 0 1 0 0 \n\n PetalWidth_2 SepalLength_0 SepalLength_1 SepalLength_2 SepalWidth_0 \\\n0 0 1 0 0 0 \n1 0 1 0 0 0 \n2 0 1 0 0 0 \n3 0 1 0 0 0 \n4 0 1 0 0 0 \n.. ... ... ... ... ... \n145 1 0 0 1 0 \n146 1 0 0 1 1 \n147 1 0 0 1 0 \n148 1 0 1 0 0 \n149 1 0 1 0 0 \n\n SepalWidth_1 SepalWidth_2 iris \n0 0 1 setosa \n1 1 0 setosa \n2 1 0 setosa \n3 1 0 setosa \n4 0 1 setosa \n.. ... ... ... \n145 1 0 virginica \n146 0 0 virginica \n147 1 0 virginica \n148 0 1 virginica \n149 1 0 virginica \n\n[150 rows x 13 columns]",
- "text/html": "\n\n
\n \n \n | \n PetalLength_0 | \n PetalLength_1 | \n PetalLength_2 | \n PetalWidth_0 | \n PetalWidth_1 | \n PetalWidth_2 | \n SepalLength_0 | \n SepalLength_1 | \n SepalLength_2 | \n SepalWidth_0 | \n SepalWidth_1 | \n SepalWidth_2 | \n iris | \n
\n \n \n \n 0 | \n 1 | \n 0 | \n 0 | \n 1 | \n 0 | \n 0 | \n 1 | \n 0 | \n 0 | \n 0 | \n 0 | \n 1 | \n setosa | \n
\n \n 1 | \n 1 | \n 0 | \n 0 | \n 1 | \n 0 | \n 0 | \n 1 | \n 0 | \n 0 | \n 0 | \n 1 | \n 0 | \n setosa | \n
\n \n 2 | \n 1 | \n 0 | \n 0 | \n 1 | \n 0 | \n 0 | \n 1 | \n 0 | \n 0 | \n 0 | \n 1 | \n 0 | \n setosa | \n
\n \n 3 | \n 1 | \n 0 | \n 0 | \n 1 | \n 0 | \n 0 | \n 1 | \n 0 | \n 0 | \n 0 | \n 1 | \n 0 | \n setosa | \n
\n \n 4 | \n 1 | \n 0 | \n 0 | \n 1 | \n 0 | \n 0 | \n 1 | \n 0 | \n 0 | \n 0 | \n 0 | \n 1 | \n setosa | \n
\n \n ... | \n ... | \n ... | \n ... | \n ... | \n ... | \n ... | \n ... | \n ... | \n ... | \n ... | \n ... | \n ... | \n ... | \n
\n \n 145 | \n 0 | \n 0 | \n 1 | \n 0 | \n 0 | \n 1 | \n 0 | \n 0 | \n 1 | \n 0 | \n 1 | \n 0 | \n virginica | \n
\n \n 146 | \n 0 | \n 0 | \n 1 | \n 0 | \n 0 | \n 1 | \n 0 | \n 0 | \n 1 | \n 1 | \n 0 | \n 0 | \n virginica | \n
\n \n 147 | \n 0 | \n 0 | \n 1 | \n 0 | \n 0 | \n 1 | \n 0 | \n 0 | \n 1 | \n 0 | \n 1 | \n 0 | \n virginica | \n
\n \n 148 | \n 0 | \n 0 | \n 1 | \n 0 | \n 0 | \n 1 | \n 0 | \n 1 | \n 0 | \n 0 | \n 0 | \n 1 | \n virginica | \n
\n \n 149 | \n 0 | \n 0 | \n 1 | \n 0 | \n 0 | \n 1 | \n 0 | \n 1 | \n 0 | \n 0 | \n 1 | \n 0 | \n virginica | \n
\n \n
\n
150 rows × 13 columns
\n
"
- },
- "execution_count": 16,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "dataset = x.join(y)\n",
- "dataset.columns = [*dataset.columns[:-1], 'iris']\n",
- "dataset"
- ]
- },
- {
- "cell_type": "markdown",
- "source": [
- "Split between train and test set in a reproducible way."
- ],
- "metadata": {
- "collapsed": false
- }
- },
- {
- "cell_type": "code",
- "execution_count": 17,
- "id": "03fc5e2c",
- "metadata": {},
- "outputs": [],
- "source": [
- "train, test = train_test_split(dataset, test_size=0.5, random_state=0)"
- ]
- },
- {
- "cell_type": "markdown",
- "source": [
- "We use as predictor a KNN with K = 4 and we train it."
- ],
- "metadata": {
- "collapsed": false
- }
- },
- {
- "cell_type": "code",
- "execution_count": 18,
- "id": "aa8a3128",
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": "0.9333333333333333"
- },
- "execution_count": 18,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "predictor = KNeighborsClassifier(n_neighbors=4)\n",
- "predictor.fit(train.iloc[:, :-1], train.iloc[:, -1])\n",
- "predictor.score(test.iloc[:, :-1], test.iloc[:, -1])"
- ]
- },
- {
- "cell_type": "markdown",
- "source": [
- "We create an extractor that uses the REAL algorithm and we extract prolog rules from our trained KNN."
- ],
- "metadata": {
- "collapsed": false
- }
- },
- {
- "cell_type": "code",
- "execution_count": 19,
- "outputs": [],
- "source": [
- "def print_scores(scores):\n",
- " print(f'Classification accuracy = {scores[EvaluableModel.ClassificationScore.ACCURACY][0]:.2f} (data), '\n",
- " f'{scores[EvaluableModel.ClassificationScore.ACCURACY][1]:.2f} (BB)\\n'\n",
- " f'F1 = {scores[EvaluableModel.ClassificationScore.F1][0]:.2f} (data), '\n",
- " f'{scores[EvaluableModel.ClassificationScore.F1][1]:.2f} (BB)')\n",
- "\n",
- "def get_scores(extractor, test, predictor):\n",
- " return extractor.score(test, predictor, True, True, EvaluableModel.Task.CLASSIFICATION,\n",
- " [EvaluableModel.ClassificationScore.ACCURACY, EvaluableModel.ClassificationScore.F1])"
- ],
- "metadata": {
- "collapsed": false,
- "pycharm": {
- "name": "#%%\n"
- }
- }
- },
- {
- "cell_type": "code",
- "execution_count": 20,
- "id": "5e97565d",
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "REAL performance (8 rules with 94.67% coverage):\n",
- "Classification accuracy = 0.96 (data), 1.00 (BB)\n",
- "F1 = 0.96 (data), 1.00 (BB)\n",
- "REAL extracted rules:\n",
- "\n",
- "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, setosa) :-\n",
- " PetalWidth =< 0.64, SepalLength =< 5.38.\n",
- "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, setosa) :-\n",
- " PetalWidth =< 0.64, SepalWidth > 3.20, SepalLength =< 6.26.\n",
- "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, versicolor) :-\n",
- " PetalWidth in [0.64, 1.63], SepalWidth =< 2.87, PetalLength > 2.26, SepalLength =< 6.26.\n",
- "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, versicolor) :-\n",
- " PetalWidth in [0.64, 1.63], SepalLength in [5.38, 6.26], SepalWidth =< 3.20.\n",
- "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, versicolor) :-\n",
- " PetalWidth in [0.64, 1.63], PetalLength =< 4.86, SepalLength > 5.38, SepalWidth =< 3.20.\n",
- "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, versicolor) :-\n",
- " SepalLength in [5.38, 6.26], SepalWidth in [2.87, 3.20], PetalLength =< 4.86, PetalWidth > 0.64.\n",
- "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, virginica) :-\n",
- " PetalLength > 4.86, SepalLength > 6.26.\n",
- "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, virginica) :-\n",
- " PetalLength > 4.86, PetalWidth > 1.63.\n"
- ]
- }
- ],
- "source": [
- "real = Extractor.real(predictor, iris_features)\n",
- "theory_from_real = real.extract(train)\n",
- "scores, completeness = get_scores(real, test, predictor)\n",
- "print(f'REAL performance ({real.n_rules} rules with {completeness * 100:.2f}% coverage):')\n",
- "print_scores(scores)\n",
- "print('REAL extracted rules:\\n\\n' + pretty_theory(theory_from_real))"
- ]
- },
- {
- "cell_type": "markdown",
- "source": [
- "We create a different extractor that use Trepan algorithm and we extract prolog rules from the same KNN."
- ],
- "metadata": {
- "collapsed": false
- }
- },
- {
- "cell_type": "code",
- "execution_count": 21,
- "id": "dc20410e",
- "metadata": {
- "pycharm": {
- "name": "#%%\n"
- }
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "TREPAN performance (3 rules with 100.00% coverage):\n",
- "Classification accuracy = 0.95 (data), 0.96 (BB)\n",
- "F1 = 0.95 (data), 0.96 (BB)\n",
- "\n",
- "Trepan extracted rules:\n",
- "\n",
- "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, versicolor) :-\n",
- " PetalLength > 2.26, PetalLength in [2.26, 4.86].\n",
- "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, virginica) :-\n",
- " PetalLength > 2.26.\n",
- "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, setosa).\n"
- ]
- }
- ],
- "source": [
- "trepan = Extractor.trepan(predictor, iris_features)\n",
- "theory_from_trepan = trepan.extract(train)\n",
- "scores, completeness = get_scores(trepan, test, predictor)\n",
- "print(f'TREPAN performance ({trepan.n_rules} rules with {completeness * 100:.2f}% coverage):')\n",
- "print_scores(scores)\n",
- "print('\\nTrepan extracted rules:\\n\\n' + pretty_theory(theory_from_trepan))"
- ]
- },
- {
- "cell_type": "markdown",
- "source": [
- "We create another different extractor that use CART algorithm."
- ],
- "metadata": {
- "collapsed": false
- }
- },
- {
- "cell_type": "code",
- "execution_count": 22,
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "CART performance (3 rules with 100.00% coverage):\n",
- "Classification accuracy = 0.95 (data), 0.96 (BB)\n",
- "F1 = 0.95 (data), 0.96 (BB)\n",
- "\n",
- "CART extracted rules:\n",
- "\n",
- "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, setosa) :-\n",
- " PetalWidth =< 0.64.\n",
- "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, virginica) :-\n",
- " PetalLength not_in [2.26, 4.86].\n",
- "iris(PetalLength, PetalWidth, SepalLength, SepalWidth, versicolor).\n"
- ]
- }
- ],
- "source": [
- "cart = Extractor.cart(predictor, discretization=iris_features, simplify=True)\n",
- "theory_from_cart = cart.extract(train)\n",
- "scores, completeness = get_scores(cart, test, predictor)\n",
- "print(f'CART performance ({cart.n_rules} rules with {completeness * 100:.2f}% coverage):')\n",
- "print_scores(scores)\n",
- "print('\\nCART extracted rules:\\n\\n' + pretty_theory(theory_from_cart))"
- ],
- "metadata": {
- "collapsed": false,
- "pycharm": {
- "name": "#%%\n"
- }
- }
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "outputs": [],
- "source": [],
- "metadata": {
- "collapsed": false,
- "pycharm": {
- "name": "#%%\n"
- }
- }
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3 (ipykernel)",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.9.7"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
-}
\ No newline at end of file
diff --git a/demo/DemoRegression.ipynb b/demo/DemoRegression.ipynb
deleted file mode 100644
index 68f73ceb..00000000
--- a/demo/DemoRegression.ipynb
+++ /dev/null
@@ -1,1835 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "id": "f52126f3",
- "metadata": {},
- "source": [
- "# PSyKE's demo for regression tasks\n",
- "\n",
- "Some imports."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 1,
- "id": "6b710e7c",
- "metadata": {},
- "outputs": [],
- "source": [
- "from psyke import Extractor, Clustering, EvaluableModel\n",
- "from psyke.tuning.pedro import PEDRO\n",
- "from psyke.tuning import Objective\n",
- "from psyke.tuning.crash import CRASH\n",
- "from sklearn.tree import DecisionTreeRegressor\n",
- "from psyke.utils.logic import pretty_theory\n",
- "from psyke.utils.metrics import mae, mse, r2\n",
- "from sklearn.model_selection import train_test_split\n",
- "from psyke.utils import Target\n",
- "import pandas as pd"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "d7c90ed2",
- "metadata": {
- "pycharm": {
- "name": "#%% md\n"
- }
- },
- "source": [
- "Import a dataset."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "id": "f8e46c49",
- "metadata": {},
- "outputs": [],
- "source": [
- "dataset = pd.read_csv(\"../test/resources/datasets/df.csv\")\n",
- "dataset = dataset[[\"X\", \"Y\", \"Z4\"]].dropna()\n",
- "#dataset = pd.read_csv(\"../test/resources/datasets/CCPP.csv\", sep=\";\", decimal=\",\")\n",
- "#dataset"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "d673b766",
- "metadata": {},
- "source": [
- "Split between train and test set in a reproducible way."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "id": "03fc5e2c",
- "metadata": {},
- "outputs": [],
- "source": [
- "train, test = train_test_split(dataset, test_size=0.5, random_state=10)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "outputs": [],
- "source": [
- "#from psyke.tuning.orchid import OrCHiD\n",
- "\n",
- "#orchid = OrCHiD(dataframe=train, algorithm=OrCHiD.Algorithm.CREAM, output=Target.REGRESSION,\n",
- "# max_mae_increase=1.2, min_rule_decrease=0.9, readability_tradeoff=0.1, patience=5, max_depth=3)\n",
- "#orchid.search()\n",
- "#(_, _, depth, threshold) = orchid.get_best()[0]"
- ],
- "metadata": {
- "collapsed": false,
- "pycharm": {
- "name": "#%%\n"
- }
- }
- },
- {
- "cell_type": "markdown",
- "id": "fa6754a0",
- "metadata": {},
- "source": [
- "We use as predictor a KNN and we train it."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "id": "bed764ca",
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "MAE = 0.08\n",
- "MSE = 0.03\n",
- "R2 = 1.00\n"
- ]
- }
- ],
- "source": [
- "#predictor = KNeighborsRegressor(n_neighbors=3).fit(train.iloc[:, :-1], train.iloc[:, -1])\n",
- "predictor = DecisionTreeRegressor().fit(train.iloc[:, :-1], train.iloc[:, -1])\n",
- "#predictor = LinearRegression().fit(train.iloc[:, :-1], train.iloc[:, -1])\n",
- "\n",
- "predicted = predictor.predict(test.iloc[:, :-1]).flatten()\n",
- "true = test.iloc[:, -1]\n",
- "\n",
- "print(f'MAE = {mae(true, predicted):.2f}')\n",
- "print(f'MSE = {mse(true, predicted):.2f}')\n",
- "print(f'R2 = {r2(true, predicted):.2f}')"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "collapsed": false,
- "pycharm": {
- "name": "#%% md\n"
- }
- },
- "source": [
- "We define a function to print the extractors' evaluation"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 6,
- "metadata": {
- "collapsed": false,
- "pycharm": {
- "name": "#%%\n"
- }
- },
- "outputs": [],
- "source": [
- "def print_scores(scores):\n",
- " print(f'MAE = {scores[EvaluableModel.RegressionScore.MAE][0]:.2f} (data), '\n",
- " f'{scores[EvaluableModel.RegressionScore.MAE][1]:.2f} (BB)\\n'\n",
- " f'MSE = {scores[EvaluableModel.RegressionScore.MSE][0]:.2f} (data), '\n",
- " f'{scores[EvaluableModel.RegressionScore.MSE][1]:.2f} (BB)\\n'\n",
- " f'R2 = {scores[EvaluableModel.RegressionScore.R2][0]:.2f} (data), '\n",
- " f'{scores[EvaluableModel.RegressionScore.R2][1]:.2f} (BB)')\n",
- "\n",
- "def get_scores(extractor, test, predictor):\n",
- " return extractor.score(test, predictor, True, True, EvaluableModel.Task.REGRESSION,\n",
- " [EvaluableModel.RegressionScore.MAE, EvaluableModel.RegressionScore.MSE,\n",
- " EvaluableModel.RegressionScore.R2])"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "96835867",
- "metadata": {},
- "source": [
- "We create several extractors that use ITER, GridEx and GridREx algorithms to extract prolog rules from the predictor."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 8,
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "ORBIt performance (2 rules with 100.00% coverage):\n",
- "MAE = 4.15 (data), 4.15 (BB)\n",
- "MSE = 28.12 (data), 28.10 (BB)\n",
- "R2 = -0.13 (data), -0.13 (BB)\n",
- "\n",
- "ORBIt extracted rules:\n",
- "\n",
- "'Z4'(X, Y, 15.42) :-\n",
- " 0.02 * X - 0.03 * Y =< -0.01, -0.02 * X + 0.03 * Y =< 0.01, 1.0 * X + 0.0 * Y =< 0.46, -1.0 * X + 0.0 * Y =< -0.16.\n",
- "'Z4'(X, Y, 5.053691).\n"
- ]
- }
- ],
- "source": [
- "orbit = Extractor.orbit(predictor, depth=3, error_threshold=1.0, gauss_components=2, output=Target.REGRESSION)\n",
- "theory_from_orbit = orbit.extract(train)\n",
- "scores, completeness = get_scores(orbit, test, predictor)\n",
- "print(f'ORBIt performance ({orbit.n_rules} rules with {completeness * 100:.2f}% coverage):')\n",
- "print_scores(scores)\n",
- "print('\\nORBIt extracted rules:\\n\\n' + pretty_theory(theory_from_orbit))"
- ],
- "metadata": {
- "collapsed": false,
- "pycharm": {
- "name": "#%%\n"
- }
- }
- },
- {
- "cell_type": "code",
- "execution_count": 14,
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "CReEPy performance (3 rules with 100.00% coverage):\n",
- "MAE = 0.68 (data), 0.71 (BB)\n",
- "MSE = 2.05 (data), 2.06 (BB)\n",
- "R2 = 0.92 (data), 0.92 (BB)\n",
- "\n",
- "CReEPy extracted rules (ExACT):\n",
- "\n",
- "'Z4'(X, Y, Z4) :-\n",
- " X in [0.15, 0.84], Y in [-0.00, 0.59], Z4 is 7.49 - 7.63 * X + 12.05 * Y.\n",
- "'Z4'(X, Y, Z4) :-\n",
- " X in [0.15, 0.84], Y in [-0.00, 0.84], Z4 is 9.0 - 12.0 * X + 15.0 * Y.\n",
- "'Z4'(X, Y, Z4) :-\n",
- " Y in [-0.00, 1.00], Z4 is 2.0 + 4.0 * X - 3.0 * Y.\n"
- ]
- }
- ],
- "source": [
- "creepy = Extractor.creepy(predictor, depth=3, error_threshold=0.02, output=Target.REGRESSION,\n",
- " clustering=Clustering.exact)\n",
- "theory_from_creepy = creepy.extract(train)\n",
- "scores, completeness = get_scores(creepy, test, predictor)\n",
- "print(f'CReEPy performance ({creepy.n_rules} rules with {completeness * 100:.2f}% coverage):')\n",
- "print_scores(scores)\n",
- "print('\\nCReEPy extracted rules (ExACT):\\n\\n' + pretty_theory(theory_from_creepy))"
- ],
- "metadata": {
- "collapsed": false,
- "pycharm": {
- "name": "#%%\n"
- }
- }
- },
- {
- "cell_type": "code",
- "execution_count": 20,
- "metadata": {
- "collapsed": false,
- "pycharm": {
- "name": "#%%\n"
- }
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "CReEPy performance (4 rules with 100.00% coverage):\n",
- "MAE = 3.37 (data), 3.47 (BB)\n",
- "MSE = 18.62 (data), 19.19 (BB)\n",
- "R2 = 0.94 (data), 0.93 (BB)\n",
- "\n",
- "CReEPy extracted rules (CREAM):\n",
- "\n",
- "'PE'(AP, AT, RH, V, PE) :-\n",
- " AT in [6.21, 32.45], V in [34.02, 50.16], AP in [997.90, 1026.41], RH in [35.63, 100.10], PE is 502.53 - 2.16 * AP - 0.26 * AT + 0.01 * RH - 0.11 * V.\n",
- "'PE'(AP, AT, RH, V, PE) :-\n",
- " AT in [6.21, 35.77], V in [25.35, 81.56], AP in [997.84, 1026.45], RH in [25.55, 100.12], PE is 234.73 - 1.42 * AP - 0.29 * AT + 0.26 * RH - 0.12 * V.\n",
- "'PE'(AP, AT, RH, V, PE) :-\n",
- " AT in [3.30, 14.60], V in [34.68, 44.47], AP in [1011.31, 1033.25], RH in [58.98, 98.68], PE is 720.26 - 2.20 * AP - 0.47 * AT - 0.18 * RH - 0.22 * V.\n",
- "'PE'(AP, AT, RH, V, PE) :-\n",
- " V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15], PE is 579.01 - 2.05 * AP - 0.60 * AT - 0.05 * RH + 0.00 * V.\n"
- ]
- }
- ],
- "source": [
- "creepy = Extractor.creepy(predictor, depth=2, error_threshold=0.02, output=Target.REGRESSION,\n",
- " clustering=Clustering.cream)\n",
- "theory_from_creepy = creepy.extract(train)\n",
- "scores, completeness = get_scores(creepy, test, predictor)\n",
- "print(f'CReEPy performance ({creepy.n_rules} rules with {completeness * 100:.2f}% coverage):')\n",
- "print_scores(scores)\n",
- "print('\\nCReEPy extracted rules (CREAM):\\n\\n' + pretty_theory(theory_from_creepy))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 21,
- "metadata": {
- "collapsed": false,
- "pycharm": {
- "name": "#%%\n"
- }
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Algorithm.ExACT. Depth: 1. Threshold = 0.00. MAE = 3.52, 2 rules\n",
- "Algorithm.ExACT. Depth: 1. Threshold = 0.00. MAE = 3.54, 2 rules\n",
- "\n",
- "Algorithm.ExACT. Depth: 2. Threshold = 0.00. MAE = 3.52, 3 rules\n",
- "Algorithm.ExACT. Depth: 2. Threshold = 0.00. MAE = 3.48, 3 rules\n",
- "Algorithm.ExACT. Depth: 2. Threshold = 0.00. MAE = 3.50, 3 rules\n",
- "\n",
- "Algorithm.ExACT. Depth: 3. Threshold = 0.00. MAE = 3.44, 4 rules\n",
- "Algorithm.ExACT. Depth: 3. Threshold = 0.00. MAE = 3.41, 4 rules\n",
- "Algorithm.ExACT. Depth: 3. Threshold = 0.00. MAE = 3.52, 4 rules\n",
- "\n",
- "**********************\n",
- "Best Algorithm.ExACT\n",
- "**********************\n",
- "MAE = 3.41, 4 rules\n",
- "Threshold = 0.00\n",
- "Depth = 3\n",
- "\n",
- "**********************\n",
- "Best MAE \n",
- "**********************\n",
- "MAE = 3.41, 4 rules\n",
- "Threshold = 0.00\n",
- "Depth = 3\n",
- "\n",
- "**********************\n",
- "Best N rules\n",
- "**********************\n",
- "MAE = 3.54, 2 rules\n",
- "Threshold = 0.00\n",
- "Depth = 1\n",
- "\n",
- "CReEPy performance (4 rules with 100.00% coverage):\n",
- "MAE = 3.37 (data), 3.46 (BB)\n",
- "MSE = 18.48 (data), 19.00 (BB)\n",
- "R2 = 0.94 (data), 0.94 (BB)\n",
- "\n",
- "CReEPy extracted rules:\n",
- "\n",
- "'PE'(AP, AT, RH, V, PE) :-\n",
- " AT in [6.21, 32.45], V in [35.39, 50.16], AP in [998.07, 1026.40], RH in [35.63, 100.10], PE is 499.89 - 2.16 * AP - 0.27 * AT + 0.01 * RH - 0.11 * V.\n",
- "'PE'(AP, AT, RH, V, PE) :-\n",
- " AT in [6.21, 32.45], V in [34.02, 50.16], AP in [997.90, 1026.41], RH in [35.63, 100.10], PE is 697.90 - 1.74 * AP - 2.04 * AT - 0.17 * RH + 0.61 * V.\n",
- "'PE'(AP, AT, RH, V, PE) :-\n",
- " AT in [6.21, 35.77], V in [25.35, 81.56], AP in [997.84, 1026.45], RH in [25.55, 100.12], PE is 234.73 - 1.42 * AP - 0.29 * AT + 0.26 * RH - 0.12 * V.\n",
- "'PE'(AP, AT, RH, V, PE) :-\n",
- " V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15], PE is 628.20 - 2.19 * AP - 0.50 * AT - 0.09 * RH - 0.17 * V.\n"
- ]
- }
- ],
- "source": [
- "crash = CRASH(predictor, train, max_depth=3, patience=1, readability_tradeoff=.5,\n",
- " algorithm=CRASH.Algorithm.ExACT, output=Target.REGRESSION)\n",
- "crash.search()\n",
- "(_, _, depth, threshold) = crash.get_best()[0]\n",
- "\n",
- "creepy = Extractor.creepy(predictor, depth=depth, error_threshold=threshold, output=Target.REGRESSION,\n",
- " clustering=Clustering.exact)\n",
- "theory_from_creepy = creepy.extract(train)\n",
- "scores, completeness = get_scores(creepy, test, predictor)\n",
- "print(f'CReEPy performance ({creepy.n_rules} rules with {completeness * 100:.2f}% coverage):')\n",
- "print_scores(scores)\n",
- "print('\\nCReEPy extracted rules:\\n\\n' + pretty_theory(theory_from_creepy))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 22,
- "metadata": {
- "collapsed": false,
- "pycharm": {
- "name": "#%%\n"
- }
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Algorithm.CREAM. Depth: 1. Threshold = 0.00. MAE = 10.29, 2 rules\n",
- "Algorithm.CREAM. Depth: 1. Threshold = 0.00. MAE = 8.46, 2 rules\n",
- "Algorithm.CREAM. Depth: 1. Threshold = 0.00. MAE = 10.29, 2 rules\n",
- "\n",
- "Algorithm.CREAM. Depth: 2. Threshold = 0.00. MAE = 6.46, 4 rules\n",
- "Algorithm.CREAM. Depth: 2. Threshold = 0.00. MAE = 6.10, 4 rules\n",
- "Algorithm.CREAM. Depth: 2. Threshold = 0.00. MAE = 7.75, 4 rules\n",
- "\n",
- "Algorithm.CREAM. Depth: 3. Threshold = 0.00. "
- ]
- },
- {
- "ename": "KeyboardInterrupt",
- "evalue": "",
- "output_type": "error",
- "traceback": [
- "\u001B[1;31m---------------------------------------------------------------------------\u001B[0m",
- "\u001B[1;31mKeyboardInterrupt\u001B[0m Traceback (most recent call last)",
- "\u001B[1;32m~\\AppData\\Local\\Temp/ipykernel_14404/1950581394.py\u001B[0m in \u001B[0;36m\u001B[1;34m\u001B[0m\n\u001B[0;32m 1\u001B[0m \u001B[0mcrash\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mCRASH\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mpredictor\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mtrain\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mmax_depth\u001B[0m\u001B[1;33m=\u001B[0m\u001B[1;36m3\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mpatience\u001B[0m\u001B[1;33m=\u001B[0m\u001B[1;36m1\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mreadability_tradeoff\u001B[0m\u001B[1;33m=\u001B[0m\u001B[1;36m.75\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0malgorithm\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mCRASH\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mAlgorithm\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mCREAM\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m----> 2\u001B[1;33m \u001B[0mcrash\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0msearch\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 3\u001B[0m \u001B[1;33m(\u001B[0m\u001B[0m_\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0m_\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mdepth\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mthreshold\u001B[0m\u001B[1;33m)\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mcrash\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mget_best\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m[\u001B[0m\u001B[1;36m0\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 4\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 5\u001B[0m creepy = Extractor.creepy(predictor, depth=depth, error_threshold=threshold, output=Target.REGRESSION,\n",
- "\u001B[1;32m~\\Desktop\\psyke\\psyke-python\\psyke\\tuning\\crash\\__init__.py\u001B[0m in \u001B[0;36msearch\u001B[1;34m(self)\u001B[0m\n\u001B[0;32m 23\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 24\u001B[0m \u001B[1;32mdef\u001B[0m \u001B[0msearch\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mself\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m---> 25\u001B[1;33m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mparams\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m__search_depth\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 26\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 27\u001B[0m \u001B[1;32mdef\u001B[0m \u001B[0m__search_depth\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mself\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n",
- "\u001B[1;32m~\\Desktop\\psyke\\psyke-python\\psyke\\tuning\\crash\\__init__.py\u001B[0m in \u001B[0;36m__search_depth\u001B[1;34m(self)\u001B[0m\n\u001B[0;32m 30\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 31\u001B[0m \u001B[1;32mfor\u001B[0m \u001B[0mdepth\u001B[0m \u001B[1;32min\u001B[0m \u001B[0mrange\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;36m1\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mmax_depth\u001B[0m \u001B[1;33m+\u001B[0m \u001B[1;36m1\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m---> 32\u001B[1;33m \u001B[0mp\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m__search_threshold\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mdepth\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 33\u001B[0m \u001B[0mb\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mOptimizer\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_best\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mp\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m[\u001B[0m\u001B[1;36m1\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 34\u001B[0m \u001B[0mprint\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n",
- "\u001B[1;32m~\\Desktop\\psyke\\psyke-python\\psyke\\tuning\\crash\\__init__.py\u001B[0m in \u001B[0;36m__search_threshold\u001B[1;34m(self, depth)\u001B[0m\n\u001B[0;32m 56\u001B[0m \u001B[0mclustering\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mClustering\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mcream\u001B[0m \u001B[1;32mif\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0malgorithm\u001B[0m \u001B[1;33m==\u001B[0m \u001B[0mCRASH\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mAlgorithm\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mCREAM\u001B[0m \u001B[1;32melse\u001B[0m \u001B[0mClustering\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mexact\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 57\u001B[0m )\n\u001B[1;32m---> 58\u001B[1;33m \u001B[0m_\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mextractor\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mextract\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mdataframe\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 59\u001B[0m mae, n = (extractor.mae(self.dataframe, self.predictor) if self.objective == Objective.MODEL else\n\u001B[0;32m 60\u001B[0m extractor.mae(self.dataframe)), extractor.n_rules\n",
- "\u001B[1;32m~\\Desktop\\psyke\\psyke-python\\psyke\\__init__.py\u001B[0m in \u001B[0;36mextract\u001B[1;34m(self, dataframe, mapping, sort)\u001B[0m\n",
- "\u001B[1;32m~\\Desktop\\psyke\\psyke-python\\psyke\\extraction\\hypercubic\\creepy\\__init__.py\u001B[0m in \u001B[0;36m_extract\u001B[1;34m(self, dataframe, mapping, sort)\u001B[0m\n\u001B[0;32m 32\u001B[0m \u001B[1;32mraise\u001B[0m \u001B[0mTypeError\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;34m\"clustering must be a HyperCubeClustering\"\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 33\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m---> 34\u001B[1;33m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mclustering\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mfit\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mdataframe\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 35\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_hypercubes\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mclustering\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mget_hypercubes\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 36\u001B[0m \u001B[1;32mfor\u001B[0m \u001B[0mcube\u001B[0m \u001B[1;32min\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_hypercubes\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n",
- "\u001B[1;32m~\\Desktop\\psyke\\psyke-python\\psyke\\clustering\\exact\\__init__.py\u001B[0m in \u001B[0;36mfit\u001B[1;34m(self, dataframe)\u001B[0m\n\u001B[0;32m 58\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_predictor\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mfit\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mdataframe\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0miloc\u001B[0m\u001B[1;33m[\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m,\u001B[0m \u001B[1;33m:\u001B[0m\u001B[1;33m-\u001B[0m\u001B[1;36m1\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mdataframe\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0miloc\u001B[0m\u001B[1;33m[\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m,\u001B[0m \u001B[1;33m-\u001B[0m\u001B[1;36m1\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 59\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_hypercubes\u001B[0m \u001B[1;33m=\u001B[0m\u001B[0;31m \u001B[0m\u001B[0;31m\\\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m---> 60\u001B[1;33m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_iterate\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mNode\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mdataframe\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mHyperCube\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mcreate_surrounding_cube\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mdataframe\u001B[0m\u001B[1;33m,\u001B[0m \u001B[1;32mTrue\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_output\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 61\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 62\u001B[0m \u001B[1;32mdef\u001B[0m \u001B[0mget_hypercubes\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mself\u001B[0m\u001B[1;33m)\u001B[0m \u001B[1;33m->\u001B[0m \u001B[0mIterable\u001B[0m\u001B[1;33m[\u001B[0m\u001B[0mHyperCube\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n",
- "\u001B[1;32m~\\Desktop\\psyke\\psyke-python\\psyke\\clustering\\cream\\__init__.py\u001B[0m in \u001B[0;36m_iterate\u001B[1;34m(self, surrounding)\u001B[0m\n\u001B[0;32m 52\u001B[0m \u001B[0mgauss_params\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mselect_gaussian_mixture\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mdata\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mgauss_components\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 53\u001B[0m \u001B[0mgauss_pred\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mgauss_params\u001B[0m\u001B[1;33m[\u001B[0m\u001B[1;36m2\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mpredict\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mdata\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m---> 54\u001B[1;33m \u001B[0mcubes\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m__eligible_cubes\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mgauss_pred\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mnode\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mgauss_params\u001B[0m\u001B[1;33m[\u001B[0m\u001B[1;36m1\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 55\u001B[0m \u001B[1;32mif\u001B[0m \u001B[0mlen\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mcubes\u001B[0m\u001B[1;33m)\u001B[0m \u001B[1;33m<\u001B[0m \u001B[1;36m1\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 56\u001B[0m \u001B[1;32mcontinue\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n",
- "\u001B[1;32m~\\Desktop\\psyke\\psyke-python\\psyke\\clustering\\cream\\__init__.py\u001B[0m in \u001B[0;36m__eligible_cubes\u001B[1;34m(self, gauss_pred, node, clusters)\u001B[0m\n\u001B[0;32m 27\u001B[0m \u001B[1;32mif\u001B[0m \u001B[0mlen\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mdf\u001B[0m\u001B[1;33m)\u001B[0m \u001B[1;33m==\u001B[0m \u001B[1;36m0\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 28\u001B[0m \u001B[1;32mcontinue\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m---> 29\u001B[1;33m \u001B[0minner_cube\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_create_cube\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mdf\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mclusters\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 30\u001B[0m \u001B[0mindices\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_indices\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0minner_cube\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mnode\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mdataframe\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 31\u001B[0m \u001B[1;32mif\u001B[0m \u001B[0mindices\u001B[0m \u001B[1;32mis\u001B[0m \u001B[1;32mNone\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n",
- "\u001B[1;32m~\\Desktop\\psyke\\psyke-python\\psyke\\clustering\\exact\\__init__.py\u001B[0m in \u001B[0;36m_create_cube\u001B[1;34m(self, dataframe, clusters)\u001B[0m\n\u001B[0;32m 49\u001B[0m \u001B[1;32mdef\u001B[0m \u001B[0m_create_cube\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mself\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mdataframe\u001B[0m\u001B[1;33m:\u001B[0m \u001B[0mpd\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mDataFrame\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mclusters\u001B[0m\u001B[1;33m:\u001B[0m \u001B[0mint\u001B[0m\u001B[1;33m)\u001B[0m \u001B[1;33m->\u001B[0m \u001B[0mClosedCube\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 50\u001B[0m \u001B[0mdata\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mExACT\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_remove_string_label\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mdataframe\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m---> 51\u001B[1;33m \u001B[0mdbscan_pred\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mDBSCAN\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0meps\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mselect_dbscan_epsilon\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mdata\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mclusters\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mfit_predict\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mdata\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0miloc\u001B[0m\u001B[1;33m[\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m,\u001B[0m \u001B[1;33m:\u001B[0m\u001B[1;33m-\u001B[0m\u001B[1;36m1\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 52\u001B[0m return HyperCube.create_surrounding_cube(\n\u001B[0;32m 53\u001B[0m \u001B[0mdataframe\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0miloc\u001B[0m\u001B[1;33m[\u001B[0m\u001B[0mnp\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mwhere\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mdbscan_pred\u001B[0m \u001B[1;33m==\u001B[0m \u001B[0mCounter\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mdbscan_pred\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mmost_common\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;36m1\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m[\u001B[0m\u001B[1;36m0\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m[\u001B[0m\u001B[1;36m0\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m,\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n",
- "\u001B[1;32m~\\Desktop\\psyke\\psyke-python\\psyke\\clustering\\utils.py\u001B[0m in \u001B[0;36mselect_dbscan_epsilon\u001B[1;34m(data, clusters)\u001B[0m\n\u001B[0;32m 30\u001B[0m \u001B[0mepsilon\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mmax\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mdistances\u001B[0m\u001B[1;33m[\u001B[0m\u001B[1;33m-\u001B[0m\u001B[1;36m1\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m,\u001B[0m \u001B[1;36m1e-3\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 31\u001B[0m \u001B[0mk\u001B[0m \u001B[1;33m=\u001B[0m \u001B[1;36m1.\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m---> 32\u001B[1;33m \u001B[0mdbscan_pred\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mDBSCAN\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0meps\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mepsilon\u001B[0m \u001B[1;33m*\u001B[0m \u001B[0mk\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mfit_predict\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mdata\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0miloc\u001B[0m\u001B[1;33m[\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m,\u001B[0m \u001B[1;33m:\u001B[0m\u001B[1;33m-\u001B[0m\u001B[1;36m1\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 33\u001B[0m \u001B[1;31m# while Counter(dbscan_pred).most_common(1)[0][0] == -1:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 34\u001B[0m \u001B[1;32mfor\u001B[0m \u001B[0mi\u001B[0m \u001B[1;32min\u001B[0m \u001B[0mrange\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;36m1000\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n",
- "\u001B[1;32m~\\Anaconda3\\lib\\site-packages\\sklearn\\cluster\\_dbscan.py\u001B[0m in \u001B[0;36mfit_predict\u001B[1;34m(self, X, y, sample_weight)\u001B[0m\n\u001B[0;32m 456\u001B[0m \u001B[0mCluster\u001B[0m \u001B[0mlabels\u001B[0m\u001B[1;33m.\u001B[0m \u001B[0mNoisy\u001B[0m \u001B[0msamples\u001B[0m \u001B[0mare\u001B[0m \u001B[0mgiven\u001B[0m \u001B[0mthe\u001B[0m \u001B[0mlabel\u001B[0m \u001B[1;33m-\u001B[0m\u001B[1;36m1.\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 457\u001B[0m \"\"\"\n\u001B[1;32m--> 458\u001B[1;33m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mfit\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mX\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0msample_weight\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0msample_weight\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 459\u001B[0m \u001B[1;32mreturn\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mlabels_\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 460\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n",
- "\u001B[1;32m~\\Anaconda3\\lib\\site-packages\\sklearn\\cluster\\_dbscan.py\u001B[0m in \u001B[0;36mfit\u001B[1;34m(self, X, y, sample_weight)\u001B[0m\n\u001B[0;32m 404\u001B[0m \u001B[0mneighbors_model\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mfit\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mX\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 405\u001B[0m \u001B[1;31m# This has worst case O(n^2) memory complexity\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m--> 406\u001B[1;33m \u001B[0mneighborhoods\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mneighbors_model\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mradius_neighbors\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mX\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mreturn_distance\u001B[0m\u001B[1;33m=\u001B[0m\u001B[1;32mFalse\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 407\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 408\u001B[0m \u001B[1;32mif\u001B[0m \u001B[0msample_weight\u001B[0m \u001B[1;32mis\u001B[0m \u001B[1;32mNone\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n",
- "\u001B[1;32m~\\Anaconda3\\lib\\site-packages\\sklearn\\neighbors\\_base.py\u001B[0m in \u001B[0;36mradius_neighbors\u001B[1;34m(self, X, radius, return_distance, sort_results)\u001B[0m\n\u001B[0;32m 1167\u001B[0m \u001B[0mn_jobs\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0meffective_n_jobs\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mn_jobs\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 1168\u001B[0m \u001B[0mdelayed_query\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mdelayed\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0m_tree_query_radius_parallel_helper\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m-> 1169\u001B[1;33m chunked_results = Parallel(n_jobs, prefer=\"threads\")(\n\u001B[0m\u001B[0;32m 1170\u001B[0m delayed_query(\n\u001B[0;32m 1171\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_tree\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mX\u001B[0m\u001B[1;33m[\u001B[0m\u001B[0ms\u001B[0m\u001B[1;33m]\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mradius\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mreturn_distance\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0msort_results\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0msort_results\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n",
- "\u001B[1;32m~\\Anaconda3\\lib\\site-packages\\joblib\\parallel.py\u001B[0m in \u001B[0;36m__call__\u001B[1;34m(self, iterable)\u001B[0m\n\u001B[0;32m 1041\u001B[0m \u001B[1;31m# remaining jobs.\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 1042\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_iterating\u001B[0m \u001B[1;33m=\u001B[0m \u001B[1;32mFalse\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m-> 1043\u001B[1;33m \u001B[1;32mif\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mdispatch_one_batch\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0miterator\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 1044\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_iterating\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_original_iterator\u001B[0m \u001B[1;32mis\u001B[0m \u001B[1;32mnot\u001B[0m \u001B[1;32mNone\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 1045\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n",
- "\u001B[1;32m~\\Anaconda3\\lib\\site-packages\\joblib\\parallel.py\u001B[0m in \u001B[0;36mdispatch_one_batch\u001B[1;34m(self, iterator)\u001B[0m\n\u001B[0;32m 859\u001B[0m \u001B[1;32mreturn\u001B[0m \u001B[1;32mFalse\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 860\u001B[0m \u001B[1;32melse\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m--> 861\u001B[1;33m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_dispatch\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mtasks\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 862\u001B[0m \u001B[1;32mreturn\u001B[0m \u001B[1;32mTrue\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 863\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n",
- "\u001B[1;32m~\\Anaconda3\\lib\\site-packages\\joblib\\parallel.py\u001B[0m in \u001B[0;36m_dispatch\u001B[1;34m(self, batch)\u001B[0m\n\u001B[0;32m 777\u001B[0m \u001B[1;32mwith\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_lock\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 778\u001B[0m \u001B[0mjob_idx\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mlen\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_jobs\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m--> 779\u001B[1;33m \u001B[0mjob\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_backend\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mapply_async\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mbatch\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mcallback\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mcb\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 780\u001B[0m \u001B[1;31m# A job can complete so quickly than its callback is\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 781\u001B[0m \u001B[1;31m# called before we get here, causing self._jobs to\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n",
- "\u001B[1;32m~\\Anaconda3\\lib\\site-packages\\joblib\\_parallel_backends.py\u001B[0m in \u001B[0;36mapply_async\u001B[1;34m(self, func, callback)\u001B[0m\n\u001B[0;32m 206\u001B[0m \u001B[1;32mdef\u001B[0m \u001B[0mapply_async\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mself\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mfunc\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mcallback\u001B[0m\u001B[1;33m=\u001B[0m\u001B[1;32mNone\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 207\u001B[0m \u001B[1;34m\"\"\"Schedule a func to be run\"\"\"\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m--> 208\u001B[1;33m \u001B[0mresult\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mImmediateResult\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mfunc\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 209\u001B[0m \u001B[1;32mif\u001B[0m \u001B[0mcallback\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 210\u001B[0m \u001B[0mcallback\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mresult\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n",
- "\u001B[1;32m~\\Anaconda3\\lib\\site-packages\\joblib\\_parallel_backends.py\u001B[0m in \u001B[0;36m__init__\u001B[1;34m(self, batch)\u001B[0m\n\u001B[0;32m 570\u001B[0m \u001B[1;31m# Don't delay the application, to avoid keeping the input\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 571\u001B[0m \u001B[1;31m# arguments in memory\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m--> 572\u001B[1;33m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mresults\u001B[0m \u001B[1;33m=\u001B[0m \u001B[0mbatch\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 573\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 574\u001B[0m \u001B[1;32mdef\u001B[0m \u001B[0mget\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mself\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n",
- "\u001B[1;32m~\\Anaconda3\\lib\\site-packages\\joblib\\parallel.py\u001B[0m in \u001B[0;36m__call__\u001B[1;34m(self)\u001B[0m\n\u001B[0;32m 260\u001B[0m \u001B[1;31m# change the default number of processes to -1\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 261\u001B[0m \u001B[1;32mwith\u001B[0m \u001B[0mparallel_backend\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_backend\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mn_jobs\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_n_jobs\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m--> 262\u001B[1;33m return [func(*args, **kwargs)\n\u001B[0m\u001B[0;32m 263\u001B[0m for func, args, kwargs in self.items]\n\u001B[0;32m 264\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n",
- "\u001B[1;32m~\\Anaconda3\\lib\\site-packages\\joblib\\parallel.py\u001B[0m in \u001B[0;36m\u001B[1;34m(.0)\u001B[0m\n\u001B[0;32m 260\u001B[0m \u001B[1;31m# change the default number of processes to -1\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 261\u001B[0m \u001B[1;32mwith\u001B[0m \u001B[0mparallel_backend\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_backend\u001B[0m\u001B[1;33m,\u001B[0m \u001B[0mn_jobs\u001B[0m\u001B[1;33m=\u001B[0m\u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0m_n_jobs\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m--> 262\u001B[1;33m return [func(*args, **kwargs)\n\u001B[0m\u001B[0;32m 263\u001B[0m for func, args, kwargs in self.items]\n\u001B[0;32m 264\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n",
- "\u001B[1;32m~\\Anaconda3\\lib\\site-packages\\sklearn\\utils\\fixes.py\u001B[0m in \u001B[0;36m__call__\u001B[1;34m(self, *args, **kwargs)\u001B[0m\n\u001B[0;32m 115\u001B[0m \u001B[1;32mdef\u001B[0m \u001B[0m__call__\u001B[0m\u001B[1;33m(\u001B[0m\u001B[0mself\u001B[0m\u001B[1;33m,\u001B[0m \u001B[1;33m*\u001B[0m\u001B[0margs\u001B[0m\u001B[1;33m,\u001B[0m \u001B[1;33m**\u001B[0m\u001B[0mkwargs\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 116\u001B[0m \u001B[1;32mwith\u001B[0m \u001B[0mconfig_context\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;33m**\u001B[0m\u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mconfig\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m:\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[1;32m--> 117\u001B[1;33m \u001B[1;32mreturn\u001B[0m \u001B[0mself\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mfunction\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;33m*\u001B[0m\u001B[0margs\u001B[0m\u001B[1;33m,\u001B[0m \u001B[1;33m**\u001B[0m\u001B[0mkwargs\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 118\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 119\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n",
- "\u001B[1;32m~\\Anaconda3\\lib\\site-packages\\sklearn\\neighbors\\_base.py\u001B[0m in \u001B[0;36m_tree_query_radius_parallel_helper\u001B[1;34m(tree, *args, **kwargs)\u001B[0m\n\u001B[0;32m 949\u001B[0m \u001B[0mcloudpickle\u001B[0m \u001B[0munder\u001B[0m \u001B[0mPyPy\u001B[0m\u001B[1;33m.\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 950\u001B[0m \"\"\"\n\u001B[1;32m--> 951\u001B[1;33m \u001B[1;32mreturn\u001B[0m \u001B[0mtree\u001B[0m\u001B[1;33m.\u001B[0m\u001B[0mquery_radius\u001B[0m\u001B[1;33m(\u001B[0m\u001B[1;33m*\u001B[0m\u001B[0margs\u001B[0m\u001B[1;33m,\u001B[0m \u001B[1;33m**\u001B[0m\u001B[0mkwargs\u001B[0m\u001B[1;33m)\u001B[0m\u001B[1;33m\u001B[0m\u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0m\u001B[0;32m 952\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n\u001B[0;32m 953\u001B[0m \u001B[1;33m\u001B[0m\u001B[0m\n",
- "\u001B[1;31mKeyboardInterrupt\u001B[0m: "
- ]
- }
- ],
- "source": [
- "crash = CRASH(predictor, train, max_depth=3, patience=1, readability_tradeoff=.75, algorithm=CRASH.Algorithm.CREAM)\n",
- "crash.search()\n",
- "(_, _, depth, threshold) = crash.get_best()[0]\n",
- "\n",
- "creepy = Extractor.creepy(predictor, depth=depth, error_threshold=threshold, output=Target.REGRESSION,\n",
- " clustering=Clustering.cream)\n",
- "theory_from_creepy = creepy.extract(train)\n",
- "scores, completeness = get_scores(creepy, test, predictor)\n",
- "print(f'CReEPy performance ({creepy.n_rules} rules with {completeness * 100:.2f}% coverage):')\n",
- "print_scores(scores)\n",
- "print('\\nCReEPy extracted rules:\\n\\n' + pretty_theory(theory_from_creepy))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "collapsed": false,
- "pycharm": {
- "name": "#%%\n"
- }
- },
- "outputs": [],
- "source": [
- "it = Extractor.iter(predictor, min_update=1.0 / 10, n_points=1, max_iterations=600,\n",
- " min_examples=100, threshold=5)\n",
- "theory_from_iter = it.extract(train)\n",
- "scores, completeness = get_scores(it, test, predictor)\n",
- "print(f'ITER performance ({it.n_rules} rules with {completeness * 100:.2f}% coverage):')\n",
- "print_scores(scores)\n",
- "print('\\nITER extracted rules:\\n\\n' + pretty_theory(theory_from_iter))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 11,
- "metadata": {
- "collapsed": false,
- "pycharm": {
- "name": "#%%\n"
- }
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Algorithm.GRIDEX. Grid (1). Fixed (2). Threshold = 0.00. MAE = 6.45, 15 rules\n",
- "Algorithm.GRIDEX. Grid (1). Fixed (2). Threshold = 0.00. MAE = 6.45, 30 rules\n",
- "\n",
- "Algorithm.GRIDEX. Grid (1). Fixed (3). Threshold = 0.00. MAE = 6.45, 86 rules\n",
- "Algorithm.GRIDEX. Grid (1). Fixed (3). Threshold = 0.00. MAE = 6.45, 142 rules\n",
- "\n",
- "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.99, 2)]). Threshold = 0.00. MAE = 6.45, 144 rules\n",
- "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.99, 2)]). Threshold = 0.00. MAE = 6.45, 146 rules\n",
- "\n",
- "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.3, 2)]). Threshold = 0.00. MAE = 6.45, 150 rules\n",
- "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.3, 2)]). Threshold = 0.00. MAE = 6.45, 154 rules\n",
- "\n",
- "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.99, 3)]). Threshold = 0.00. MAE = 6.45, 157 rules\n",
- "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.99, 3)]). Threshold = 0.00. MAE = 6.45, 160 rules\n",
- "\n",
- "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.3, 3)]). Threshold = 0.00. MAE = 6.45, 169 rules\n",
- "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.3, 3)]). Threshold = 0.00. MAE = 6.45, 178 rules\n",
- "\n",
- "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.99, 5)]). Threshold = 0.00. MAE = 6.45, 183 rules\n",
- "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.99, 5)]). Threshold = 0.00. MAE = 6.45, 188 rules\n",
- "\n",
- "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.3, 5)]). Threshold = 0.00. MAE = 6.45, 209 rules\n",
- "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.3, 5)]). Threshold = 0.00. MAE = 6.45, 230 rules\n",
- "\n",
- "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.99, 10)]). Threshold = 0.00. MAE = 6.45, 240 rules\n",
- "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.99, 10)]). Threshold = 0.00. MAE = 6.45, 250 rules\n",
- "\n",
- "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.33, 2), (0.67, 3)]). Threshold = 0.00. MAE = 6.45, 256 rules\n",
- "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.33, 2), (0.67, 3)]). Threshold = 0.00. MAE = 6.45, 262 rules\n",
- "\n",
- "**********************\n",
- "Best Algorithm.GRIDEX\n",
- "**********************\n",
- "MAE = 6.45, 15 rules\n",
- "Threshold = 0.00\n",
- "Iterations = 1\n",
- "Strategy = Fixed (2)\n",
- "\n",
- "**********************\n",
- "Best MAE \n",
- "**********************\n",
- "MAE = 6.45, 256 rules\n",
- "Threshold = 0.00\n",
- "Iterations = 1\n",
- "Strategy = Adaptive ([(0.33, 2), (0.67, 3)])\n",
- "\n",
- "**********************\n",
- "Best N rules\n",
- "**********************\n",
- "MAE = 6.45, 15 rules\n",
- "Threshold = 0.00\n",
- "Iterations = 1\n",
- "Strategy = Fixed (2)\n",
- "\n",
- "GridEx performance (277 rules with 99.90% coverage):\n",
- "MAE = 6.50 (data), 6.49 (BB)\n",
- "MSE = 66.41 (data), 65.91 (BB)\n",
- "R2 = 0.77 (data), 0.77 (BB)\n",
- "\n",
- "GridEx extracted rules:\n",
- "\n",
- "'PE'(AP, AT, RH, V, 473.96) :-\n",
- " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [25.55, 62.85].\n",
- "'PE'(AP, AT, RH, V, 468.97) :-\n",
- " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 471.39) :-\n",
- " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n",
- "'PE'(AP, AT, RH, V, 472.61) :-\n",
- " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 468.07) :-\n",
- " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 470.26) :-\n",
- " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n",
- "'PE'(AP, AT, RH, V, 464.10) :-\n",
- " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 445.50) :-\n",
- " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [25.55, 62.85].\n",
- "'PE'(AP, AT, RH, V, 446.77) :-\n",
- " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 449.32) :-\n",
- " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n",
- "'PE'(AP, AT, RH, V, 447.25) :-\n",
- " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 436.54) :-\n",
- " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [992.88, 1013.07], RH in [25.55, 62.85].\n",
- "'PE'(AP, AT, RH, V, 438.05) :-\n",
- " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 441.71) :-\n",
- " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n",
- "'PE'(AP, AT, RH, V, 446.25) :-\n",
- " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 473.96) :-\n",
- " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [25.55, 62.85].\n",
- "'PE'(AP, AT, RH, V, 468.97) :-\n",
- " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 471.39) :-\n",
- " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n",
- "'PE'(AP, AT, RH, V, 472.61) :-\n",
- " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 468.07) :-\n",
- " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 470.26) :-\n",
- " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n",
- "'PE'(AP, AT, RH, V, 464.10) :-\n",
- " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 445.50) :-\n",
- " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [25.55, 62.85].\n",
- "'PE'(AP, AT, RH, V, 446.77) :-\n",
- " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 449.32) :-\n",
- " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n",
- "'PE'(AP, AT, RH, V, 447.25) :-\n",
- " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 436.54) :-\n",
- " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [992.88, 1013.07], RH in [25.55, 62.85].\n",
- "'PE'(AP, AT, RH, V, 438.05) :-\n",
- " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 441.71) :-\n",
- " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n",
- "'PE'(AP, AT, RH, V, 446.25) :-\n",
- " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 482.41) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 481.90) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 477.04) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 482.21) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 478.54) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 477.40) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 482.33) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 479.69) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 477.58) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 477.58) :-\n",
- " AT in [2.33, 13.48], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 475.51) :-\n",
- " AT in [2.33, 13.48], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 477.59) :-\n",
- " AT in [2.33, 13.48], V in [44.09, 62.82], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 477.63) :-\n",
- " AT in [2.33, 13.48], V in [44.09, 62.82], AP in [1019.79, 1033.25], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 476.84) :-\n",
- " AT in [2.33, 13.48], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 459.40) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 457.29) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 457.77) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 460.79) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 461.57) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 463.79) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 460.57) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 459.06) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 456.52) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 451.68) :-\n",
- " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 450.11) :-\n",
- " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 455.09) :-\n",
- " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 451.49) :-\n",
- " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 451.23) :-\n",
- " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 456.93) :-\n",
- " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1019.79, 1033.25], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 457.31) :-\n",
- " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 456.15) :-\n",
- " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1019.79, 1033.25], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 448.29) :-\n",
- " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 445.98) :-\n",
- " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 451.08) :-\n",
- " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 447.20) :-\n",
- " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 443.67) :-\n",
- " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 450.66) :-\n",
- " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 450.45) :-\n",
- " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [1019.79, 1033.25], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 442.79) :-\n",
- " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 443.17) :-\n",
- " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 445.23) :-\n",
- " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 437.81) :-\n",
- " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 439.21) :-\n",
- " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 443.28) :-\n",
- " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [992.88, 1006.34], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 442.04) :-\n",
- " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 443.39) :-\n",
- " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 444.45) :-\n",
- " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 442.41) :-\n",
- " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 440.86) :-\n",
- " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 435.81) :-\n",
- " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [992.88, 1006.34], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 434.24) :-\n",
- " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 434.45) :-\n",
- " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 435.93) :-\n",
- " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 436.02) :-\n",
- " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 434.65) :-\n",
- " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 436.39) :-\n",
- " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 482.41) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 481.90) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 477.04) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 482.21) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 478.54) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 477.40) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 482.33) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 479.69) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 477.58) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 477.58) :-\n",
- " AT in [2.33, 13.48], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 475.51) :-\n",
- " AT in [2.33, 13.48], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 477.59) :-\n",
- " AT in [2.33, 13.48], V in [44.09, 62.82], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 477.63) :-\n",
- " AT in [2.33, 13.48], V in [44.09, 62.82], AP in [1019.79, 1033.25], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 476.84) :-\n",
- " AT in [2.33, 13.48], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 459.40) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 457.29) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 457.77) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 460.79) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 461.57) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 463.79) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 460.57) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 459.06) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 456.52) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 451.68) :-\n",
- " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 450.11) :-\n",
- " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 455.09) :-\n",
- " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 451.49) :-\n",
- " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 451.23) :-\n",
- " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 456.93) :-\n",
- " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1019.79, 1033.25], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 457.31) :-\n",
- " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 456.15) :-\n",
- " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1019.79, 1033.25], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 448.29) :-\n",
- " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 445.98) :-\n",
- " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 451.08) :-\n",
- " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 447.20) :-\n",
- " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 443.67) :-\n",
- " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 450.66) :-\n",
- " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 450.45) :-\n",
- " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [1019.79, 1033.25], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 442.79) :-\n",
- " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 443.17) :-\n",
- " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 445.23) :-\n",
- " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 437.81) :-\n",
- " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 439.21) :-\n",
- " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 443.28) :-\n",
- " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [992.88, 1006.34], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 442.04) :-\n",
- " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 443.39) :-\n",
- " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 444.45) :-\n",
- " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 442.41) :-\n",
- " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 440.86) :-\n",
- " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 435.81) :-\n",
- " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [992.88, 1006.34], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 434.24) :-\n",
- " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 434.45) :-\n",
- " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 435.93) :-\n",
- " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 436.02) :-\n",
- " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 434.65) :-\n",
- " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 436.39) :-\n",
- " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 470.05) :-\n",
- " AT in [2.33, 19.05], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 441.29) :-\n",
- " AT in [19.05, 35.77], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 470.05) :-\n",
- " AT in [2.33, 19.05], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 441.29) :-\n",
- " AT in [19.05, 35.77], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 471.13) :-\n",
- " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 461.20) :-\n",
- " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 449.17) :-\n",
- " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 439.66) :-\n",
- " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 471.13) :-\n",
- " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 461.20) :-\n",
- " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 449.17) :-\n",
- " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 439.66) :-\n",
- " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 476.90) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 453.67) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 436.76) :-\n",
- " AT in [24.62, 35.77], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 476.90) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 453.67) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 436.76) :-\n",
- " AT in [24.62, 35.77], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 477.45) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 475.45) :-\n",
- " AT in [2.33, 13.48], V in [44.09, 62.82], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 477.45) :-\n",
- " AT in [2.33, 13.48], V in [62.82, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 463.56) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 452.52) :-\n",
- " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 444.06) :-\n",
- " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 441.94) :-\n",
- " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 442.07) :-\n",
- " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 435.18) :-\n",
- " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 477.45) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 475.45) :-\n",
- " AT in [2.33, 13.48], V in [44.09, 62.82], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 477.45) :-\n",
- " AT in [2.33, 13.48], V in [62.82, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 463.56) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 452.52) :-\n",
- " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 444.06) :-\n",
- " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 441.94) :-\n",
- " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 442.07) :-\n",
- " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 435.18) :-\n",
- " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 483.28) :-\n",
- " AT in [2.33, 9.02], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 470.58) :-\n",
- " AT in [9.02, 15.71], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 453.90) :-\n",
- " AT in [15.71, 22.39], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 440.37) :-\n",
- " AT in [22.39, 29.08], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 433.51) :-\n",
- " AT in [29.08, 35.77], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 483.28) :-\n",
- " AT in [2.33, 9.02], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 470.58) :-\n",
- " AT in [9.02, 15.71], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 453.90) :-\n",
- " AT in [15.71, 22.39], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 440.37) :-\n",
- " AT in [22.39, 29.08], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 433.51) :-\n",
- " AT in [29.08, 35.77], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 485.17) :-\n",
- " AT in [2.33, 9.02], V in [25.35, 36.59], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 483.31) :-\n",
- " AT in [2.33, 9.02], V in [36.59, 47.84], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 482.27) :-\n",
- " AT in [2.33, 9.02], V in [47.84, 59.08], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 482.21) :-\n",
- " AT in [2.33, 9.02], V in [70.32, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 472.40) :-\n",
- " AT in [9.02, 15.71], V in [25.35, 36.59], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 470.93) :-\n",
- " AT in [9.02, 15.71], V in [36.59, 47.84], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 466.36) :-\n",
- " AT in [9.02, 15.71], V in [47.84, 59.08], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 467.00) :-\n",
- " AT in [9.02, 15.71], V in [70.32, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 457.10) :-\n",
- " AT in [15.71, 22.39], V in [25.35, 36.59], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 459.41) :-\n",
- " AT in [15.71, 22.39], V in [36.59, 47.84], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 452.81) :-\n",
- " AT in [15.71, 22.39], V in [47.84, 59.08], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 448.42) :-\n",
- " AT in [15.71, 22.39], V in [59.08, 70.32], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 446.88) :-\n",
- " AT in [15.71, 22.39], V in [70.32, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 445.49) :-\n",
- " AT in [22.39, 29.08], V in [36.59, 47.84], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 444.57) :-\n",
- " AT in [22.39, 29.08], V in [47.84, 59.08], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 440.40) :-\n",
- " AT in [22.39, 29.08], V in [59.08, 70.32], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 435.49) :-\n",
- " AT in [22.39, 29.08], V in [70.32, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 440.89) :-\n",
- " AT in [29.08, 35.77], V in [36.59, 47.84], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 443.08) :-\n",
- " AT in [29.08, 35.77], V in [47.84, 59.08], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 433.92) :-\n",
- " AT in [29.08, 35.77], V in [59.08, 70.32], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 432.88) :-\n",
- " AT in [29.08, 35.77], V in [70.32, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 485.17) :-\n",
- " AT in [2.33, 9.02], V in [25.35, 36.59], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 483.31) :-\n",
- " AT in [2.33, 9.02], V in [36.59, 47.84], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 482.27) :-\n",
- " AT in [2.33, 9.02], V in [47.84, 59.08], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 482.21) :-\n",
- " AT in [2.33, 9.02], V in [70.32, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 472.40) :-\n",
- " AT in [9.02, 15.71], V in [25.35, 36.59], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 470.93) :-\n",
- " AT in [9.02, 15.71], V in [36.59, 47.84], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 466.36) :-\n",
- " AT in [9.02, 15.71], V in [47.84, 59.08], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 467.00) :-\n",
- " AT in [9.02, 15.71], V in [70.32, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 457.10) :-\n",
- " AT in [15.71, 22.39], V in [25.35, 36.59], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 459.41) :-\n",
- " AT in [15.71, 22.39], V in [36.59, 47.84], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 452.81) :-\n",
- " AT in [15.71, 22.39], V in [47.84, 59.08], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 448.42) :-\n",
- " AT in [15.71, 22.39], V in [59.08, 70.32], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 446.88) :-\n",
- " AT in [15.71, 22.39], V in [70.32, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 445.49) :-\n",
- " AT in [22.39, 29.08], V in [36.59, 47.84], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 444.57) :-\n",
- " AT in [22.39, 29.08], V in [47.84, 59.08], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 440.40) :-\n",
- " AT in [22.39, 29.08], V in [59.08, 70.32], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 435.49) :-\n",
- " AT in [22.39, 29.08], V in [70.32, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 440.89) :-\n",
- " AT in [29.08, 35.77], V in [36.59, 47.84], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 443.08) :-\n",
- " AT in [29.08, 35.77], V in [47.84, 59.08], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 433.92) :-\n",
- " AT in [29.08, 35.77], V in [59.08, 70.32], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 432.88) :-\n",
- " AT in [29.08, 35.77], V in [70.32, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 486.49) :-\n",
- " AT in [2.33, 5.68], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 482.56) :-\n",
- " AT in [5.68, 9.02], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 474.79) :-\n",
- " AT in [9.02, 12.36], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 466.96) :-\n",
- " AT in [12.36, 15.71], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 458.45) :-\n",
- " AT in [15.71, 19.05], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 450.01) :-\n",
- " AT in [19.05, 22.39], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 442.66) :-\n",
- " AT in [22.39, 25.74], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 437.65) :-\n",
- " AT in [25.74, 29.08], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 433.90) :-\n",
- " AT in [29.08, 32.42], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 436.90) :-\n",
- " AT in [32.42, 35.77], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 486.49) :-\n",
- " AT in [2.33, 5.68], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 482.56) :-\n",
- " AT in [5.68, 9.02], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 474.79) :-\n",
- " AT in [9.02, 12.36], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 466.96) :-\n",
- " AT in [12.36, 15.71], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 458.45) :-\n",
- " AT in [15.71, 19.05], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 450.01) :-\n",
- " AT in [19.05, 22.39], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 442.66) :-\n",
- " AT in [22.39, 25.74], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 437.65) :-\n",
- " AT in [25.74, 29.08], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 433.90) :-\n",
- " AT in [29.08, 32.42], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 436.90) :-\n",
- " AT in [32.42, 35.77], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 476.95) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 53.46], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 477.83) :-\n",
- " AT in [2.33, 13.48], V in [53.46, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 459.42) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 53.46], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 446.57) :-\n",
- " AT in [13.48, 24.62], V in [53.46, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 442.25) :-\n",
- " AT in [24.62, 35.77], V in [25.35, 53.46], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 436.31) :-\n",
- " AT in [24.62, 35.77], V in [53.46, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 476.95) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 53.46], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 477.83) :-\n",
- " AT in [2.33, 13.48], V in [53.46, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 459.42) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 53.46], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 446.57) :-\n",
- " AT in [13.48, 24.62], V in [53.46, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 442.25) :-\n",
- " AT in [24.62, 35.77], V in [25.35, 53.46], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 436.31) :-\n",
- " AT in [24.62, 35.77], V in [53.46, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 473.96) :-\n",
- " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [25.55, 62.85].\n",
- "'PE'(AP, AT, RH, V, 468.97) :-\n",
- " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 471.39) :-\n",
- " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n",
- "'PE'(AP, AT, RH, V, 472.61) :-\n",
- " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 468.07) :-\n",
- " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 470.26) :-\n",
- " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n",
- "'PE'(AP, AT, RH, V, 464.10) :-\n",
- " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 445.50) :-\n",
- " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [25.55, 62.85].\n",
- "'PE'(AP, AT, RH, V, 446.77) :-\n",
- " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 449.32) :-\n",
- " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n",
- "'PE'(AP, AT, RH, V, 447.25) :-\n",
- " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 436.54) :-\n",
- " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [992.88, 1013.07], RH in [25.55, 62.85].\n",
- "'PE'(AP, AT, RH, V, 438.05) :-\n",
- " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 441.71) :-\n",
- " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n",
- "'PE'(AP, AT, RH, V, 446.25) :-\n",
- " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n"
- ]
- }
- ],
- "source": [
- "pedro = PEDRO(predictor, train, max_mae_increase=1.2, min_rule_decrease=0.9, readability_tradeoff=0.1,\n",
- " max_depth=1, patience=1, algorithm=PEDRO.Algorithm.GRIDEX, objective=Objective.MODEL)\n",
- "pedro.search()\n",
- "(_, _, threshold, grid) = pedro.get_best()[0]\n",
- "\n",
- "gridEx = Extractor.gridex(predictor, grid, threshold=threshold)\n",
- "theory_from_gridEx = gridEx.extract(train)\n",
- "scores, completeness = get_scores(gridEx, test, predictor)\n",
- "print(f'GridEx performance ({gridEx.n_rules} rules with {completeness * 100:.2f}% coverage):')\n",
- "print_scores(scores)\n",
- "print('\\nGridEx extracted rules:\\n\\n' + pretty_theory(theory_from_gridEx))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 12,
- "metadata": {
- "collapsed": false,
- "pycharm": {
- "name": "#%%\n"
- }
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "**********************\n",
- "Best Algorithm.GRIDEX\n",
- "**********************\n",
- "MAE = 6.45, 15 rules\n",
- "Threshold = 0.00\n",
- "Iterations = 1\n",
- "Strategy = Fixed (2)\n",
- "\n",
- "**********************\n",
- "Best MAE \n",
- "**********************\n",
- "MAE = 6.45, 256 rules\n",
- "Threshold = 0.00\n",
- "Iterations = 1\n",
- "Strategy = Adaptive ([(0.33, 2), (0.67, 3)])\n",
- "\n",
- "**********************\n",
- "Best N rules\n",
- "**********************\n",
- "MAE = 6.45, 15 rules\n",
- "Threshold = 0.00\n",
- "Iterations = 1\n",
- "Strategy = Fixed (2)\n",
- "\n",
- "GridREx performance (292 rules with 99.90% coverage):\n",
- "MAE = 6.50 (data), 6.49 (BB)\n",
- "MSE = 66.41 (data), 65.91 (BB)\n",
- "R2 = 0.77 (data), 0.77 (BB)\n",
- "GridREx extracted rules:\n",
- "\n",
- "'PE'(AP, AT, RH, V, 473.96) :-\n",
- " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [25.55, 62.85].\n",
- "'PE'(AP, AT, RH, V, 468.97) :-\n",
- " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 471.39) :-\n",
- " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n",
- "'PE'(AP, AT, RH, V, 472.61) :-\n",
- " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 468.07) :-\n",
- " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 470.26) :-\n",
- " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n",
- "'PE'(AP, AT, RH, V, 464.10) :-\n",
- " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 445.50) :-\n",
- " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [25.55, 62.85].\n",
- "'PE'(AP, AT, RH, V, 446.77) :-\n",
- " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 449.32) :-\n",
- " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n",
- "'PE'(AP, AT, RH, V, 447.25) :-\n",
- " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 436.54) :-\n",
- " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [992.88, 1013.07], RH in [25.55, 62.85].\n",
- "'PE'(AP, AT, RH, V, 438.05) :-\n",
- " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 441.71) :-\n",
- " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n",
- "'PE'(AP, AT, RH, V, 446.25) :-\n",
- " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 473.96) :-\n",
- " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [25.55, 62.85].\n",
- "'PE'(AP, AT, RH, V, 468.97) :-\n",
- " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 471.39) :-\n",
- " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n",
- "'PE'(AP, AT, RH, V, 472.61) :-\n",
- " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 468.07) :-\n",
- " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 470.26) :-\n",
- " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n",
- "'PE'(AP, AT, RH, V, 464.10) :-\n",
- " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 445.50) :-\n",
- " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [25.55, 62.85].\n",
- "'PE'(AP, AT, RH, V, 446.77) :-\n",
- " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 449.32) :-\n",
- " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n",
- "'PE'(AP, AT, RH, V, 447.25) :-\n",
- " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 436.54) :-\n",
- " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [992.88, 1013.07], RH in [25.55, 62.85].\n",
- "'PE'(AP, AT, RH, V, 438.05) :-\n",
- " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 441.71) :-\n",
- " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n",
- "'PE'(AP, AT, RH, V, 446.25) :-\n",
- " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 482.41) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 481.90) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 477.04) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 482.21) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 478.54) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 477.40) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 482.33) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 479.69) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 477.58) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 477.58) :-\n",
- " AT in [2.33, 13.48], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 475.51) :-\n",
- " AT in [2.33, 13.48], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 477.59) :-\n",
- " AT in [2.33, 13.48], V in [44.09, 62.82], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 477.63) :-\n",
- " AT in [2.33, 13.48], V in [44.09, 62.82], AP in [1019.79, 1033.25], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 476.84) :-\n",
- " AT in [2.33, 13.48], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 459.40) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 457.29) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 457.77) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 460.79) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 461.57) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 463.79) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 460.57) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 459.06) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 456.52) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 451.68) :-\n",
- " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 450.11) :-\n",
- " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 455.09) :-\n",
- " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 451.49) :-\n",
- " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 451.23) :-\n",
- " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 456.93) :-\n",
- " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1019.79, 1033.25], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 457.31) :-\n",
- " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 456.15) :-\n",
- " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1019.79, 1033.25], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 448.29) :-\n",
- " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 445.98) :-\n",
- " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 451.08) :-\n",
- " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 447.20) :-\n",
- " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 443.67) :-\n",
- " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 450.66) :-\n",
- " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 450.45) :-\n",
- " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [1019.79, 1033.25], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 442.79) :-\n",
- " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 443.17) :-\n",
- " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 445.23) :-\n",
- " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 437.81) :-\n",
- " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 439.21) :-\n",
- " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 443.28) :-\n",
- " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [992.88, 1006.34], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 442.04) :-\n",
- " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 443.39) :-\n",
- " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 444.45) :-\n",
- " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 442.41) :-\n",
- " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 440.86) :-\n",
- " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 435.81) :-\n",
- " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [992.88, 1006.34], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 434.24) :-\n",
- " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 434.45) :-\n",
- " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 435.93) :-\n",
- " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 436.02) :-\n",
- " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 434.65) :-\n",
- " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 436.39) :-\n",
- " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 482.41) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 481.90) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 477.04) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 482.21) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 478.54) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 477.40) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 482.33) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 479.69) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 477.58) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 477.58) :-\n",
- " AT in [2.33, 13.48], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 475.51) :-\n",
- " AT in [2.33, 13.48], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 477.59) :-\n",
- " AT in [2.33, 13.48], V in [44.09, 62.82], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 477.63) :-\n",
- " AT in [2.33, 13.48], V in [44.09, 62.82], AP in [1019.79, 1033.25], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 476.84) :-\n",
- " AT in [2.33, 13.48], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 459.40) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 457.29) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 457.77) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 460.79) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 461.57) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 463.79) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 460.57) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 459.06) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 456.52) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [1019.79, 1033.25], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 451.68) :-\n",
- " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 450.11) :-\n",
- " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 455.09) :-\n",
- " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 451.49) :-\n",
- " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 451.23) :-\n",
- " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 456.93) :-\n",
- " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1019.79, 1033.25], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 457.31) :-\n",
- " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 456.15) :-\n",
- " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [1019.79, 1033.25], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 448.29) :-\n",
- " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 445.98) :-\n",
- " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 451.08) :-\n",
- " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 447.20) :-\n",
- " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 443.67) :-\n",
- " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 450.66) :-\n",
- " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 450.45) :-\n",
- " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [1019.79, 1033.25], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 442.79) :-\n",
- " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 443.17) :-\n",
- " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 445.23) :-\n",
- " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 437.81) :-\n",
- " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 439.21) :-\n",
- " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 443.28) :-\n",
- " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [992.88, 1006.34], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 442.04) :-\n",
- " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 443.39) :-\n",
- " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 444.45) :-\n",
- " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 442.41) :-\n",
- " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 440.86) :-\n",
- " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 435.81) :-\n",
- " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [992.88, 1006.34], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 434.24) :-\n",
- " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [992.88, 1006.34], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 434.45) :-\n",
- " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [992.88, 1006.34], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 435.93) :-\n",
- " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [25.55, 50.42].\n",
- "'PE'(AP, AT, RH, V, 436.02) :-\n",
- " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 434.65) :-\n",
- " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [1006.34, 1019.79], RH in [75.28, 100.15].\n",
- "'PE'(AP, AT, RH, V, 436.39) :-\n",
- " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [1019.79, 1033.25], RH in [50.42, 75.28].\n",
- "'PE'(AP, AT, RH, V, 470.05) :-\n",
- " AT in [2.33, 19.05], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 441.29) :-\n",
- " AT in [19.05, 35.77], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 470.05) :-\n",
- " AT in [2.33, 19.05], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 441.29) :-\n",
- " AT in [19.05, 35.77], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 471.13) :-\n",
- " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 461.20) :-\n",
- " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 449.17) :-\n",
- " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 439.66) :-\n",
- " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 471.13) :-\n",
- " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 461.20) :-\n",
- " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 449.17) :-\n",
- " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 439.66) :-\n",
- " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 476.90) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 453.67) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 436.76) :-\n",
- " AT in [24.62, 35.77], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 476.90) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 453.67) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 436.76) :-\n",
- " AT in [24.62, 35.77], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 477.45) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 475.45) :-\n",
- " AT in [2.33, 13.48], V in [44.09, 62.82], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 477.45) :-\n",
- " AT in [2.33, 13.48], V in [62.82, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 463.56) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 452.52) :-\n",
- " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 444.06) :-\n",
- " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 441.94) :-\n",
- " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 442.07) :-\n",
- " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 435.18) :-\n",
- " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 477.45) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 44.09], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 475.45) :-\n",
- " AT in [2.33, 13.48], V in [44.09, 62.82], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 477.45) :-\n",
- " AT in [2.33, 13.48], V in [62.82, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 463.56) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 44.09], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 452.52) :-\n",
- " AT in [13.48, 24.62], V in [44.09, 62.82], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 444.06) :-\n",
- " AT in [13.48, 24.62], V in [62.82, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 441.94) :-\n",
- " AT in [24.62, 35.77], V in [25.35, 44.09], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 442.07) :-\n",
- " AT in [24.62, 35.77], V in [44.09, 62.82], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 435.18) :-\n",
- " AT in [24.62, 35.77], V in [62.82, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 483.28) :-\n",
- " AT in [2.33, 9.02], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 470.58) :-\n",
- " AT in [9.02, 15.71], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 453.90) :-\n",
- " AT in [15.71, 22.39], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 440.37) :-\n",
- " AT in [22.39, 29.08], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 433.51) :-\n",
- " AT in [29.08, 35.77], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 483.28) :-\n",
- " AT in [2.33, 9.02], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 470.58) :-\n",
- " AT in [9.02, 15.71], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 453.90) :-\n",
- " AT in [15.71, 22.39], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 440.37) :-\n",
- " AT in [22.39, 29.08], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 433.51) :-\n",
- " AT in [29.08, 35.77], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 485.17) :-\n",
- " AT in [2.33, 9.02], V in [25.35, 36.59], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 483.31) :-\n",
- " AT in [2.33, 9.02], V in [36.59, 47.84], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 482.27) :-\n",
- " AT in [2.33, 9.02], V in [47.84, 59.08], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 482.21) :-\n",
- " AT in [2.33, 9.02], V in [70.32, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 472.40) :-\n",
- " AT in [9.02, 15.71], V in [25.35, 36.59], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 470.93) :-\n",
- " AT in [9.02, 15.71], V in [36.59, 47.84], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 466.36) :-\n",
- " AT in [9.02, 15.71], V in [47.84, 59.08], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 467.00) :-\n",
- " AT in [9.02, 15.71], V in [70.32, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 457.10) :-\n",
- " AT in [15.71, 22.39], V in [25.35, 36.59], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 459.41) :-\n",
- " AT in [15.71, 22.39], V in [36.59, 47.84], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 452.81) :-\n",
- " AT in [15.71, 22.39], V in [47.84, 59.08], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 448.42) :-\n",
- " AT in [15.71, 22.39], V in [59.08, 70.32], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 446.88) :-\n",
- " AT in [15.71, 22.39], V in [70.32, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 445.49) :-\n",
- " AT in [22.39, 29.08], V in [36.59, 47.84], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 444.57) :-\n",
- " AT in [22.39, 29.08], V in [47.84, 59.08], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 440.40) :-\n",
- " AT in [22.39, 29.08], V in [59.08, 70.32], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 435.49) :-\n",
- " AT in [22.39, 29.08], V in [70.32, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 440.89) :-\n",
- " AT in [29.08, 35.77], V in [36.59, 47.84], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 443.08) :-\n",
- " AT in [29.08, 35.77], V in [47.84, 59.08], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 433.92) :-\n",
- " AT in [29.08, 35.77], V in [59.08, 70.32], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 432.88) :-\n",
- " AT in [29.08, 35.77], V in [70.32, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 485.17) :-\n",
- " AT in [2.33, 9.02], V in [25.35, 36.59], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 483.31) :-\n",
- " AT in [2.33, 9.02], V in [36.59, 47.84], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 482.27) :-\n",
- " AT in [2.33, 9.02], V in [47.84, 59.08], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 482.21) :-\n",
- " AT in [2.33, 9.02], V in [70.32, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 472.40) :-\n",
- " AT in [9.02, 15.71], V in [25.35, 36.59], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 470.93) :-\n",
- " AT in [9.02, 15.71], V in [36.59, 47.84], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 466.36) :-\n",
- " AT in [9.02, 15.71], V in [47.84, 59.08], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 467.00) :-\n",
- " AT in [9.02, 15.71], V in [70.32, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 457.10) :-\n",
- " AT in [15.71, 22.39], V in [25.35, 36.59], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 459.41) :-\n",
- " AT in [15.71, 22.39], V in [36.59, 47.84], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 452.81) :-\n",
- " AT in [15.71, 22.39], V in [47.84, 59.08], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 448.42) :-\n",
- " AT in [15.71, 22.39], V in [59.08, 70.32], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 446.88) :-\n",
- " AT in [15.71, 22.39], V in [70.32, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 445.49) :-\n",
- " AT in [22.39, 29.08], V in [36.59, 47.84], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 444.57) :-\n",
- " AT in [22.39, 29.08], V in [47.84, 59.08], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 440.40) :-\n",
- " AT in [22.39, 29.08], V in [59.08, 70.32], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 435.49) :-\n",
- " AT in [22.39, 29.08], V in [70.32, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 440.89) :-\n",
- " AT in [29.08, 35.77], V in [36.59, 47.84], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 443.08) :-\n",
- " AT in [29.08, 35.77], V in [47.84, 59.08], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 433.92) :-\n",
- " AT in [29.08, 35.77], V in [59.08, 70.32], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 432.88) :-\n",
- " AT in [29.08, 35.77], V in [70.32, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 486.49) :-\n",
- " AT in [2.33, 5.68], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 482.56) :-\n",
- " AT in [5.68, 9.02], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 474.79) :-\n",
- " AT in [9.02, 12.36], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 466.96) :-\n",
- " AT in [12.36, 15.71], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 458.45) :-\n",
- " AT in [15.71, 19.05], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 450.01) :-\n",
- " AT in [19.05, 22.39], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 442.66) :-\n",
- " AT in [22.39, 25.74], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 437.65) :-\n",
- " AT in [25.74, 29.08], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 433.90) :-\n",
- " AT in [29.08, 32.42], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 436.90) :-\n",
- " AT in [32.42, 35.77], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 486.49) :-\n",
- " AT in [2.33, 5.68], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 482.56) :-\n",
- " AT in [5.68, 9.02], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 474.79) :-\n",
- " AT in [9.02, 12.36], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 466.96) :-\n",
- " AT in [12.36, 15.71], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 458.45) :-\n",
- " AT in [15.71, 19.05], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 450.01) :-\n",
- " AT in [19.05, 22.39], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 442.66) :-\n",
- " AT in [22.39, 25.74], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 437.65) :-\n",
- " AT in [25.74, 29.08], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 433.90) :-\n",
- " AT in [29.08, 32.42], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 436.90) :-\n",
- " AT in [32.42, 35.77], V in [25.35, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 476.95) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 53.46], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 477.83) :-\n",
- " AT in [2.33, 13.48], V in [53.46, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 459.42) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 53.46], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 446.57) :-\n",
- " AT in [13.48, 24.62], V in [53.46, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 442.25) :-\n",
- " AT in [24.62, 35.77], V in [25.35, 53.46], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 436.31) :-\n",
- " AT in [24.62, 35.77], V in [53.46, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 476.95) :-\n",
- " AT in [2.33, 13.48], V in [25.35, 53.46], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 477.83) :-\n",
- " AT in [2.33, 13.48], V in [53.46, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 459.42) :-\n",
- " AT in [13.48, 24.62], V in [25.35, 53.46], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 446.57) :-\n",
- " AT in [13.48, 24.62], V in [53.46, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 442.25) :-\n",
- " AT in [24.62, 35.77], V in [25.35, 53.46], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 436.31) :-\n",
- " AT in [24.62, 35.77], V in [53.46, 81.56], AP in [992.88, 1033.25], RH in [25.55, 100.15].\n",
- "'PE'(AP, AT, RH, V, 473.96) :-\n",
- " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [25.55, 62.85].\n",
- "'PE'(AP, AT, RH, V, 468.97) :-\n",
- " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 471.39) :-\n",
- " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n",
- "'PE'(AP, AT, RH, V, 472.61) :-\n",
- " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 468.07) :-\n",
- " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 470.26) :-\n",
- " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n",
- "'PE'(AP, AT, RH, V, 464.10) :-\n",
- " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 445.50) :-\n",
- " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [25.55, 62.85].\n",
- "'PE'(AP, AT, RH, V, 446.77) :-\n",
- " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 449.32) :-\n",
- " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n",
- "'PE'(AP, AT, RH, V, 447.25) :-\n",
- " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 436.54) :-\n",
- " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [992.88, 1013.07], RH in [25.55, 62.85].\n",
- "'PE'(AP, AT, RH, V, 438.05) :-\n",
- " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [992.88, 1013.07], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, 441.71) :-\n",
- " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [25.55, 62.85].\n",
- "'PE'(AP, AT, RH, V, 446.25) :-\n",
- " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [62.85, 100.15].\n",
- "'PE'(AP, AT, RH, V, PE) :-\n",
- " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [25.55, 62.85], PE is 462.71 - 2.15 * AP - 0.22 * AT + 0.04 * RH - 0.02 * V.\n",
- "'PE'(AP, AT, RH, V, PE) :-\n",
- " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [62.85, 100.15], PE is 431.79 - 2.16 * AP - 0.45 * AT + 0.08 * RH - 0.06 * V.\n",
- "'PE'(AP, AT, RH, V, PE) :-\n",
- " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [25.55, 62.85], PE is 495.74 - 1.80 * AP - 0.07 * AT + 0.00 * RH - 0.01 * V.\n",
- "'PE'(AP, AT, RH, V, PE) :-\n",
- " AT in [2.33, 19.05], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [62.85, 100.15], PE is 703.70 - 2.37 * AP - 0.12 * AT - 0.18 * RH - 0.11 * V.\n",
- "'PE'(AP, AT, RH, V, PE) :-\n",
- " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [992.88, 1013.07], RH in [62.85, 100.15], PE is 540.25 - 2.54 * AP - 0.04 * AT - 0.04 * RH + 0.03 * V.\n",
- "'PE'(AP, AT, RH, V, PE) :-\n",
- " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [25.55, 62.85], PE is 556.66 - 2.35 * AP - 0.04 * AT - 0.05 * RH + 0.05 * V.\n",
- "'PE'(AP, AT, RH, V, PE) :-\n",
- " AT in [2.33, 19.05], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [62.85, 100.15], PE is 453.81 - 2.40 * AP - 0.18 * AT + 0.05 * RH - 0.04 * V.\n",
- "'PE'(AP, AT, RH, V, PE) :-\n",
- " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [25.55, 62.85], PE is 495.08 - 1.30 * AP - 0.20 * AT - 0.00 * RH - 0.10 * V.\n",
- "'PE'(AP, AT, RH, V, PE) :-\n",
- " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [992.88, 1013.07], RH in [62.85, 100.15], PE is 394.31 - 1.06 * AP - 0.32 * AT + 0.09 * RH - 0.01 * V.\n",
- "'PE'(AP, AT, RH, V, PE) :-\n",
- " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [25.55, 62.85], PE is 625.50 - 1.14 * AP + 0.09 * AT - 0.13 * RH - 0.27 * V.\n",
- "'PE'(AP, AT, RH, V, PE) :-\n",
- " AT in [19.05, 35.77], V in [25.35, 53.46], AP in [1013.07, 1033.25], RH in [62.85, 100.15], PE is 699.87 - 1.10 * AP + 0.06 * AT - 0.21 * RH - 0.05 * V.\n",
- "'PE'(AP, AT, RH, V, PE) :-\n",
- " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [992.88, 1013.07], RH in [25.55, 62.85], PE is 106.52 - 1.12 * AP - 0.21 * AT + 0.37 * RH - 0.04 * V.\n",
- "'PE'(AP, AT, RH, V, PE) :-\n",
- " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [992.88, 1013.07], RH in [62.85, 100.15], PE is 180.91 - 1.23 * AP - 0.29 * AT + 0.31 * RH - 0.09 * V.\n",
- "'PE'(AP, AT, RH, V, PE) :-\n",
- " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [25.55, 62.85], PE is 396.75 - 1.41 * AP - 0.28 * AT + 0.10 * RH - 0.01 * V.\n",
- "'PE'(AP, AT, RH, V, PE) :-\n",
- " AT in [19.05, 35.77], V in [53.46, 81.56], AP in [1013.07, 1033.25], RH in [62.85, 100.15], PE is 446.80 - 1.76 * AP - 0.30 * AT + 0.07 * RH - 0.22 * V.\n"
- ]
- }
- ],
- "source": [
- "#pedro = PEDRO(predictor, train, max_mae_increase=1.2, min_rule_decrease=0.9, readability_tradeoff=0.1,\n",
- "# max_depth=2, patience=1, algorithm=PEDRO.Algorithm.GRIDREX, objective=Objective.MODEL)\n",
- "#pedro.search()\n",
- "(_, _, threshold, grid) = pedro.get_best()[0]\n",
- "\n",
- "gridREx = Extractor.gridrex(predictor, grid, threshold=threshold)\n",
- "theory_from_gridREx = gridREx.extract(train)\n",
- "scores, completeness = get_scores(gridREx, test, predictor)\n",
- "print(f'GridREx performance ({gridREx.n_rules} rules with {completeness * 100:.2f}% coverage):')\n",
- "print_scores(scores)\n",
- "print('GridREx extracted rules:\\n\\n' + pretty_theory(theory_from_gridREx))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 13,
- "metadata": {
- "collapsed": false,
- "pycharm": {
- "name": "#%%\n"
- }
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "CART performance (6 rules with 100.00% coverage):\n",
- "MAE = 4.46 (data), 4.49 (BB)\n",
- "MSE = 32.55 (data), 32.53 (BB)\n",
- "R2 = 0.89 (data), 0.89 (BB)\n",
- "CART extracted rules:\n",
- "\n",
- "'PE'(AP, AT, RH, V, 479.15) :-\n",
- " AT =< 18.25, AT =< 11.90.\n",
- "'PE'(AP, AT, RH, V, 435.66) :-\n",
- " AT > 18.25, V > 66.20.\n",
- "'PE'(AP, AT, RH, V, 451.33) :-\n",
- " AT > 18.25, V =< 66.20, AT =< 22.89.\n",
- "'PE'(AP, AT, RH, V, 443.00) :-\n",
- " AT > 18.25, V =< 66.20, AT > 22.89.\n",
- "'PE'(AP, AT, RH, V, 467.45) :-\n",
- " AT > 11.90, AT =< 15.64.\n",
- "'PE'(AP, AT, RH, V, 459.70) :-\n",
- " AT > 15.64.\n"
- ]
- }
- ],
- "source": [
- "cart = Extractor.cart(predictor, max_depth=5, max_leaves=6, simplify=True)\n",
- "theory_from_cart = cart.extract(train)\n",
- "scores, completeness = get_scores(cart, test, predictor)\n",
- "print(f'CART performance ({cart.n_rules} rules with {completeness * 100:.2f}% coverage):')\n",
- "print_scores(scores)\n",
- "print('CART extracted rules:\\n\\n' + pretty_theory(theory_from_cart))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 13,
- "outputs": [],
- "source": [],
- "metadata": {
- "collapsed": false,
- "pycharm": {
- "name": "#%%\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.9.7"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 5
-}
\ No newline at end of file
diff --git a/demo/DemoRegressionScaled.ipynb b/demo/DemoRegressionScaled.ipynb
index b57fab34..133d3e91 100644
--- a/demo/DemoRegressionScaled.ipynb
+++ b/demo/DemoRegressionScaled.ipynb
@@ -1,15 +1,5 @@
{
"cells": [
- {
- "cell_type": "markdown",
- "id": "f52126f3",
- "metadata": {},
- "source": [
- "# PSyKE's demo for regression tasks\n",
- "\n",
- "Some imports."
- ]
- },
{
"cell_type": "code",
"execution_count": 1,
@@ -17,976 +7,399 @@
"metadata": {},
"outputs": [],
"source": [
- "from psyke import Extractor, Clustering\n",
- "from psyke.tuning.pedro import PEDRO\n",
- "from psyke.tuning import Objective\n",
- "from psyke.tuning.crash import CRASH\n",
- "from sklearn.tree import DecisionTreeRegressor\n",
- "from psyke.utils.logic import pretty_theory\n",
- "from psyke.utils.metrics import mae, mse, r2\n",
- "from sklearn.model_selection import train_test_split\n",
+ "from sklearn.neighbors import KNeighborsRegressor as KNN\n",
"from sklearn.preprocessing import StandardScaler\n",
- "from psyke.utils import Target\n",
- "import pandas as pd"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "d7c90ed2",
- "metadata": {
- "pycharm": {
- "name": "#%% md\n"
- }
- },
- "source": [
- "Import an artificial dataset."
+ "\n",
+ "from joblib import dump, load\n",
+ "import pandas as pd\n",
+ "import numpy as np\n",
+ "\n",
+ "from psyke import Extractor, Clustering, Target\n",
+ "from psyke.extraction.hypercubic.strategy import AdaptiveStrategy\n",
+ "from psyke.extraction.hypercubic import Grid, FeatureRanker\n",
+ "from psyke.utils.logic import pretty_theory\n",
+ "\n",
+ "from plot import *"
]
},
{
"cell_type": "code",
"execution_count": 2,
- "id": "f8e46c49",
- "metadata": {},
"outputs": [],
"source": [
- "#dataset = pd.read_csv(\"../test/resources/datasets/df.csv\")\n",
- "#dataset = dataset[[\"X\", \"Y\", \"Z4\"]].dropna()\n",
- "#dataset = pd.read_csv(\"../test/resources/datasets/CCPP.csv\", sep=\";\", decimal=\",\")\n",
- "dataset = pd.read_csv(\"../test/resources/datasets/arti.csv\")"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "d673b766",
- "metadata": {},
- "source": [
- "Split between train and test set in a reproducible way."
- ]
+ "def plot(testB, x, pred, extracted):\n",
+ " missing = pd.read_csv(\"data/missing.csv\", parse_dates = [0], index_col = 0)\n",
+ " df = pd.read_csv(\"data/averaged1.csv\", parse_dates = [0], index_col = 0)\n",
+ " df.LPFnorm[missing.index] = np.nan\n",
+ "\n",
+ " for i, b in bartels.iterrows():\n",
+ " if b.n != testB:\n",
+ " continue\n",
+ " xminmax = [b.t0, b.t1]\n",
+ "\n",
+ " f, axes = plt.subplots(3, figsize=(10, 8)) # l x h\n",
+ "\n",
+ " myplot(axes[0], [3, 1], \"LPF\", df.index, df.LPFnorm, xminmax)\n",
+ " myplot(axes[0], [3, 1], \"\", missing.index, missing.LPF0, xminmax, color='r', marker='*', lw=0, size=10)\n",
+ " myplot(axes[1], [3, 2], \"V\", df.index, df.V, xminmax)\n",
+ " myplot(axes[1], [3, 2], \"\", x, pred, xminmax, color='b', marker='.', lw=0)\n",
+ " myplot(axes[1], [3, 2], \"\", x, extracted, xminmax, color='r', marker='.', lw=0)\n",
+ " myplot(axes[2], [3, 3], \"B\", df.index, df.B, xminmax)\n",
+ " plt.subplots_adjust(hspace=0.6)\n",
+ " plt.savefig(f\"plot/{b.n}.jpg\", dpi=96 * 2)\n",
+ " plt.show()"
+ ],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%%\n"
+ }
+ }
},
{
"cell_type": "code",
- "execution_count": 3,
- "id": "03fc5e2c",
- "metadata": {},
+ "execution_count": 5,
"outputs": [],
"source": [
- "train, test = train_test_split(dataset, test_size=0.5, random_state=10)\n",
+ "def splitTest(data):\n",
+ " b = bartels[(bartels.n == 2490)]\n",
+ " data = data[(data.index >= b.t1.values[0])]\n",
"\n",
- "scaler = StandardScaler().fit(train)\n",
- "train = pd.DataFrame(scaler.transform(train), columns=train.columns, index=train.index)\n",
- "test = pd.DataFrame(scaler.transform(test), columns=test.columns, index=test.index)\n",
+ " b = bartels[(bartels.n == 2494) | (bartels.n == 2495)]\n",
+ " idx = np.zeros_like(data.index, dtype='bool')\n",
+ " for _, row in b.iterrows():\n",
+ " t0, t1 = row.t0, row.t1\n",
+ " idx = idx | (data.index >= t0) & (data.index < t1)\n",
+ " return data[~idx], data[idx]\n",
"\n",
- "normalization = {key: (m, s) for key, m, s in zip(train.columns, scaler.mean_, scaler.scale_)}"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "fa6754a0",
- "metadata": {},
- "source": [
- "We select and train a predictor."
- ]
+ "bartels = pd.read_csv(\"data/bartels.csv\", parse_dates = [1, 2])\n",
+ "data = pd.read_csv(f'data/halffuzzycoefs4B3.csv', parse_dates=[0], index_col=0)\n",
+ "train, test = splitTest(data)\n",
+ "train.to_csv('data/alltrain.csv')\n",
+ "test.to_csv('data/alltest.csv')\n",
+ "\n",
+ "data = pd.read_csv(f'data/pruned.csv', parse_dates=[0], index_col=0)\n",
+ "train, test = splitTest(data)\n",
+ "train.to_csv('data/prunedtrain.csv')\n",
+ "test.to_csv('data/prunedtest.csv')"
+ ],
+ "metadata": {
+ "collapsed": false,
+ "pycharm": {
+ "name": "#%%\n"
+ }
+ }
},
{
"cell_type": "code",
- "execution_count": 4,
- "id": "bed764ca",
- "metadata": {},
+ "execution_count": 73,
"outputs": [
{
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "MAE = 0.00\n",
- "MSE = 0.00\n",
- "R2 = 1.00\n"
- ]
+ "data": {
+ "text/plain": " Bmin Bmedian Bmax Btrend Bhalf1 Bhalf2 \\\n2016-03-04 00:00:00 4.0 7.5 12.3 -0.080751 0.009474 -0.106862 \n2016-03-04 01:00:00 4.0 7.5 12.3 -0.086067 -0.012065 -0.101174 \n2016-03-04 02:00:00 4.0 7.5 12.3 -0.090328 -0.029534 -0.094717 \n2016-03-04 03:00:00 4.0 7.5 12.3 -0.094527 -0.046781 -0.089474 \n2016-03-04 04:00:00 4.0 7.5 12.3 -0.098312 -0.062166 -0.087105 \n... ... ... ... ... ... ... \n2017-07-02 19:00:00 1.6 8.0 18.2 0.168533 0.139028 0.004049 \n2017-07-02 20:00:00 1.6 8.3 18.2 0.165550 0.157085 -0.019089 \n2017-07-02 21:00:00 1.6 8.3 18.2 0.161067 0.174393 -0.041862 \n2017-07-02 22:00:00 1.6 8.5 18.2 0.156652 0.188077 -0.061781 \n2017-07-02 23:00:00 1.6 8.5 18.2 0.151061 0.198158 -0.086761 \n\n Bthird1 Bthird2 Bthird3 GCRmin ... GCRhalf1 \\\n2016-03-04 00:00:00 -0.001462 -0.016066 -0.068720 -3.883201 ... -0.034045 \n2016-03-04 01:00:00 -0.004731 -0.012913 -0.074356 -3.883201 ... -0.035872 \n2016-03-04 02:00:00 -0.007107 -0.008399 -0.080310 -3.883201 ... -0.038517 \n2016-03-04 03:00:00 -0.010202 -0.001853 -0.085397 -3.883201 ... -0.040322 \n2016-03-04 04:00:00 -0.012979 0.006375 -0.089585 -3.883201 ... -0.042501 \n... ... ... ... ... ... ... \n2017-07-02 19:00:00 -0.032341 0.005700 0.162350 -4.670171 ... -0.059403 \n2017-07-02 20:00:00 -0.032566 0.005048 0.159932 -4.670171 ... -0.058878 \n2017-07-02 21:00:00 -0.033405 0.002897 0.157075 -4.670171 ... -0.058062 \n2017-07-02 22:00:00 -0.033445 0.001775 0.153994 -4.670171 ... -0.057460 \n2017-07-02 23:00:00 -0.033619 0.001199 0.149502 -4.670171 ... -0.056252 \n\n GCRhalf2 GCRthird1 GCRthird2 GCRthird3 GCRfourth1 \\\n2016-03-04 00:00:00 0.060357 0.002682 -0.072897 0.065471 0.007162 \n2016-03-04 01:00:00 0.061504 0.000701 -0.070397 0.064501 0.006544 \n2016-03-04 02:00:00 0.062143 -0.002516 -0.066904 0.064396 0.004833 \n2016-03-04 03:00:00 0.063626 -0.002422 -0.062109 0.066305 0.004309 \n2016-03-04 04:00:00 0.064246 -0.005347 -0.056971 0.065904 0.002981 \n... ... ... ... ... ... \n2017-07-02 19:00:00 0.016938 -0.075540 0.018295 -0.025042 -0.074034 \n2017-07-02 20:00:00 0.015490 -0.076592 0.020250 -0.027076 -0.076765 \n2017-07-02 21:00:00 0.014373 -0.076522 0.022473 -0.028479 -0.079294 \n2017-07-02 22:00:00 0.013574 -0.077431 0.025158 -0.029432 -0.080745 \n2017-07-02 23:00:00 0.012860 -0.077216 0.027493 -0.031331 -0.082300 \n\n GCRfourth2 GCRfourth3 GCRfourth4 V \n2016-03-04 00:00:00 -0.092158 0.046471 0.069499 410.0 \n2016-03-04 01:00:00 -0.095190 0.049612 0.069178 400.0 \n2016-03-04 02:00:00 -0.098934 0.049670 0.071374 395.0 \n2016-03-04 03:00:00 -0.102389 0.052382 0.072217 408.0 \n2016-03-04 04:00:00 -0.105296 0.052220 0.070273 406.0 \n... ... ... ... ... \n2017-07-02 19:00:00 -0.027912 0.071203 -0.054068 477.0 \n2017-07-02 20:00:00 -0.026023 0.071905 -0.053493 442.0 \n2017-07-02 21:00:00 -0.022508 0.073575 -0.054818 437.0 \n2017-07-02 22:00:00 -0.020645 0.074790 -0.054839 436.0 \n2017-07-02 23:00:00 -0.017545 0.074579 -0.054656 430.0 \n\n[9720 rows x 23 columns]",
+ "text/html": "\n\n
\n \n \n | \n Bmin | \n Bmedian | \n Bmax | \n Btrend | \n Bhalf1 | \n Bhalf2 | \n Bthird1 | \n Bthird2 | \n Bthird3 | \n GCRmin | \n ... | \n GCRhalf1 | \n GCRhalf2 | \n GCRthird1 | \n GCRthird2 | \n GCRthird3 | \n GCRfourth1 | \n GCRfourth2 | \n GCRfourth3 | \n GCRfourth4 | \n V | \n
\n \n \n \n 2016-03-04 00:00:00 | \n 4.0 | \n 7.5 | \n 12.3 | \n -0.080751 | \n 0.009474 | \n -0.106862 | \n -0.001462 | \n -0.016066 | \n -0.068720 | \n -3.883201 | \n ... | \n -0.034045 | \n 0.060357 | \n 0.002682 | \n -0.072897 | \n 0.065471 | \n 0.007162 | \n -0.092158 | \n 0.046471 | \n 0.069499 | \n 410.0 | \n
\n \n 2016-03-04 01:00:00 | \n 4.0 | \n 7.5 | \n 12.3 | \n -0.086067 | \n -0.012065 | \n -0.101174 | \n -0.004731 | \n -0.012913 | \n -0.074356 | \n -3.883201 | \n ... | \n -0.035872 | \n 0.061504 | \n 0.000701 | \n -0.070397 | \n 0.064501 | \n 0.006544 | \n -0.095190 | \n 0.049612 | \n 0.069178 | \n 400.0 | \n
\n \n 2016-03-04 02:00:00 | \n 4.0 | \n 7.5 | \n 12.3 | \n -0.090328 | \n -0.029534 | \n -0.094717 | \n -0.007107 | \n -0.008399 | \n -0.080310 | \n -3.883201 | \n ... | \n -0.038517 | \n 0.062143 | \n -0.002516 | \n -0.066904 | \n 0.064396 | \n 0.004833 | \n -0.098934 | \n 0.049670 | \n 0.071374 | \n 395.0 | \n
\n \n 2016-03-04 03:00:00 | \n 4.0 | \n 7.5 | \n 12.3 | \n -0.094527 | \n -0.046781 | \n -0.089474 | \n -0.010202 | \n -0.001853 | \n -0.085397 | \n -3.883201 | \n ... | \n -0.040322 | \n 0.063626 | \n -0.002422 | \n -0.062109 | \n 0.066305 | \n 0.004309 | \n -0.102389 | \n 0.052382 | \n 0.072217 | \n 408.0 | \n
\n \n 2016-03-04 04:00:00 | \n 4.0 | \n 7.5 | \n 12.3 | \n -0.098312 | \n -0.062166 | \n -0.087105 | \n -0.012979 | \n 0.006375 | \n -0.089585 | \n -3.883201 | \n ... | \n -0.042501 | \n 0.064246 | \n -0.005347 | \n -0.056971 | \n 0.065904 | \n 0.002981 | \n -0.105296 | \n 0.052220 | \n 0.070273 | \n 406.0 | \n
\n \n ... | \n ... | \n ... | \n ... | \n ... | \n ... | \n ... | \n ... | \n ... | \n ... | \n ... | \n ... | \n ... | \n ... | \n ... | \n ... | \n ... | \n ... | \n ... | \n ... | \n ... | \n ... | \n
\n \n 2017-07-02 19:00:00 | \n 1.6 | \n 8.0 | \n 18.2 | \n 0.168533 | \n 0.139028 | \n 0.004049 | \n -0.032341 | \n 0.005700 | \n 0.162350 | \n -4.670171 | \n ... | \n -0.059403 | \n 0.016938 | \n -0.075540 | \n 0.018295 | \n -0.025042 | \n -0.074034 | \n -0.027912 | \n 0.071203 | \n -0.054068 | \n 477.0 | \n
\n \n 2017-07-02 20:00:00 | \n 1.6 | \n 8.3 | \n 18.2 | \n 0.165550 | \n 0.157085 | \n -0.019089 | \n -0.032566 | \n 0.005048 | \n 0.159932 | \n -4.670171 | \n ... | \n -0.058878 | \n 0.015490 | \n -0.076592 | \n 0.020250 | \n -0.027076 | \n -0.076765 | \n -0.026023 | \n 0.071905 | \n -0.053493 | \n 442.0 | \n
\n \n 2017-07-02 21:00:00 | \n 1.6 | \n 8.3 | \n 18.2 | \n 0.161067 | \n 0.174393 | \n -0.041862 | \n -0.033405 | \n 0.002897 | \n 0.157075 | \n -4.670171 | \n ... | \n -0.058062 | \n 0.014373 | \n -0.076522 | \n 0.022473 | \n -0.028479 | \n -0.079294 | \n -0.022508 | \n 0.073575 | \n -0.054818 | \n 437.0 | \n
\n \n 2017-07-02 22:00:00 | \n 1.6 | \n 8.5 | \n 18.2 | \n 0.156652 | \n 0.188077 | \n -0.061781 | \n -0.033445 | \n 0.001775 | \n 0.153994 | \n -4.670171 | \n ... | \n -0.057460 | \n 0.013574 | \n -0.077431 | \n 0.025158 | \n -0.029432 | \n -0.080745 | \n -0.020645 | \n 0.074790 | \n -0.054839 | \n 436.0 | \n
\n \n 2017-07-02 23:00:00 | \n 1.6 | \n 8.5 | \n 18.2 | \n 0.151061 | \n 0.198158 | \n -0.086761 | \n -0.033619 | \n 0.001199 | \n 0.149502 | \n -4.670171 | \n ... | \n -0.056252 | \n 0.012860 | \n -0.077216 | \n 0.027493 | \n -0.031331 | \n -0.082300 | \n -0.017545 | \n 0.074579 | \n -0.054656 | \n 430.0 | \n
\n \n
\n
9720 rows × 23 columns
\n
"
+ },
+ "execution_count": 73,
+ "metadata": {},
+ "output_type": "execute_result"
}
],
"source": [
- "#predictor = KNeighborsRegressor(n_neighbors=3).fit(train.iloc[:, :-1], train.iloc[:, -1])\n",
- "predictor = DecisionTreeRegressor().fit(train.iloc[:, :-1], train.iloc[:, -1])\n",
- "#predictor = LinearRegression().fit(train.iloc[:, :-1], train.iloc[:, -1])\n",
- "\n",
- "m, s = normalization[test.columns[-1]]\n",
- "\n",
- "predicted = predictor.predict(test.iloc[:, :-1]).flatten() * s + m\n",
- "true = test.iloc[:, -1] * s + m\n",
- "\n",
- "print(f'MAE = {mae(true, predicted):.2f}')\n",
- "print(f'MSE = {mse(true, predicted):.2f}')\n",
- "print(f'R2 = {r2(true, predicted):.2f}')"
- ]
- },
- {
- "cell_type": "markdown",
+ "pd.read_csv('data/alltrain.csv', parse_dates=[0], index_col=[0])"
+ ],
"metadata": {
"collapsed": false,
"pycharm": {
- "name": "#%% md\n"
+ "name": "#%%\n"
}
- },
- "source": [
- "We define a function to print the extractors’ evaluation"
- ]
+ }
},
{
"cell_type": "code",
- "execution_count": 5,
+ "execution_count": 3,
+ "outputs": [],
+ "source": [
+ "def getTrainTest(data, testB):\n",
+ " b = bartels[bartels.n==testB]\n",
+ " t0, t1 = b.t0.values[0], b.t1.values[0]\n",
+ " idx = (data.index >= t0) & (data.index < t1)\n",
+ " return data[~idx], data[idx]\n",
+ "\n",
+ "def getScaler(train, name):\n",
+ " scaler = StandardScaler().fit(train)\n",
+ " dump(scaler, f\"scalers/scalerV{name}.joblib\")\n",
+ " normalization = {key: (m, s) for key, m, s in zip(train.columns, scaler.mean_, scaler.scale_)}\n",
+ " return scaler, pd.DataFrame(scaler.transform(train), columns=train.columns), normalization"
+ ],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%%\n"
}
- },
- "outputs": [],
- "source": [
- "def evaluate(name, extractor, true, predicted):\n",
- " extracted = extractor.unscale(extractor.predict(test.iloc[:, :-1]), test.columns[-1])\n",
- " print(f'{name} performance ({extractor.n_rules} rules):\\n'\n",
- " f'MAE = {mae(true, extracted):.2f}\\nMAE fidelity = {mae(predicted, extracted):.2f}\\n'\n",
- " f'R2 = {r2(true, extracted):.2f}\\nR2 fidelity = {r2(predicted, extracted):.2f}\\n')"
- ]
- },
- {
- "cell_type": "markdown",
- "id": "96835867",
- "metadata": {},
- "source": [
- "We create several extractors that use ITER, GridEx and GridREx algorithms to extract prolog rules from the predictor."
- ]
+ }
},
{
"cell_type": "code",
- "execution_count": 6,
+ "execution_count": 4,
+ "outputs": [],
+ "source": [
+ "def gridex(model, train, test, normalization):\n",
+ " ranked = FeatureRanker(train.columns).fit(model, train.iloc[:, :-1]).rankings()\n",
+ " gridEx = Extractor.gridex(model, Grid(1, AdaptiveStrategy(ranked, [(0.6, 3), (0.75, 4)])),\n",
+ " threshold=.5, min_examples=1, normalization=normalization)\n",
+ " gridEx.extract(train)\n",
+ " return gridEx.brute_predict(test), gridEx.n_rules, sum([p is None for p in gridEx.predict(test)])\n",
+ " \n",
+ "def gridrex(model, train, test, normalization):\n",
+ " ranked = FeatureRanker(train.columns).fit(model, train.iloc[:, :-1]).rankings()\n",
+ " gridREx = Extractor.gridrex(model, Grid(1, AdaptiveStrategy(ranked, [(0.5, 3)])),\n",
+ " threshold=.5, min_examples=1, normalization=normalization)\n",
+ " gridREx.extract(train)\n",
+ " return gridREx.brute_predict(test, 'default'), gridREx.n_rules, sum([p is None for p in gridREx.predict(test)])\n",
+ "\n",
+ "def cart(model, train, test, normalization):\n",
+ " CART = Extractor.cart(model, max_depth=10, max_leaves=10, normalization=normalization)\n",
+ " CART.extract(train)\n",
+ " return CART.predict(test), CART.n_rules, sum([p is None for p in CART.predict(test)])\n",
+ "\n",
+ "def cosmik(model, train, test, normalization):\n",
+ " COSMiK = Extractor.cosmik(model, max_components=4, k=125, patience=12, close_to_center=True,\n",
+ " output=Target.REGRESSION, normalization=normalization)\n",
+ " COSMiK.extract(train)\n",
+ " return COSMiK.brute_predict(test, 'default'), COSMiK.n_rules, sum([p is None for p in COSMiK.predict(test)])\n",
+ "\n",
+ "def cream(model, train, test, normalization):\n",
+ " CReEPy = Extractor.creepy(model, clustering=Clustering.cream, depth=5, error_threshold=.5, gauss_components=10,\n",
+ " output=Target.REGRESSION, normalization=normalization)\n",
+ " CReEPy.extract(train)\n",
+ " return CReEPy.brute_predict(test), CReEPy.n_rules, sum([p is None for p in CReEPy.predict(test)])\n",
+ "\n",
+ "def exact(model, train, test, normalization):\n",
+ " CReEPy = Extractor.creepy(model, clustering=Clustering.exact, depth=5, error_threshold=.5, gauss_components=10,\n",
+ " output=Target.REGRESSION, normalization=normalization)\n",
+ " CReEPy.extract(train)\n",
+ " return CReEPy.brute_predict(test), CReEPy.n_rules, sum([p is None for p in CReEPy.predict(test)])"
+ ],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%%\n"
}
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "ITER performance (9 rules):\n",
- "MAE = 0.04\n",
- "MAE fidelity = 0.04\n",
- "R2 = 0.88\n",
- "R2 fidelity = 0.88\n",
- "\n",
- "ITER extracted rules:\n",
- "\n",
- "z(X, Y, 0.7) :-\n",
- " X in [0.00, 0.46], Y in [0.00, 0.43].\n",
- "z(X, Y, 0.59) :-\n",
- " X in [0.00, 0.46], Y in [0.43, 0.53].\n",
- "z(X, Y, 0.4) :-\n",
- " X in [0.00, 0.46], Y in [0.53, 0.99].\n",
- "z(X, Y, 0.47) :-\n",
- " X in [0.46, 0.56], Y in [0.00, 0.43].\n",
- "z(X, Y, 0.3) :-\n",
- " X in [0.56, 0.99], Y in [0.00, 0.43].\n",
- "z(X, Y, 0.18) :-\n",
- " X in [0.46, 0.56], Y in [0.53, 0.99].\n",
- "z(X, Y, 0.0) :-\n",
- " X in [0.56, 0.99], Y in [0.53, 0.99].\n",
- "z(X, Y, 0.32) :-\n",
- " X in [0.46, 0.56], Y in [0.43, 0.53].\n",
- "z(X, Y, 0.20) :-\n",
- " X in [0.56, 0.99], Y in [0.43, 0.53].\n"
- ]
- }
- ],
- "source": [
- "it = Extractor.iter(predictor, min_update=1.0 / 10, n_points=1, max_iterations=600,\n",
- " min_examples=100, threshold=.4, normalization=normalization)\n",
- "theory_from_iter = it.extract(train)\n",
- "evaluate('ITER', it, true, predicted)\n",
- "print('ITER extracted rules:\\n\\n' + pretty_theory(theory_from_iter))"
- ]
+ }
},
{
"cell_type": "code",
"execution_count": 7,
- "metadata": {
- "collapsed": false,
- "pycharm": {
- "name": "#%%\n"
- }
- },
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
- "CReEPy performance (3 rules):\n",
- "MAE = 0.08\n",
- "MAE fidelity = 0.08\n",
- "R2 = 0.81\n",
- "R2 fidelity = 0.81\n",
- "\n",
- "CReEPy extracted rules:\n",
- "\n",
- "z(X, Y, 0.7) :-\n",
- " X in [0.00, 0.49], Y in [0.00, 0.49].\n",
- "z(X, Y, 0.4) :-\n",
- " X in [0.00, 0.49], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.145238).\n"
+ "2491\n",
+ "GridEx\n",
+ "GridREx\n",
+ "CART\n",
+ "COSMiK\n",
+ "ExACT\n",
+ "CREAM\n",
+ "2492\n",
+ "GridEx\n",
+ "GridREx\n",
+ "CART\n",
+ "COSMiK\n",
+ "ExACT\n",
+ "CREAM\n",
+ "2493\n",
+ "GridEx\n",
+ "GridREx\n",
+ "CART\n",
+ "COSMiK\n",
+ "ExACT\n",
+ "CREAM\n"
]
}
],
"source": [
- "creepy = Extractor.creepy(predictor, depth=3, error_threshold=0.02, output=Target.CONSTANT,\n",
- " normalization=normalization, clustering=Clustering.exact)\n",
- "theory_from_creepy = creepy.extract(train)\n",
- "evaluate('CReEPy', creepy, true, predicted)\n",
- "print('CReEPy extracted rules:\\n\\n' + pretty_theory(theory_from_creepy))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 8,
+ "bartels = pd.read_csv(\"data/bartels.csv\", parse_dates = [1, 2])\n",
+ "\n",
+ "extractors = ['GridEx', 'GridREx', 'CART', 'COSMiK', 'ExACT', 'CREAM']\n",
+ "\n",
+ "TESTB = [i for i in range(2491, 2509)]\n",
+ "\n",
+ "predicted = {name: [] for name in ['index', 'V', 'model'] + extractors}\n",
+ "\n",
+ "rules = {name: [] for name in ['BR'] + extractors}\n",
+ "\n",
+ "missed = {name: [] for name in ['BR'] + extractors}\n",
+ "\n",
+ "for testB in TESTB[:3]:\n",
+ " rules['BR'].append(testB)\n",
+ " missed['BR'].append(testB)\n",
+ " print(testB)\n",
+ "\n",
+ " data = pd.read_csv(f'data/pruned.csv', parse_dates=[0], index_col=0)\n",
+ " train, test = getTrainTest(data, testB)\n",
+ "\n",
+ " predicted['index'] += list(test.index.values)\n",
+ " predicted['V'] += list(test.V.values)\n",
+ "\n",
+ " scaler, scaledTrain, normalization = getScaler(train, f\"test{testB}\")\n",
+ " scaledTest = pd.DataFrame(scaler.transform(test), columns=test.columns).iloc[:, :-1]\n",
+ " m, s = normalization[test.columns[-1]]\n",
+ "\n",
+ " model = KNN(200, weights='distance', p=1).fit(scaledTrain.iloc[:, :-1], scaledTrain.iloc[:, -1])\n",
+ " #dump(model, f\"models/RF/{k}_{name}_{testB}.joblib\")\n",
+ " predicted['model'] += list(model.predict(scaledTest) * s + m)\n",
+ "\n",
+ " for name, fun in zip(extractors, [cart, cart, cart, cosmik, exact, cream]):\n",
+ " print(name)\n",
+ " #if name in ['GridREx', 'CART', 'COSMiK']:\n",
+ " # continue\n",
+ " pred, n, miss = fun(model, scaledTrain, scaledTest, normalization)\n",
+ " predicted[name] += list(pred)\n",
+ " rules[name].append(n)\n",
+ " missed[name].append(miss)"
+ ],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%%\n"
}
- },
+ }
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
- "CReEPy performance (3 rules):\n",
- "MAE = 0.03\n",
- "MAE fidelity = 0.03\n",
- "R2 = 0.94\n",
- "R2 fidelity = 0.94\n",
- "\n",
- "CReEPy extracted rules:\n",
- "\n",
- "z(X, Y, Z) :-\n",
- " X in [0.00, 0.49], Y in [0.00, 0.49], Z is 0.7.\n",
- "z(X, Y, Z) :-\n",
- " X in [0.00, 0.49], Y in [0.00, 0.99], Z is 0.4.\n",
- "z(X, Y, Z) :-\n",
- " Y in [0.00, 0.99], Z is 0.38 - 0.09 * X - 1.73 * Y.\n"
+ "90.20644923758856 47.26039351140736\n",
+ "90.20644923758856 47.26039351140736\n",
+ "90.20644923758856 47.26039351140736\n",
+ "73.38650661174208 31.857409982273143\n",
+ "71.27591988138312 36.1748132343631\n",
+ "70.26005494494277 33.783890819165826\n"
]
+ },
+ {
+ "data": {
+ "text/plain": " BR GridEx GridREx CART COSMiK ExACT CREAM\n0 2491 10 10 10 4 6 6\n1 2492 10 10 10 8 6 6\n2 2493 10 10 10 9 6 7",
+ "text/html": "\n\n
\n \n \n | \n BR | \n GridEx | \n GridREx | \n CART | \n COSMiK | \n ExACT | \n CREAM | \n
\n \n \n \n 0 | \n 2491 | \n 10 | \n 10 | \n 10 | \n 4 | \n 6 | \n 6 | \n
\n \n 1 | \n 2492 | \n 10 | \n 10 | \n 10 | \n 8 | \n 6 | \n 6 | \n
\n \n 2 | \n 2493 | \n 10 | \n 10 | \n 10 | \n 9 | \n 6 | \n 7 | \n
\n \n
\n
"
+ },
+ "execution_count": 15,
+ "metadata": {},
+ "output_type": "execute_result"
}
],
"source": [
- "creepy = Extractor.creepy(predictor, depth=3, error_threshold=0.02, output=Target.REGRESSION,\n",
- " normalization=normalization, clustering=Clustering.exact)\n",
- "theory_from_creepy = creepy.extract(train)\n",
- "evaluate('CReEPy', creepy, true, predicted)\n",
- "print('CReEPy extracted rules:\\n\\n' + pretty_theory(theory_from_creepy))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 9,
+ "p = pd.DataFrame(predicted)\n",
+ "for e in extractors:\n",
+ " print(abs(p.V - p[e]).mean(), abs(p.model - p[e]).mean())\n",
+ "\n",
+ "b = 2493\n",
+ "#plot(b, p['index'], p.model, p.COSMiK)\n",
+ "#plot(b, p['index'], p.model, p.ExACT)\n",
+ "#plot(b, p['index'], p.model, p.CREAM)\n",
+ "\n",
+ "pd.DataFrame(rules)"
+ ],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%%\n"
}
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "CReEPy performance (4 rules):\n",
- "MAE = 0.01\n",
- "MAE fidelity = 0.01\n",
- "R2 = 0.94\n",
- "R2 fidelity = 0.94\n",
- "\n",
- "CReEPy extracted rules:\n",
- "\n",
- "z(X, Y, Z) :-\n",
- " X in [0.51, 0.99], Y in [0.00, 0.49], Z is 0.3.\n",
- "z(X, Y, Z) :-\n",
- " X in [0.50, 0.99], Y in [0.00, 0.98], Z is 0.0.\n",
- "z(X, Y, Z) :-\n",
- " X in [0.00, 0.49], Y in [0.50, 0.99], Z is 0.4.\n",
- "z(X, Y, Z) :-\n",
- " Y in [0.00, 0.99], Z is 0.7.\n"
- ]
- }
- ],
- "source": [
- "creepy = Extractor.creepy(predictor, depth=2, error_threshold=0.02, output=Target.REGRESSION,\n",
- " normalization=normalization, clustering=Clustering.cream)\n",
- "theory_from_creepy = creepy.extract(train)\n",
- "evaluate('CReEPy', creepy, true, predicted)\n",
- "print('CReEPy extracted rules:\\n\\n' + pretty_theory(theory_from_creepy))"
- ]
+ }
},
{
"cell_type": "code",
- "execution_count": 10,
+ "execution_count": null,
+ "outputs": [],
+ "source": [
+ "pd.DataFrame(predicted).to_csv(\"results/pred1.csv\")\n",
+ "pd.DataFrame(rules).to_csv('results/rules1.csv')\n",
+ "pd.DataFrame(missed).to_csv('results/missed1.csv')"
+ ],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%%\n"
}
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Algorithm.ExACT. Depth: 1. Threshold = 0.00. MAE = 0.06, 2 rules\n",
- "Algorithm.ExACT. Depth: 1. Threshold = 0.00. MAE = 0.06, 2 rules\n",
- "\n",
- "Algorithm.ExACT. Depth: 2. Threshold = 0.00. MAE = 0.06, 2 rules\n",
- "Algorithm.ExACT. Depth: 2. Threshold = 0.00. MAE = 0.06, 2 rules\n",
- "\n",
- "**********************\n",
- "Best Algorithm.ExACT\n",
- "**********************\n",
- "MAE = 0.06, 2 rules\n",
- "Threshold = 0.00\n",
- "Depth = 2\n",
- "\n",
- "**********************\n",
- "Best MAE \n",
- "**********************\n",
- "MAE = 0.06, 2 rules\n",
- "Threshold = 0.00\n",
- "Depth = 2\n",
- "\n",
- "**********************\n",
- "Best N rules\n",
- "**********************\n",
- "MAE = 0.06, 2 rules\n",
- "Threshold = 0.00\n",
- "Depth = 2\n",
- "\n",
- "CReEPy performance (3 rules):\n",
- "MAE = 0.69\n",
- "MAE fidelity = 0.69\n",
- "R2 = -8.82\n",
- "R2 fidelity = -8.82\n",
- "\n",
- "CReEPy extracted rules:\n",
- "\n",
- "z(X, Y, Z) :-\n",
- " X in [-1.70, 0.01], Y in [-1.69, 0.02], Z is 1.37.\n",
- "z(X, Y, Z) :-\n",
- " X in [-1.70, 0.01], Y in [-1.69, 1.75], Z is 0.19.\n",
- "z(X, Y, Z) :-\n",
- " Y in [-1.69, 1.75], Z is -0.76 - 0.02 * X - 0.50 * Y.\n"
- ]
- }
- ],
- "source": [
- "crash = CRASH(predictor, train, max_depth=3, patience=1, readability_tradeoff=.5,\n",
- " algorithm=CRASH.Algorithm.ExACT, output=Target.REGRESSION, normalization=normalization)\n",
- "crash.search()\n",
- "(_, _, depth, threshold) = crash.get_best()[0]\n",
- "\n",
- "creepy = Extractor.creepy(predictor, depth=depth, error_threshold=threshold, output=Target.REGRESSION,\n",
- " clustering=Clustering.exact)\n",
- "theory_from_creepy = creepy.extract(train)\n",
- "evaluate('CReEPy', creepy, true, predicted)\n",
- "print('CReEPy extracted rules:\\n\\n' + pretty_theory(theory_from_creepy))"
- ]
+ }
},
{
"cell_type": "code",
- "execution_count": 11,
+ "execution_count": null,
+ "outputs": [],
+ "source": [],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%%\n"
}
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Algorithm.CREAM. Depth: 1. Threshold = 0.00. MAE = 0.12, 2 rules\n",
- "Algorithm.CREAM. Depth: 1. Threshold = 0.00. MAE = 0.12, 2 rules\n",
- "\n",
- "Algorithm.CREAM. Depth: 2. Threshold = 0.00. MAE = 0.02, 3 rules\n",
- "Algorithm.CREAM. Depth: 2. Threshold = 0.00. MAE = 0.02, 3 rules\n",
- "\n",
- "**********************\n",
- "Best Algorithm.CREAM\n",
- "**********************\n",
- "MAE = 0.02, 3 rules\n",
- "Threshold = 0.00\n",
- "Depth = 2\n",
- "\n",
- "**********************\n",
- "Best MAE \n",
- "**********************\n",
- "MAE = 0.02, 3 rules\n",
- "Threshold = 0.00\n",
- "Depth = 2\n",
- "\n",
- "**********************\n",
- "Best N rules\n",
- "**********************\n",
- "MAE = 0.12, 2 rules\n",
- "Threshold = 0.00\n",
- "Depth = 1\n",
- "\n",
- "CReEPy performance (4 rules):\n",
- "MAE = 0.69\n",
- "MAE fidelity = 0.69\n",
- "R2 = -9.40\n",
- "R2 fidelity = -9.40\n",
- "\n",
- "CReEPy extracted rules:\n",
- "\n",
- "z(X, Y, Z) :-\n",
- " X in [0.07, 1.75], Y in [-1.69, 0.00], Z is -0.19.\n",
- "z(X, Y, Z) :-\n",
- " X in [0.02, 1.75], Y in [-1.69, 1.71], Z is -1.37.\n",
- "z(X, Y, Z) :-\n",
- " X in [-1.69, 0.01], Y in [0.03, 1.75], Z is 0.19.\n",
- "z(X, Y, Z) :-\n",
- " Y in [-1.69, 1.75], Z is 1.37.\n"
- ]
- }
- ],
- "source": [
- "crash = CRASH(predictor, train, max_depth=3, patience=1, readability_tradeoff=.75, algorithm=CRASH.Algorithm.CREAM,\n",
- " normalization=normalization)\n",
- "crash.search()\n",
- "(_, _, depth, threshold) = crash.get_best()[0]\n",
- "\n",
- "creepy = Extractor.creepy(predictor, depth=depth, error_threshold=threshold, output=Target.REGRESSION,\n",
- " clustering=Clustering.cream)\n",
- "theory_from_creepy = creepy.extract(train)\n",
- "evaluate('CReEPy', creepy, true, predicted)\n",
- "print('CReEPy extracted rules:\\n\\n' + pretty_theory(theory_from_creepy))"
- ]
+ }
},
{
"cell_type": "code",
- "execution_count": 12,
+ "execution_count": null,
+ "outputs": [],
+ "source": [
+ "[\n",
+ " ('half2', 1.0),\n",
+ " ('Bmin', 0.9014926374248455),\n",
+ " ('Bmedian', 0.5931779258652916),\n",
+ " ('Bmax', 0.5580664110760513),\n",
+ "\n",
+ " ('trend', 0.441328536097858),\n",
+ " ('max', 0.19391808653199277),\n",
+ " ('median', 0.16157357528452515),\n",
+ "\n",
+ " ('halfB2', 0.06672545822303622),\n",
+ " ('min', 0.042323799412967836),\n",
+ " ('B', 0.014457395044254808),\n",
+ " ('halfB1', 0.005159557201584083),\n",
+ " ('half1', 0.0023286124765232786),\n",
+ "]"
+ ],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%%\n"
}
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Algorithm.GRIDEX. Grid (1). Fixed (2). Threshold = 0.00. MAE = 0.00, 4 rules\n",
- "Algorithm.GRIDEX. Grid (1). Fixed (2). Threshold = 0.00. MAE = 0.00, 8 rules\n",
- "\n",
- "Algorithm.GRIDEX. Grid (1). Fixed (3). Threshold = 0.00. MAE = 0.00, 17 rules\n",
- "Algorithm.GRIDEX. Grid (1). Fixed (3). Threshold = 0.00. MAE = 0.00, 26 rules\n",
- "\n",
- "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.99, 2)]). Threshold = 0.00. MAE = 0.00, 28 rules\n",
- "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.99, 2)]). Threshold = 0.00. MAE = 0.00, 30 rules\n",
- "\n",
- "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.99, 3)]). Threshold = 0.00. MAE = 0.00, 33 rules\n",
- "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.99, 3)]). Threshold = 0.00. MAE = 0.00, 36 rules\n",
- "\n",
- "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.99, 5)]). Threshold = 0.00. MAE = 0.00, 41 rules\n",
- "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.99, 5)]). Threshold = 0.00. MAE = 0.00, 46 rules\n",
- "\n",
- "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.99, 10)]). Threshold = 0.00. MAE = 0.00, 56 rules\n",
- "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.99, 10)]). Threshold = 0.00. MAE = 0.00, 66 rules\n",
- "\n",
- "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.33, 2), (0.67, 3)]). Threshold = 0.00. MAE = 0.00, 72 rules\n",
- "Algorithm.GRIDEX. Grid (1). Adaptive ([(0.33, 2), (0.67, 3)]). Threshold = 0.00. MAE = 0.00, 78 rules\n",
- "\n",
- "**********************\n",
- "Best Algorithm.GRIDEX\n",
- "**********************\n",
- "MAE = 0.00, 4 rules\n",
- "Threshold = 0.00\n",
- "Iterations = 1\n",
- "Strategy = Fixed (2)\n",
- "\n",
- "**********************\n",
- "Best MAE \n",
- "**********************\n",
- "MAE = 0.00, 72 rules\n",
- "Threshold = 0.00\n",
- "Iterations = 1\n",
- "Strategy = Adaptive ([(0.33, 2), (0.67, 3)])\n",
- "\n",
- "**********************\n",
- "Best N rules\n",
- "**********************\n",
- "MAE = 0.00, 4 rules\n",
- "Threshold = 0.00\n",
- "Iterations = 1\n",
- "Strategy = Fixed (2)\n",
- "\n",
- "GridEx performance (82 rules):\n",
- "MAE = 0.00\n",
- "MAE fidelity = 0.00\n",
- "R2 = 0.99\n",
- "R2 fidelity = 0.99\n",
- "\n",
- "GridEx extracted rules:\n",
- "\n",
- "z(X, Y, 0.7) :-\n",
- " X in [0.00, 0.50], Y in [0.00, 0.49].\n",
- "z(X, Y, 0.39) :-\n",
- " X in [0.00, 0.50], Y in [0.49, 0.99].\n",
- "z(X, Y, 0.3) :-\n",
- " X in [0.50, 0.99], Y in [0.00, 0.49].\n",
- "z(X, Y, 0.0) :-\n",
- " X in [0.50, 0.99], Y in [0.49, 0.99].\n",
- "z(X, Y, 0.7) :-\n",
- " X in [0.00, 0.50], Y in [0.00, 0.49].\n",
- "z(X, Y, 0.39) :-\n",
- " X in [0.00, 0.50], Y in [0.49, 0.99].\n",
- "z(X, Y, 0.3) :-\n",
- " X in [0.50, 0.99], Y in [0.00, 0.49].\n",
- "z(X, Y, 0.0) :-\n",
- " X in [0.50, 0.99], Y in [0.49, 0.99].\n",
- "z(X, Y, 0.7) :-\n",
- " X in [0.00, 0.33], Y in [0.00, 0.33].\n",
- "z(X, Y, 0.54) :-\n",
- " X in [0.00, 0.33], Y in [0.33, 0.66].\n",
- "z(X, Y, 0.4) :-\n",
- " X in [0.00, 0.33], Y in [0.66, 0.99].\n",
- "z(X, Y, 0.48) :-\n",
- " X in [0.33, 0.66], Y in [0.00, 0.33].\n",
- "z(X, Y, 0.37) :-\n",
- " X in [0.33, 0.66], Y in [0.33, 0.66].\n",
- "z(X, Y, 0.17) :-\n",
- " X in [0.33, 0.66], Y in [0.66, 0.99].\n",
- "z(X, Y, 0.3) :-\n",
- " X in [0.66, 0.99], Y in [0.00, 0.33].\n",
- "z(X, Y, 0.14) :-\n",
- " X in [0.66, 0.99], Y in [0.33, 0.66].\n",
- "z(X, Y, 0.0) :-\n",
- " X in [0.66, 0.99], Y in [0.66, 0.99].\n",
- "z(X, Y, 0.7) :-\n",
- " X in [0.00, 0.33], Y in [0.00, 0.33].\n",
- "z(X, Y, 0.54) :-\n",
- " X in [0.00, 0.33], Y in [0.33, 0.66].\n",
- "z(X, Y, 0.4) :-\n",
- " X in [0.00, 0.33], Y in [0.66, 0.99].\n",
- "z(X, Y, 0.48) :-\n",
- " X in [0.33, 0.66], Y in [0.00, 0.33].\n",
- "z(X, Y, 0.37) :-\n",
- " X in [0.33, 0.66], Y in [0.33, 0.66].\n",
- "z(X, Y, 0.17) :-\n",
- " X in [0.33, 0.66], Y in [0.66, 0.99].\n",
- "z(X, Y, 0.3) :-\n",
- " X in [0.66, 0.99], Y in [0.00, 0.33].\n",
- "z(X, Y, 0.14) :-\n",
- " X in [0.66, 0.99], Y in [0.33, 0.66].\n",
- "z(X, Y, 0.0) :-\n",
- " X in [0.66, 0.99], Y in [0.66, 0.99].\n",
- "z(X, Y, 0.55) :-\n",
- " X in [0.00, 0.50], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.14) :-\n",
- " X in [0.50, 0.99], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.55) :-\n",
- " X in [0.00, 0.50], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.14) :-\n",
- " X in [0.50, 0.99], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.55) :-\n",
- " X in [0.00, 0.33], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.35) :-\n",
- " X in [0.33, 0.66], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.14) :-\n",
- " X in [0.66, 0.99], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.55) :-\n",
- " X in [0.00, 0.33], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.35) :-\n",
- " X in [0.33, 0.66], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.14) :-\n",
- " X in [0.66, 0.99], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.56) :-\n",
- " X in [0.00, 0.20], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.55) :-\n",
- " X in [0.20, 0.40], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.37) :-\n",
- " X in [0.40, 0.60], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.14) :-\n",
- " X in [0.60, 0.80], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.14) :-\n",
- " X in [0.80, 0.99], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.56) :-\n",
- " X in [0.00, 0.20], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.55) :-\n",
- " X in [0.20, 0.40], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.37) :-\n",
- " X in [0.40, 0.60], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.14) :-\n",
- " X in [0.60, 0.80], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.14) :-\n",
- " X in [0.80, 0.99], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.56) :-\n",
- " X in [0.00, 0.10], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.54) :-\n",
- " X in [0.10, 0.20], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.54) :-\n",
- " X in [0.20, 0.30], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.55) :-\n",
- " X in [0.30, 0.40], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.55) :-\n",
- " X in [0.40, 0.50], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.15) :-\n",
- " X in [0.50, 0.60], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.15) :-\n",
- " X in [0.60, 0.70], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.13) :-\n",
- " X in [0.70, 0.80], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.14) :-\n",
- " X in [0.80, 0.89], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.14) :-\n",
- " X in [0.89, 0.99], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.56) :-\n",
- " X in [0.00, 0.10], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.54) :-\n",
- " X in [0.10, 0.20], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.54) :-\n",
- " X in [0.20, 0.30], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.55) :-\n",
- " X in [0.30, 0.40], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.55) :-\n",
- " X in [0.40, 0.50], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.15) :-\n",
- " X in [0.50, 0.60], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.15) :-\n",
- " X in [0.60, 0.70], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.13) :-\n",
- " X in [0.70, 0.80], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.14) :-\n",
- " X in [0.80, 0.89], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.14) :-\n",
- " X in [0.89, 0.99], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.7) :-\n",
- " X in [0.00, 0.33], Y in [0.00, 0.49].\n",
- "z(X, Y, 0.4) :-\n",
- " X in [0.00, 0.33], Y in [0.49, 0.99].\n",
- "z(X, Y, 0.52) :-\n",
- " X in [0.33, 0.66], Y in [0.00, 0.49].\n",
- "z(X, Y, 0.17) :-\n",
- " X in [0.33, 0.66], Y in [0.49, 0.99].\n",
- "z(X, Y, 0.29) :-\n",
- " X in [0.66, 0.99], Y in [0.00, 0.49].\n",
- "z(X, Y, 0.0) :-\n",
- " X in [0.66, 0.99], Y in [0.49, 0.99].\n",
- "z(X, Y, 0.7) :-\n",
- " X in [0.00, 0.33], Y in [0.00, 0.49].\n",
- "z(X, Y, 0.4) :-\n",
- " X in [0.00, 0.33], Y in [0.49, 0.99].\n",
- "z(X, Y, 0.52) :-\n",
- " X in [0.33, 0.66], Y in [0.00, 0.49].\n",
- "z(X, Y, 0.17) :-\n",
- " X in [0.33, 0.66], Y in [0.49, 0.99].\n",
- "z(X, Y, 0.29) :-\n",
- " X in [0.66, 0.99], Y in [0.00, 0.49].\n",
- "z(X, Y, 0.0) :-\n",
- " X in [0.66, 0.99], Y in [0.49, 0.99].\n",
- "z(X, Y, 0.7) :-\n",
- " X in [0.00, 0.50], Y in [0.00, 0.49].\n",
- "z(X, Y, 0.39) :-\n",
- " X in [0.00, 0.50], Y in [0.49, 0.99].\n",
- "z(X, Y, 0.3) :-\n",
- " X in [0.50, 0.99], Y in [0.00, 0.49].\n",
- "z(X, Y, 0.0) :-\n",
- " X in [0.50, 0.99], Y in [0.49, 0.99].\n"
- ]
- }
- ],
- "source": [
- "pedro = PEDRO(predictor, train, max_mae_increase=1.2, min_rule_decrease=0.9, readability_tradeoff=0.1,\n",
- " max_depth=1, patience=1, algorithm=PEDRO.Algorithm.GRIDEX, objective=Objective.MODEL,\n",
- " normalization=normalization)\n",
- "pedro.search()\n",
- "(_, _, threshold, grid) = pedro.get_best()[0]\n",
- "\n",
- "gridEx = Extractor.gridex(predictor, grid, threshold=threshold, normalization=normalization)\n",
- "theory_from_gridEx = gridEx.extract(train)\n",
- "evaluate('GridEx', gridEx, true, predicted)\n",
- "print('GridEx extracted rules:\\n\\n' + pretty_theory(theory_from_gridEx))"
- ]
+ }
},
{
"cell_type": "code",
- "execution_count": 13,
+ "execution_count": null,
+ "outputs": [],
+ "source": [
+ "import pandas as pd\n",
+ "\n",
+ "p = pd.read_csv('results/cartpredpruned.csv')\n",
+ "p = p[p.columns[2:]]\n",
+ "for c in p.columns[2:]:\n",
+ " p[c] = abs(p[c] - p.model)\n",
+ "p.describe().loc['mean']"
+ ],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%%\n"
}
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "**********************\n",
- "Best Algorithm.GRIDEX\n",
- "**********************\n",
- "MAE = 0.00, 4 rules\n",
- "Threshold = 0.00\n",
- "Iterations = 1\n",
- "Strategy = Fixed (2)\n",
- "\n",
- "**********************\n",
- "Best MAE \n",
- "**********************\n",
- "MAE = 0.00, 72 rules\n",
- "Threshold = 0.00\n",
- "Iterations = 1\n",
- "Strategy = Adaptive ([(0.33, 2), (0.67, 3)])\n",
- "\n",
- "**********************\n",
- "Best N rules\n",
- "**********************\n",
- "MAE = 0.00, 4 rules\n",
- "Threshold = 0.00\n",
- "Iterations = 1\n",
- "Strategy = Fixed (2)\n",
- "\n",
- "GridREx performance (86 rules):\n",
- "MAE = 0.00\n",
- "MAE fidelity = 0.00\n",
- "R2 = 0.99\n",
- "R2 fidelity = 0.99\n",
- "\n",
- "GridREx extracted rules:\n",
- "\n",
- "z(X, Y, 0.7) :-\n",
- " X in [0.00, 0.50], Y in [0.00, 0.49].\n",
- "z(X, Y, 0.39) :-\n",
- " X in [0.00, 0.50], Y in [0.49, 0.99].\n",
- "z(X, Y, 0.3) :-\n",
- " X in [0.50, 0.99], Y in [0.00, 0.49].\n",
- "z(X, Y, 0.0) :-\n",
- " X in [0.50, 0.99], Y in [0.49, 0.99].\n",
- "z(X, Y, 0.7) :-\n",
- " X in [0.00, 0.50], Y in [0.00, 0.49].\n",
- "z(X, Y, 0.39) :-\n",
- " X in [0.00, 0.50], Y in [0.49, 0.99].\n",
- "z(X, Y, 0.3) :-\n",
- " X in [0.50, 0.99], Y in [0.00, 0.49].\n",
- "z(X, Y, 0.0) :-\n",
- " X in [0.50, 0.99], Y in [0.49, 0.99].\n",
- "z(X, Y, 0.7) :-\n",
- " X in [0.00, 0.33], Y in [0.00, 0.33].\n",
- "z(X, Y, 0.54) :-\n",
- " X in [0.00, 0.33], Y in [0.33, 0.66].\n",
- "z(X, Y, 0.4) :-\n",
- " X in [0.00, 0.33], Y in [0.66, 0.99].\n",
- "z(X, Y, 0.48) :-\n",
- " X in [0.33, 0.66], Y in [0.00, 0.33].\n",
- "z(X, Y, 0.37) :-\n",
- " X in [0.33, 0.66], Y in [0.33, 0.66].\n",
- "z(X, Y, 0.17) :-\n",
- " X in [0.33, 0.66], Y in [0.66, 0.99].\n",
- "z(X, Y, 0.3) :-\n",
- " X in [0.66, 0.99], Y in [0.00, 0.33].\n",
- "z(X, Y, 0.14) :-\n",
- " X in [0.66, 0.99], Y in [0.33, 0.66].\n",
- "z(X, Y, 0.0) :-\n",
- " X in [0.66, 0.99], Y in [0.66, 0.99].\n",
- "z(X, Y, 0.7) :-\n",
- " X in [0.00, 0.33], Y in [0.00, 0.33].\n",
- "z(X, Y, 0.54) :-\n",
- " X in [0.00, 0.33], Y in [0.33, 0.66].\n",
- "z(X, Y, 0.4) :-\n",
- " X in [0.00, 0.33], Y in [0.66, 0.99].\n",
- "z(X, Y, 0.48) :-\n",
- " X in [0.33, 0.66], Y in [0.00, 0.33].\n",
- "z(X, Y, 0.37) :-\n",
- " X in [0.33, 0.66], Y in [0.33, 0.66].\n",
- "z(X, Y, 0.17) :-\n",
- " X in [0.33, 0.66], Y in [0.66, 0.99].\n",
- "z(X, Y, 0.3) :-\n",
- " X in [0.66, 0.99], Y in [0.00, 0.33].\n",
- "z(X, Y, 0.14) :-\n",
- " X in [0.66, 0.99], Y in [0.33, 0.66].\n",
- "z(X, Y, 0.0) :-\n",
- " X in [0.66, 0.99], Y in [0.66, 0.99].\n",
- "z(X, Y, 0.55) :-\n",
- " X in [0.00, 0.50], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.14) :-\n",
- " X in [0.50, 0.99], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.55) :-\n",
- " X in [0.00, 0.50], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.14) :-\n",
- " X in [0.50, 0.99], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.55) :-\n",
- " X in [0.00, 0.33], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.35) :-\n",
- " X in [0.33, 0.66], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.14) :-\n",
- " X in [0.66, 0.99], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.55) :-\n",
- " X in [0.00, 0.33], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.35) :-\n",
- " X in [0.33, 0.66], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.14) :-\n",
- " X in [0.66, 0.99], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.56) :-\n",
- " X in [0.00, 0.20], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.55) :-\n",
- " X in [0.20, 0.40], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.37) :-\n",
- " X in [0.40, 0.60], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.14) :-\n",
- " X in [0.60, 0.80], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.14) :-\n",
- " X in [0.80, 0.99], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.56) :-\n",
- " X in [0.00, 0.20], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.55) :-\n",
- " X in [0.20, 0.40], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.37) :-\n",
- " X in [0.40, 0.60], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.14) :-\n",
- " X in [0.60, 0.80], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.14) :-\n",
- " X in [0.80, 0.99], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.56) :-\n",
- " X in [0.00, 0.10], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.54) :-\n",
- " X in [0.10, 0.20], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.54) :-\n",
- " X in [0.20, 0.30], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.55) :-\n",
- " X in [0.30, 0.40], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.55) :-\n",
- " X in [0.40, 0.50], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.15) :-\n",
- " X in [0.50, 0.60], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.15) :-\n",
- " X in [0.60, 0.70], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.13) :-\n",
- " X in [0.70, 0.80], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.14) :-\n",
- " X in [0.80, 0.89], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.14) :-\n",
- " X in [0.89, 0.99], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.56) :-\n",
- " X in [0.00, 0.10], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.54) :-\n",
- " X in [0.10, 0.20], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.54) :-\n",
- " X in [0.20, 0.30], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.55) :-\n",
- " X in [0.30, 0.40], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.55) :-\n",
- " X in [0.40, 0.50], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.15) :-\n",
- " X in [0.50, 0.60], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.15) :-\n",
- " X in [0.60, 0.70], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.13) :-\n",
- " X in [0.70, 0.80], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.14) :-\n",
- " X in [0.80, 0.89], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.14) :-\n",
- " X in [0.89, 0.99], Y in [0.00, 0.99].\n",
- "z(X, Y, 0.7) :-\n",
- " X in [0.00, 0.33], Y in [0.00, 0.49].\n",
- "z(X, Y, 0.4) :-\n",
- " X in [0.00, 0.33], Y in [0.49, 0.99].\n",
- "z(X, Y, 0.52) :-\n",
- " X in [0.33, 0.66], Y in [0.00, 0.49].\n",
- "z(X, Y, 0.17) :-\n",
- " X in [0.33, 0.66], Y in [0.49, 0.99].\n",
- "z(X, Y, 0.29) :-\n",
- " X in [0.66, 0.99], Y in [0.00, 0.49].\n",
- "z(X, Y, 0.0) :-\n",
- " X in [0.66, 0.99], Y in [0.49, 0.99].\n",
- "z(X, Y, 0.7) :-\n",
- " X in [0.00, 0.33], Y in [0.00, 0.49].\n",
- "z(X, Y, 0.4) :-\n",
- " X in [0.00, 0.33], Y in [0.49, 0.99].\n",
- "z(X, Y, 0.52) :-\n",
- " X in [0.33, 0.66], Y in [0.00, 0.49].\n",
- "z(X, Y, 0.17) :-\n",
- " X in [0.33, 0.66], Y in [0.49, 0.99].\n",
- "z(X, Y, 0.29) :-\n",
- " X in [0.66, 0.99], Y in [0.00, 0.49].\n",
- "z(X, Y, 0.0) :-\n",
- " X in [0.66, 0.99], Y in [0.49, 0.99].\n",
- "z(X, Y, 0.7) :-\n",
- " X in [0.00, 0.50], Y in [0.00, 0.49].\n",
- "z(X, Y, 0.39) :-\n",
- " X in [0.00, 0.50], Y in [0.49, 0.99].\n",
- "z(X, Y, 0.3) :-\n",
- " X in [0.50, 0.99], Y in [0.00, 0.49].\n",
- "z(X, Y, 0.0) :-\n",
- " X in [0.50, 0.99], Y in [0.49, 0.99].\n",
- "z(X, Y, Z) :-\n",
- " X in [0.00, 0.50], Y in [0.00, 0.49], Z is 0.7.\n",
- "z(X, Y, Z) :-\n",
- " X in [0.00, 0.50], Y in [0.49, 0.99], Z is 0.40 - 0.07 * X + 0.00 * Y.\n",
- "z(X, Y, Z) :-\n",
- " X in [0.50, 0.99], Y in [0.00, 0.49], Z is 0.3.\n",
- "z(X, Y, Z) :-\n",
- " X in [0.50, 0.99], Y in [0.49, 0.99], Z is 0.0.\n"
- ]
- }
- ],
- "source": [
- "#pedro = PEDRO(predictor, train, max_mae_increase=1.2, min_rule_decrease=0.9, readability_tradeoff=0.1,\n",
- "# max_depth=2, patience=1, algorithm=PEDRO.Algorithm.GRIDREX, objective=Objective.MODEL)\n",
- "#pedro.search()\n",
- "(_, _, threshold, grid) = pedro.get_best()[0]\n",
- "\n",
- "gridREx = Extractor.gridrex(predictor, grid, threshold=threshold, normalization=normalization)\n",
- "theory_from_gridREx = gridREx.extract(train)\n",
- "evaluate('GridREx', gridREx, true, predicted)\n",
- "print('GridREx extracted rules:\\n\\n' + pretty_theory(theory_from_gridREx))"
- ]
+ }
},
{
"cell_type": "code",
- "execution_count": 14,
+ "execution_count": null,
+ "outputs": [],
+ "source": [],
"metadata": {
"collapsed": false,
"pycharm": {
"name": "#%%\n"
}
- },
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "CART performance (4 rules):\n",
- "MAE = 0.00\n",
- "MAE fidelity = 0.00\n",
- "R2 = 1.00\n",
- "R2 fidelity = 1.00\n",
- "\n",
- "CART extracted rules:\n",
- "\n",
- "z(X, Y, 0.3) :-\n",
- " X > 0.50, Y =< 0.49.\n",
- "z(X, Y, 0.0) :-\n",
- " X > 0.50, Y > 0.49.\n",
- "z(X, Y, 0.7) :-\n",
- " Y =< 0.50.\n",
- "z(X, Y, 0.4).\n"
- ]
- }
- ],
- "source": [
- "cart = Extractor.cart(predictor, max_depth=4, max_leaves=4, simplify=True, normalization=normalization)\n",
- "theory_from_cart = cart.extract(train)\n",
- "evaluate('CART', cart, true, predicted)\n",
- "print('CART extracted rules:\\n\\n' + pretty_theory(theory_from_cart))"
- ]
+ }
}
],
"metadata": {
diff --git a/demo/README.md b/demo/README.md
deleted file mode 100644
index a67d14ac..00000000
--- a/demo/README.md
+++ /dev/null
@@ -1,40 +0,0 @@
-## About Notebooks files in this directory
-
-Notebook files (`.ipynb`) in this directory contain demos of PSyKE.
-
-These are NOT meant to be executed directly, but rather via some container started from the [PSyKE Image](https://hub.docker.com/r/pikalab/psyke) on DockerHub.
-
-To do so, please ensure
-- [Docker](https://docs.docker.com/engine/install/) is installed on your system
-- the Docker service is up and running
-
-and then follow these steps:
-
-1. Choose a target version of PSyKE, say `X.Y.Z`
- - cf. [DockerHub image tags](https://hub.docker.com/r/pikalab/psyke/tags)
- - cf. [PyPi releases history](https://pypi.org/project/psyke/#history)
- - cf. [GitHub releases](https://github.com/psykei/psyke-python/releases)
-
-2. Pull the corresponding image:
- ```bash
- docker pull pikalab/psyke:X.Y.Z
- ```
-
-2. Run the image into a container:
- ```bash
- docker run --rm -it -p 8888:8888 --name psyke pikalab/psyke:X.Y.Z
- ```
-
-3. Some logs such as the following ones should eventually be printed
- ```
- To access the notebook, open this file in a browser:
- file:///root/.local/share/jupyter/runtime/nbserver-7-open.html
- Or copy and paste one of these URLs:
- http://66fa9b93bbe7:8888/?token=
- or http://127.0.0.1:8888/?token=
- ```
-
-4. Open your browser and browse to `http://localhost:8888/?token=`
- - use the token from the logs above, if requested by the Web page
-
-5. Enjoy PSyKE-powered notebook!
diff --git a/demo/demo.py b/demo/demo.py
deleted file mode 100644
index c4d2d124..00000000
--- a/demo/demo.py
+++ /dev/null
@@ -1,27 +0,0 @@
-from sklearn.datasets import load_iris
-from sklearn.model_selection import train_test_split
-from sklearn.neighbors import KNeighborsClassifier
-import pandas as pd
-from psyke import Extractor
-from psyke.utils.dataframe import get_discrete_features_equal_frequency, get_discrete_dataset
-from psyke.utils.logic import pretty_theory
-
-x, y = load_iris(return_X_y=True, as_frame=True)
-x.columns = ['SepalLength', 'SepalWidth', 'PetalLength', 'PetalWidth']
-iris_features = get_discrete_features_equal_frequency(x, bins=3, output=False)
-x = get_discrete_dataset(x, iris_features)
-y = pd.DataFrame(y).replace({"target": {0: 'setosa', 1: 'virginica', 2: 'versicolor'}})
-dataset = x.join(y)
-dataset.columns = [*dataset.columns[:-1], 'iris']
-train, test = train_test_split(dataset, test_size=0.5, random_state=0)
-
-predictor = KNeighborsClassifier(n_neighbors=7)
-predictor.fit(train.iloc[:, :-1], train.iloc[:, -1])
-
-real = Extractor.real(predictor, iris_features)
-theory_from_real = real.extract(train)
-print('REAL extracted rules:\n' + pretty_theory(theory_from_real))
-
-trepan = Extractor.trepan(predictor, iris_features)
-theory_from_trepan = trepan.extract(train)
-print('\nTrepan extracted rules:\n' + pretty_theory(theory_from_trepan))
diff --git a/psyke/__init__.py b/psyke/__init__.py
index eb71036c..77bb12e8 100644
--- a/psyke/__init__.py
+++ b/psyke/__init__.py
@@ -56,14 +56,27 @@ def predict(self, dataframe: pd.DataFrame, mapping: dict[str: int] = None) -> It
:param mapping: for one-hot encoding.
:return: a list of predictions.
"""
- ys = self._predict(dataframe)
+ return self.__convert(self._predict(dataframe), mapping)
+
+ def _predict(self, dataframe: pd.DataFrame) -> Iterable:
+ raise NotImplementedError('predict')
+
+ def __convert(self, ys: Iterable, mapping: dict[str: int] = None) -> Iterable:
if mapping is not None:
inverse_mapping = {v: k for k, v in mapping.items()}
ys = [inverse_mapping[y] for y in ys]
+ if self.normalization is not None:
+ m, s = self.normalization[list(self.normalization.keys())[-1]]
+ ys = [prediction if prediction is None else prediction * s + m for prediction in ys]
return ys
- def _predict(self, dataframe: pd.DataFrame) -> Iterable:
- raise NotImplementedError('predict')
+ def brute_predict(self, dataframe: pd.DataFrame, criterion: str = 'corner', n: int = 2,
+ mapping: dict[str: int] = None) -> Iterable:
+ return self.__convert(self._brute_predict(dataframe, criterion, n, mapping), mapping)
+
+ def _brute_predict(self, dataframe: pd.DataFrame, criterion: str = 'corner', n: int = 2,
+ mapping: dict[str: int] = None) -> Iterable:
+ raise NotImplementedError('brute_predict')
def unscale(self, values, name):
if self.normalization is None or isinstance(values, LinearRegression):
@@ -76,9 +89,13 @@ def unscale(self, values, name):
return values
def score(self, dataframe: pd.DataFrame, predictor=None, fidelity: bool = False, completeness: bool = True,
+ brute: bool = False, criterion: str = 'corners', n: int = 2,
task: EvaluableModel.Task = Task.CLASSIFICATION,
scoring_function: Iterable[EvaluableModel.Score] = [ClassificationScore.ACCURACY]):
- extracted = np.array(self.predict(dataframe.iloc[:, :-1]))
+ extracted = np.array(
+ self.predict(dataframe.iloc[:, :-1]) if not brute else
+ self.brute_predict(dataframe.iloc[:, :-1], criterion, n)
+ )
idx = [prediction is not None for prediction in extracted]
y_extracted = extracted[idx]
true = [dataframe.iloc[idx, -1]]
@@ -153,59 +170,81 @@ def extract(self, dataframe: pd.DataFrame, mapping: dict[str: int] = None, sort:
"""
raise NotImplementedError('extract')
- def mae(self, dataframe: pd.DataFrame, predictor=None) -> float:
+ def mae(self, dataframe: pd.DataFrame, predictor=None, brute: bool = False, criterion: str = 'center',
+ n: int = 3) -> float:
"""
Calculates the predictions' MAE w.r.t. the instances given as input.
:param dataframe: is the set of instances to be used to calculate the mean absolute error.
:param predictor: if provided, its predictions on the dataframe are taken instead of the dataframe instances.
+ :param brute: if True, a brute prediction is executed.
+ :param criterion: creterion for brute prediction.
+ :param n: number of points for brute prediction with 'perimeter' criterion.
:return: the mean absolute error (MAE) of the predictions.
"""
- return self.score(dataframe, predictor, predictor is not None, False, Extractor.Task.REGRESSION,
- [Extractor.RegressionScore.MAE])[Extractor.RegressionScore.MAE][-1]
+ return self.score(dataframe, predictor, predictor is not None, False, brute, criterion, n,
+ Extractor.Task.REGRESSION, [Extractor.RegressionScore.MAE])[Extractor.RegressionScore.MAE][-1]
- def mse(self, dataframe: pd.DataFrame, predictor=None) -> float:
+ def mse(self, dataframe: pd.DataFrame, predictor=None, brute: bool = False, criterion: str = 'center',
+ n: int = 3) -> float:
"""
Calculates the predictions' MSE w.r.t. the instances given as input.
:param dataframe: is the set of instances to be used to calculate the mean squared error.
:param predictor: if provided, its predictions on the dataframe are taken instead of the dataframe instances.
+ :param brute: if True, a brute prediction is executed.
+ :param criterion: creterion for brute prediction.
+ :param n: number of points for brute prediction with 'perimeter' criterion.
:return: the mean squared error (MSE) of the predictions.
"""
- return self.score(dataframe, predictor, predictor is not None, False, Extractor.Task.REGRESSION,
- [Extractor.RegressionScore.MSE])[Extractor.RegressionScore.MSE][-1]
+ return self.score(dataframe, predictor, predictor is not None, False, brute, criterion, n,
+ Extractor.Task.REGRESSION, [Extractor.RegressionScore.MSE])[Extractor.RegressionScore.MSE][-1]
- def r2(self, dataframe: pd.DataFrame, predictor=None) -> float:
+ def r2(self, dataframe: pd.DataFrame, predictor=None, brute: bool = False, criterion: str = 'center',
+ n: int = 3) -> float:
"""
Calculates the predictions' R2 score w.r.t. the instances given as input.
:param dataframe: is the set of instances to be used to calculate the R2 score.
:param predictor: if provided, its predictions on the dataframe are taken instead of the dataframe instances.
+ :param brute: if True, a brute prediction is executed.
+ :param criterion: creterion for brute prediction.
+ :param n: number of points for brute prediction with 'perimeter' criterion.
:return: the R2 score of the predictions.
"""
- return self.score(dataframe, predictor, predictor is not None, False,
+ return self.score(dataframe, predictor, predictor is not None, False, brute, criterion, n,
Extractor.Task.REGRESSION, [Extractor.RegressionScore.R2])[Extractor.RegressionScore.R2][-1]
- def accuracy(self, dataframe: pd.DataFrame, predictor=None) -> float:
+ def accuracy(self, dataframe: pd.DataFrame, predictor=None, brute: bool = False, criterion: str = 'center',
+ n: int = 3) -> float:
"""
Calculates the predictions' accuracy classification score w.r.t. the instances given as input.
:param dataframe: is the set of instances to be used to calculate the accuracy classification score.
:param predictor: if provided, its predictions on the dataframe are taken instead of the dataframe instances.
+ :param brute: if True, a brute prediction is executed.
+ :param criterion: creterion for brute prediction.
+ :param n: number of points for brute prediction with 'perimeter' criterion.
:return: the accuracy classification score of the predictions.
"""
- return self.score(dataframe, predictor, predictor is not None, False, Extractor.Task.CLASSIFICATION,
+ return self.score(dataframe, predictor, predictor is not None, False, brute, criterion, n,
+ Extractor.Task.CLASSIFICATION,
[Extractor.ClassificationScore.ACCURACY])[Extractor.ClassificationScore.ACCURACY][-1]
- def f1(self, dataframe: pd.DataFrame, predictor=None) -> float:
+ def f1(self, dataframe: pd.DataFrame, predictor=None, brute: bool = False, criterion: str = 'center',
+ n: int = 3) -> float:
"""
Calculates the predictions' F1 score w.r.t. the instances given as input.
:param dataframe: is the set of instances to be used to calculate the F1 score.
:param predictor: if provided, its predictions on the dataframe are taken instead of the dataframe instances.
+ :param brute: if True, a brute prediction is executed.
+ :param criterion: creterion for brute prediction.
+ :param n: number of points for brute prediction with 'perimeter' criterion.
:return: the F1 score of the predictions.
"""
- return self.score(dataframe, predictor, predictor is not None, False, Extractor.Task.CLASSIFICATION,
+ return self.score(dataframe, predictor, predictor is not None, False, brute, criterion, n,
+ Extractor.Task.CLASSIFICATION,
[Extractor.ClassificationScore.F1])[Extractor.ClassificationScore.F1][-1]
@staticmethod
@@ -218,6 +257,27 @@ def cart(predictor, max_depth: int = 3, max_leaves: int = 3,
return Cart(predictor, max_depth, max_leaves, discretization=discretization, normalization=normalization,
simplify=simplify)
+ @staticmethod
+ def divine(predictor, k: int = 5, patience: int = 15, close_to_center: bool = True,
+ discretization: Iterable[DiscreteFeature] = None, normalization=None) -> Extractor:
+ """
+ Creates a new DiViNE extractor.
+ """
+ from psyke.extraction.hypercubic.divine import DiViNE
+ return DiViNE(predictor, k=k, patience=patience, close_to_center=close_to_center,
+ discretization=discretization, normalization=normalization)
+
+ @staticmethod
+ def cosmik(predictor, max_components: int = 4, k: int = 5, patience: int = 15, close_to_center: bool = True,
+ output: Target = Target.CONSTANT,
+ discretization: Iterable[DiscreteFeature] = None, normalization=None) -> Extractor:
+ """
+ Creates a new COSMiK extractor.
+ """
+ from psyke.extraction.hypercubic.cosmik import COSMiK
+ return COSMiK(predictor, max_components=max_components, k=k, patience=patience, close_to_center=close_to_center,
+ output=output, discretization=discretization, normalization=normalization)
+
@staticmethod
def iter(predictor, min_update: float = 0.1, n_points: int = 1, max_iterations: int = 600, min_examples: int = 250,
threshold: float = 0.1, fill_gaps: bool = True, normalization: dict[str, tuple[float, float]] = None,
@@ -250,15 +310,15 @@ def gridrex(predictor, grid, min_examples: int = 250, threshold: float = 0.1,
return GridREx(predictor, grid, min_examples, threshold, normalization, seed)
@staticmethod
- def creepy(predictor, clustering, depth: int, error_threshold: float, output, gauss_components: int = 2,
- ranks: [(str, float)] = [], ignore_threshold: float = 0.0,
- normalization: dict[str, tuple[float, float]] = None) -> Extractor:
+ def creepy(predictor, clustering, depth: int, error_threshold: float, output: Target = Target.CONSTANT,
+ gauss_components: int = 2, ranks: [(str, float)] = [], ignore_threshold: float = 0.0,
+ discretization=None, normalization: dict[str, tuple[float, float]] = None) -> Extractor:
"""
Creates a new CReEPy extractor.
"""
from psyke.extraction.hypercubic.creepy import CReEPy
return CReEPy(predictor, depth, error_threshold, output, gauss_components, ranks, ignore_threshold,
- normalization, clustering)
+ discretization, normalization, clustering)
@staticmethod
def real(predictor, discretization=None) -> Extractor:
@@ -314,6 +374,7 @@ def __init__(self, predictor, discretization=None, normalization=None):
Extractor.__init__(self, predictor=predictor, discretization=discretization, normalization=normalization)
def extract(self, dataframe: pd.DataFrame, mapping: dict[str: int] = None, sort: bool = True) -> Theory:
+ from psyke.extraction.hypercubic import HyperCubeExtractor, HyperCube
new_y = self.predictor.predict(dataframe.iloc[:, :-1])
if mapping is not None:
if hasattr(new_y[0], 'shape'):
@@ -326,7 +387,11 @@ def extract(self, dataframe: pd.DataFrame, mapping: dict[str: int] = None, sort:
new_y = pd.DataFrame(new_y).set_index(dataframe.index)
data = dataframe.iloc[:, :-1].copy().join(new_y)
data.columns = dataframe.columns
- return self._extract(data, mapping, sort)
+ theory = self._extract(data, mapping, sort)
+ if isinstance(self, HyperCubeExtractor):
+ self._surrounding = HyperCube.create_surrounding_cube(dataframe, output=self._output)
+ self._surrounding.update(dataframe, self.predictor)
+ return theory
def _extract(self, dataframe: pd.DataFrame, mapping: dict[str: int] = None, sort: bool = True) -> Theory:
raise NotImplementedError('extract')
diff --git a/psyke/extraction/cart/__init__.py b/psyke/extraction/cart/__init__.py
index c2ceabff..444045ed 100644
--- a/psyke/extraction/cart/__init__.py
+++ b/psyke/extraction/cart/__init__.py
@@ -77,8 +77,8 @@ def _extract(self, data: pd.DataFrame, mapping: dict[str: int] = None, sort: boo
self._cart_predictor.predictor.fit(data.iloc[:, :-1], data.iloc[:, -1])
return self._create_theory(data, mapping, sort)
- def _predict(self, data) -> Iterable:
- return self._cart_predictor.predict(data)
+ def _predict(self, dataframe: pd.DataFrame) -> Iterable:
+ return self._cart_predictor.predict(dataframe)
@property
def n_rules(self) -> int:
diff --git a/psyke/extraction/hypercubic/__init__.py b/psyke/extraction/hypercubic/__init__.py
index 7d7783a5..7a5ee046 100644
--- a/psyke/extraction/hypercubic/__init__.py
+++ b/psyke/extraction/hypercubic/__init__.py
@@ -9,26 +9,78 @@
from sklearn.linear_model import LinearRegression
from tuprolog.core import Var, Struct, clause
from tuprolog.theory import Theory, mutable_theory
-from psyke import logger, PedagogicalExtractor
-from psyke.extraction.hypercubic.hypercube import HyperCube, RegressionCube, ClassificationCube, ClosedCube
+from psyke import logger, PedagogicalExtractor, EvaluableModel
+from psyke.extraction.hypercubic.hypercube import HyperCube, RegressionCube, ClassificationCube, ClosedCube, Point, \
+ GenericCube
from psyke.utils.logic import create_variable_list, create_head, to_var, Simplifier
from psyke.utils import Target, get_int_precision
from psyke.extraction.hypercubic.strategy import Strategy, FixedStrategy
+from sklearn.neighbors import BallTree
-class HyperCubePredictor:
- def __init__(self, cubes=[], output=Target.CONSTANT, normalization=None):
- self._hypercubes = cubes
+class HyperCubePredictor(EvaluableModel):
+ def __init__(self, output=Target.CONSTANT, normalization=None):
+ super().__init__(normalization)
+ self._hypercubes = []
self._output = output
- self.normalization = normalization
def _predict(self, dataframe: pd.DataFrame) -> Iterable:
- return np.array([self._predict_from_cubes(dict(row.to_dict())) for _, row in dataframe.iterrows()])
+ return np.array([self._predict_from_cubes(row.to_dict()) for _, row in dataframe.iterrows()])
+
+ def _brute_predict(self, dataframe: pd.DataFrame, criterion: str = 'corner', n: int = 2,
+ mapping: dict[str: int] = None) -> Iterable:
+ predictions = self._predict(dataframe)
+ idx = [prediction is None for prediction in predictions]
+ if sum(idx) > 0:
+ if criterion == 'default':
+ if not isinstance(self, HyperCubeExtractor):
+ raise ValueError("'default' criterion only available for instances of HyperCubeExtractor")
+ predictions[idx] = np.array([HyperCubePredictor._get_cube_output(
+ self._surrounding, row
+ ) for _, row in dataframe[idx].iterrows()])
+ elif criterion == 'surface':
+ if not isinstance(self, HyperCubeExtractor):
+ raise ValueError("'surface' criterion only available for instances of HyperCubeExtractor")
+ predictions[idx] = np.array([HyperCubePredictor._get_cube_output(self._brute_predict_surface(row), row)
+ for _, row in dataframe[idx].iterrows()])
+ else:
+ tree, cubes = self._create_brute_tree(criterion, n)
+ predictions[idx] = np.array([HyperCubePredictor._brute_predict_from_cubes(
+ row.to_dict(), tree, cubes
+ ) for _, row in dataframe[idx].iterrows()])
+ return np.array(predictions)
- def _predict_from_cubes(self, data: dict[str, float]) -> float | None:
- data = {k: v for k, v in data.items()}
+ @staticmethod
+ def _brute_predict_from_cubes(row: dict[str, float], tree: BallTree,
+ cubes: list[GenericCube]) -> float | str:
+ idx = tree.query([list(row.values())], k=1)[1][0][0]
+ return HyperCubePredictor._get_cube_output(cubes[idx], row)
+
+ def _brute_predict_surface(self, row: dict[str, float]) -> GenericCube:
+ distances = [(
+ cube.surface_distance(Point(list(row.keys()), list(row.values))), cube.volume(), cube
+ ) for cube in self._hypercubes]
+ return min(distances)[-1]
+
+ def _create_brute_tree(self, criterion: str = 'center', n: int = 2) -> (BallTree, list[GenericCube]):
+ admissible_criteria = ['surface', 'center', 'corner', 'perimeter', 'density', 'default']
+ if criterion not in admissible_criteria:
+ raise NotImplementedError(
+ "'criterion' should be chosen in " + str(admissible_criteria)
+ )
+
+ points = [(cube.center, cube) for cube in self._hypercubes] if criterion == 'center' else \
+ [(cube.barycenter, cube) for cube in self._hypercubes] if criterion == 'density' else \
+ [(corner, cube) for cube in self._hypercubes for corner in cube.corners()] if criterion == 'corner' else \
+ [(point, cube) for cube in self._hypercubes for point in cube.perimeter_samples(n)] \
+ if criterion == 'perimeter' else None
+
+ return BallTree(pd.concat([point[0].to_dataframe() for point in points], ignore_index=True)), \
+ [point[1] for point in points]
+
+ def _predict_from_cubes(self, data: dict[str, float]) -> float | str | None:
for cube in self._hypercubes:
- if cube.__contains__(data):
+ if data in cube:
if self._output == Target.CLASSIFICATION:
return HyperCubePredictor._get_cube_output(cube, data)
else:
@@ -50,9 +102,10 @@ def _get_cube_output(cube, data: dict[str, float]) -> float:
class HyperCubeExtractor(HyperCubePredictor, PedagogicalExtractor, ABC):
- def __init__(self, predictor, output, normalization):
- PedagogicalExtractor.__init__(self, predictor, normalization=normalization)
+ def __init__(self, predictor, output, discretization=None, normalization=None):
HyperCubePredictor.__init__(self, output=output, normalization=normalization)
+ PedagogicalExtractor.__init__(self, predictor, discretization=discretization, normalization=normalization)
+ self._surrounding = None
def _default_cube(self) -> HyperCube | RegressionCube | ClassificationCube:
if self._output == Target.CONSTANT:
@@ -61,6 +114,11 @@ def _default_cube(self) -> HyperCube | RegressionCube | ClassificationCube:
return RegressionCube()
return ClassificationCube()
+ def _sort_cubes(self):
+ cubes = [(cube.diversity, i, cube) for i, cube in enumerate(self._hypercubes)]
+ cubes.sort()
+ self._hypercubes = [cube[2] for cube in cubes]
+
@staticmethod
def _create_head(dataframe: pd.DataFrame, variables: list[Var], output: float | LinearRegression) -> Struct:
return create_head(dataframe.columns[-1], variables[:-1], output) \
@@ -70,7 +128,11 @@ def _create_head(dataframe: pd.DataFrame, variables: list[Var], output: float |
def _ignore_dimensions(self) -> Iterable[str]:
return []
- def _create_theory(self, dataframe: pd.DataFrame, sort: bool = True) -> Theory:
+ def __drop(self, dataframe: pd.DataFrame):
+ self._hypercubes = [cube for cube in self._hypercubes if cube.count(dataframe) > 1]
+
+ def _create_theory(self, dataframe: pd.DataFrame, sort: bool = False) -> Theory:
+ self.__drop(dataframe)
new_theory = mutable_theory()
for cube in self._hypercubes:
logger.info(cube.output)
diff --git a/psyke/extraction/hypercubic/cosmik/__init__.py b/psyke/extraction/hypercubic/cosmik/__init__.py
new file mode 100644
index 00000000..c7be3a89
--- /dev/null
+++ b/psyke/extraction/hypercubic/cosmik/__init__.py
@@ -0,0 +1,43 @@
+import pandas as pd
+from sklearn.mixture import GaussianMixture
+from tuprolog.theory import Theory
+
+from psyke import Target, Extractor
+from psyke.clustering.utils import select_gaussian_mixture
+from psyke.extraction.hypercubic import HyperCube, HyperCubeExtractor, RegressionCube
+
+
+class COSMiK(HyperCubeExtractor):
+ """
+ Explanator implementing COSMiK algorithm.
+ """
+
+ def __init__(self, predictor, max_components: int = 4, k: int = 5, patience: int = 15, close_to_center: bool = True,
+ output: Target = Target.CONSTANT, discretization=None, normalization=None):
+ super().__init__(predictor, Target.REGRESSION, discretization, normalization)
+ self.max = max_components
+ self.k = k
+ self.patience = patience
+ self.output = output
+ self.close_to_center = close_to_center
+
+ def _extract(self, dataframe: pd.DataFrame, mapping: dict[str: int] = None, sort: bool = True) -> Theory:
+ X, y = dataframe.iloc[:, :-1], dataframe.iloc[:, -1]
+
+ _, n, _ = select_gaussian_mixture(dataframe, self.max)
+ gmm = GaussianMixture(n)
+ gmm.fit(X, y)
+
+ divine = Extractor.divine(gmm, self.k, self.patience, self.close_to_center,
+ self.discretization, self.normalization)
+ df = X.join(pd.DataFrame(gmm.predict(X)))
+ df.columns = dataframe.columns
+ divine.extract(df)
+
+ self._hypercubes = [HyperCube(cube.dimensions.copy()) if self.output == Target.CONSTANT else
+ RegressionCube(cube.dimensions.copy()) for cube in divine._hypercubes]
+ for cube in self._hypercubes:
+ cube.update(dataframe, self.predictor)
+
+ self._sort_cubes()
+ return self._create_theory(dataframe, sort)
\ No newline at end of file
diff --git a/psyke/extraction/hypercubic/creepy/__init__.py b/psyke/extraction/hypercubic/creepy/__init__.py
index 8bdba96f..1d72f759 100644
--- a/psyke/extraction/hypercubic/creepy/__init__.py
+++ b/psyke/extraction/hypercubic/creepy/__init__.py
@@ -11,18 +11,19 @@
from psyke.clustering import HyperCubeClustering
from psyke.extraction.hypercubic import HyperCubeExtractor
from psyke.utils import Target
+from psyke.utils.logic import last_in_body
-class CReEPy(HyperCubeExtractor, ABC):
+class CReEPy(HyperCubeExtractor):
"""
Explanator implementing CReEPy algorithm.
"""
def __init__(self, predictor, depth: int, error_threshold: float, output: Target = Target.CONSTANT,
gauss_components: int = 5, ranks: list[(str, float)] = [], ignore_threshold: float = 0.0,
- normalization=None, clustering=Clustering.exact):
+ discretization=None, normalization=None, clustering=Clustering.exact):
super().__init__(predictor, Target.CLASSIFICATION if isinstance(predictor, ClassifierMixin) else output,
- normalization)
+ discretization, normalization)
self.clustering = clustering(depth, error_threshold, self._output, gauss_components)
self.ranks = ranks
self.ignore_threshold = ignore_threshold
@@ -40,7 +41,7 @@ def _extract(self, dataframe: pd.DataFrame, mapping: dict[str: int] = None, sort
last_clause = list(theory.clauses)[-1]
theory.retract(last_clause)
theory.assertZ(clause(
- last_clause.head, [list(last_clause.body)[-1]] if self._output is Target.REGRESSION else []))
+ last_clause.head, [last_in_body(last_clause.body)] if self._output is Target.REGRESSION else []))
last_cube = self._hypercubes[-1]
for dimension in last_cube.dimensions.keys():
last_cube[dimension] = [-np.inf, np.inf]
diff --git a/psyke/extraction/hypercubic/divine/__init__.py b/psyke/extraction/hypercubic/divine/__init__.py
new file mode 100644
index 00000000..08c80e74
--- /dev/null
+++ b/psyke/extraction/hypercubic/divine/__init__.py
@@ -0,0 +1,83 @@
+import numpy as np
+import pandas as pd
+from tuprolog.theory import Theory
+
+from psyke import Target
+from psyke.extraction.hypercubic import HyperCubeExtractor
+from psyke.extraction.hypercubic.hypercube import Point, GenericCube, HyperCube
+
+from sklearn.neighbors import BallTree
+
+
+class DiViNE(HyperCubeExtractor):
+ """
+ Explanator implementing DiViNE algorithm.
+ """
+
+ def __init__(self, predictor, k: int = 5, patience: int = 15, close_to_center: bool = True,
+ discretization=None, normalization=None):
+ super().__init__(predictor, Target.CLASSIFICATION, discretization, normalization)
+ self.k = k
+ self.patience = patience
+ self.vicinity_function = DiViNE.closest_to_center if close_to_center else DiViNE.closest_to_corners
+
+ @staticmethod
+ def __pop(data: pd.DataFrame, idx: int = None) -> (Point, pd.DataFrame):
+ if idx is None:
+ idx = data.sample(1).index.values[0]
+ t = data.T
+ return DiViNE.__to_point(t.pop(idx)), t.T.reset_index(drop=True)
+
+ @staticmethod
+ def __to_point(instance) -> Point:
+ point = Point(instance.index.values, instance.values)
+ return point
+
+ def __to_cube(self, point: Point) -> GenericCube:
+ cube = HyperCube.cube_from_point(point.dimensions, self._output)
+ cube._output = list(point.dimensions.values())[-1]
+ return cube
+
+ def __clean(self, data: pd.DataFrame) -> pd.DataFrame:
+ _, idx = BallTree(data.iloc[:, :-1]).query(data.iloc[:, :-1], k=self.k)
+ # how many output classes are associated with the k neighbors
+ count = np.array(list(map(lambda indices: len(data.iloc[indices].iloc[:, -1].unique()), idx)))
+ # instances with neighbors of different classes are discarded
+ return data[count == 1]
+
+ def __closest(self, data: pd.DataFrame, cube: GenericCube) -> (Point, pd.DataFrame):
+ return DiViNE.__pop(data, self.vicinity_function(BallTree(data.iloc[:, :-1]), cube))
+
+ @staticmethod
+ def closest_to_center(tree: BallTree, cube: GenericCube):
+ return tree.query([list(cube.center.dimensions.values())], k=1)[1][0][-1]
+
+ @staticmethod
+ def closest_to_corners(tree: BallTree, cube: GenericCube):
+ distance, idx = tree.query([list(point.dimensions.values()) for point in cube.corners()], k=1)
+ return idx[np.argmin(distance)][-1]
+
+ def _extract(self, dataframe: pd.DataFrame, mapping: dict[str: int] = None, sort: bool = True) -> Theory:
+ data = self.__clean(dataframe)
+
+ while len(data) > 0:
+ discarded = []
+ patience = self.patience
+ point, data = self.__pop(data)
+ cube = self.__to_cube(point)
+
+ while patience > 0 and len(data) > 0:
+ other, data = self.__closest(data, cube)
+ if cube.output == list(other.dimensions.values())[-1]:
+ cube = cube.merge_with_point(other)
+ data = data[~(cube.filter_indices(data.iloc[:, :-1]))].reset_index(drop=True)
+ else:
+ patience -= 1
+ discarded.append(other)
+ if cube.volume() > 0:
+ cube.update(dataframe, self.predictor)
+ self._hypercubes.append(cube)
+ if len(discarded) > 0:
+ data = pd.concat([data] + [d.to_dataframe() for d in discarded]).reset_index(drop=True)
+ self._sort_cubes()
+ return self._create_theory(dataframe, sort)
diff --git a/psyke/extraction/hypercubic/gridex/__init__.py b/psyke/extraction/hypercubic/gridex/__init__.py
index 09272ee0..664554b6 100644
--- a/psyke/extraction/hypercubic/gridex/__init__.py
+++ b/psyke/extraction/hypercubic/gridex/__init__.py
@@ -17,7 +17,7 @@ class GridEx(HyperCubeExtractor):
def __init__(self, predictor, grid: Grid, min_examples: int, threshold: float, normalization=None,
seed=get_default_random_seed()):
- super().__init__(predictor, Target.CONSTANT, normalization)
+ super().__init__(predictor, Target.CONSTANT, normalization=normalization)
self.grid = grid
self.min_examples = min_examples
self.threshold = threshold
diff --git a/psyke/extraction/hypercubic/hypercube.py b/psyke/extraction/hypercubic/hypercube.py
index 7c8d2d2b..342d1da7 100644
--- a/psyke/extraction/hypercubic/hypercube.py
+++ b/psyke/extraction/hypercubic/hypercube.py
@@ -30,25 +30,31 @@ class Point:
EPSILON = get_default_precision()
- def __init__(self, dimensions: list[str], values: list[float]):
+ def __init__(self, dimensions: list[str], values: list[float | str]):
self._dimensions = {dimension: value for (dimension, value) in zip(dimensions, values)}
- def __getitem__(self, feature: str) -> float:
+ def __getitem__(self, feature: str) -> float | str:
if feature in self._dimensions.keys():
return self._dimensions[feature]
else:
raise FeatureNotFoundException(feature)
- def __setitem__(self, key: str, value: float) -> None:
+ def __setitem__(self, key: str, value: float | str) -> None:
self._dimensions[key] = value
def __eq__(self, other: Point) -> bool:
return all([abs(self[dimension] - other[dimension]) < Point.EPSILON for dimension in self._dimensions])
@property
- def dimensions(self) -> dict[str, float]:
+ def dimensions(self) -> dict[str, float | str]:
return self._dimensions
+ def to_dataframe(self) -> pd.DataFrame:
+ return pd.DataFrame(data=[self.dimensions.values()], columns=list(self.dimensions.keys()))
+
+ def copy(self) -> Point:
+ return Point(list(self._dimensions.keys()), list(self._dimensions.values()))
+
class HyperCube:
"""
@@ -59,11 +65,12 @@ class HyperCube:
INT_PRECISION = get_int_precision()
def __init__(self, dimension: dict[str, tuple[float, float]] = None, limits: set[Limit] = None,
- output: float | LinearRegression = 0.0):
+ output: float | LinearRegression | str = 0.0):
self._dimensions = self._fit_dimension(dimension) if dimension is not None else {}
self._limits = limits if limits is not None else set()
self._output = output
self._diversity = 0.0
+ self._barycenter = Point([], [])
def __contains__(self, point: dict[str, float]) -> bool:
"""
@@ -101,13 +108,17 @@ def limit_count(self) -> int:
return len(self._limits)
@property
- def output(self) -> float | LinearRegression:
+ def output(self) -> float | str | LinearRegression:
return self._output
@property
def diversity(self) -> float:
return self._diversity
+ @property
+ def barycenter(self) -> Point:
+ return self._barycenter
+
def _fit_dimension(self, dimension: dict[str, tuple[float, float]]) -> dict[str, tuple[float, float]]:
new_dimension: dict[str, tuple[float, float]] = {}
for key, value in dimension.items():
@@ -125,12 +136,11 @@ def filter_indices(self, dataset: pd.DataFrame) -> ndarray:
ds = dataset.to_numpy(copy=True)
return np.all((v[:, 0] <= ds) & (ds < v[:, 1]), axis=1)
- def _filter_dataframe(self, dataset: pd.DataFrame) -> pd.DataFrame:
+ def filter_dataframe(self, dataset: pd.DataFrame) -> pd.DataFrame:
return dataset[self.filter_indices(dataset)]
- def _zip_dimensions(self, hypercube: HyperCube) -> list[ZippedDimension]:
- return [ZippedDimension(dimension, self[dimension], hypercube[dimension])
- for dimension in self._dimensions.keys()]
+ def _zip_dimensions(self, other: HyperCube) -> list[ZippedDimension]:
+ return [ZippedDimension(dimension, self[dimension], other[dimension]) for dimension in self._dimensions.keys()]
def add_limit(self, limit_or_feature: Limit | str, direction: str = None) -> None:
if isinstance(limit_or_feature, Limit):
@@ -167,7 +177,7 @@ def copy(self) -> HyperCube:
return HyperCube(self.dimensions.copy(), self._limits.copy(), self.output)
def count(self, dataset: pd.DataFrame) -> int:
- return self._filter_dataframe(dataset.iloc[:, :-1]).shape[0]
+ return self.filter_dataframe(dataset.iloc[:, :-1]).shape[0]
def body(self, variables: dict[str, Var], ignore: list[str], unscale=None, normalization=None) -> Iterable[Struct]:
dimensions = dict(self.dimensions)
@@ -202,7 +212,7 @@ def _create_tuple(self, generator: Random) -> dict:
return {k: generator.uniform(self.get_first(k), self.get_second(k)) for k in self._dimensions.keys()}
@staticmethod
- def cube_from_point(point: dict, output=None) -> GenericCube:
+ def cube_from_point(point: dict[str, float], output=None) -> GenericCube:
if output is Target.CLASSIFICATION:
return ClassificationCube({k: (v, v) for k, v in list(point.items())[:-1]})
if output is Target.REGRESSION:
@@ -249,6 +259,7 @@ def diagonal(self) -> float:
lambda a, b: a + b, [(dimension[1] - dimension[0]) ** 2 for dimension in self._dimensions.values()], 0
) ** 0.5
+ @property
def center(self) -> Point:
return Point(list(self._dimensions.keys()),
[(interval[0] + interval[1]) / 2 for interval in self._dimensions.values()])
@@ -258,6 +269,50 @@ def corners(self) -> Iterable[Point]:
Point(list(self._dimensions.keys()), values) for values in itertools.product(*self._dimensions.values())
]
+ def surface_distance(self, point: Point) -> float:
+ s = 0
+ for d in self.dimensions.keys():
+ lower, upper = self[d]
+ p = point[d]
+ if p > upper:
+ s += (p - upper)**2
+ elif p < lower:
+ s += (lower - p)**2
+ return s**0.5
+
+ def perimeter_samples(self, n: int = 5) -> Iterable[Point]:
+ def duplicate(point: Point, feature: str) -> Iterable[Point]:
+ new_point_a = point.copy()
+ new_point_b = point.copy()
+ new_point_a[feature] = self.get_first(feature)
+ new_point_b[feature] = self.get_second(feature)
+ return [new_point_a, new_point_b]
+
+ def remove_duplicates(points: Iterable[Point]) -> Iterable[Point]:
+ new_points = []
+ for point in points:
+ if point not in new_points:
+ new_points.append(point)
+ return new_points
+
+ def split(point: Point, feature: str, n: int):
+ points = []
+ a, b = self.get_first(feature), self.get_second(feature)
+ for value in np.linspace(a, b, n) if n > 1 else [(a + b) / 2]:
+ new_point = point.copy()
+ new_point[feature] = value
+ points.append(new_point)
+ return points
+
+ points = []
+ for primary in self._dimensions:
+ new_points = [Point([], [])]
+ for secondary in self._dimensions:
+ new_points = np.array([duplicate(point, secondary) if primary != secondary else
+ split(point, primary, n) for point in new_points]).flatten()
+ points = points + list(new_points)
+ return remove_duplicates(points)
+
def is_adjacent(self, cube: HyperCube) -> str | None:
adjacent = None
for (feature, [a1, b1]) in self._dimensions.items():
@@ -276,6 +331,15 @@ def merge_along_dimension(self, cube: HyperCube, feature: str) -> HyperCube:
new_cube.update_dimension(feature, (min(a1, a2), max(b1, b2)))
return new_cube
+ def merge(self, other: HyperCube) -> HyperCube:
+ new_cube = self.copy()
+ for dimension in self.dimensions.keys():
+ new_cube = new_cube.merge_along_dimension(other, dimension)
+ return new_cube
+
+ def merge_with_point(self, other: Point) -> HyperCube:
+ return self.merge(HyperCube.cube_from_point(other.dimensions))
+
# TODO: maybe two different methods are more readable and easier to debug
def overlap(self, hypercubes: Iterable[HyperCube] | HyperCube) -> HyperCube | bool | None:
if isinstance(hypercubes, Iterable):
@@ -298,10 +362,12 @@ def update_dimension(self, feature: str, lower: float | tuple[float, float], upp
self.update_dimension(feature, (lower, upper))
def update(self, dataset: pd.DataFrame, predictor) -> None:
- filtered = self._filter_dataframe(dataset.iloc[:, :-1])
+ filtered = self.filter_dataframe(dataset.iloc[:, :-1])
predictions = predictor.predict(filtered)
self._output = np.mean(predictions)
self._diversity = np.std(predictions)
+ means = filtered.describe().loc['mean']
+ self._barycenter = Point(means.index.values, means.values)
# TODO: why this is not a property?
def init_diversity(self, std: float) -> None:
@@ -313,40 +379,45 @@ def __init__(self, dimension: dict[str, tuple] = None):
super().__init__(dimension=dimension, output=LinearRegression())
def update(self, dataset: pd.DataFrame, predictor) -> None:
- filtered = self._filter_dataframe(dataset.iloc[:, :-1])
+ filtered = self.filter_dataframe(dataset.iloc[:, :-1])
if len(filtered > 0):
predictions = predictor.predict(filtered)
self._output.fit(filtered, predictions)
self._diversity = (abs(self._output.predict(filtered) - predictions)).mean()
+ means = filtered.describe().loc['mean']
+ self._barycenter = Point(means.index.values, means.values)
def copy(self) -> RegressionCube:
return RegressionCube(self.dimensions.copy())
def body(self, variables: dict[str, Var], ignore: list[str], unscale=None, normalization=None) -> Iterable[Struct]:
- intercept = self.output.intercept_ if normalization is None else \
- unscale(sum([-self.output.coef_[i] * normalization[name][0] / normalization[name][1] for i, name in
- enumerate(self.dimensions.keys())], self.output.intercept_), list(normalization.keys())[-1])
- coefs = self.output.coef_ if normalization is None else \
- [self.output.coef_[i] / normalization[name][1] for i, name in enumerate(self.dimensions.keys())]
+ intercept = self.output.intercept_ if normalization is None else unscale(sum(
+ [-self.output.coef_[i] * normalization[name][0] / normalization[name][1] for i, name in
+ enumerate(self.dimensions.keys())], self.output.intercept_), list(normalization.keys())[-1])
+ coefs = self.output.coef_ if normalization is None else [
+ self.output.coef_[i] / normalization[name][1] * normalization[list(normalization.keys())[-1]][1] for
+ i, name in enumerate(self.dimensions.keys())
+ ]
return list(super().body(variables, ignore, unscale, normalization)) + [linear_function_creator(
- list(variables.values()), [to_rounded_real(v) for v in coefs],
- to_rounded_real(intercept)
+ list(variables.values()), [to_rounded_real(v) for v in coefs], to_rounded_real(intercept)
)]
class ClassificationCube(HyperCube):
- def __init__(self, dimension: dict[str, tuple] = None):
- super().__init__(dimension=dimension)
+ def __init__(self, dimension: dict[str, tuple] = None, limits: set[Limit] = None, output: str = ""):
+ super().__init__(dimension=dimension, limits=limits, output=output)
def update(self, dataset: pd.DataFrame, predictor) -> None:
- filtered = self._filter_dataframe(dataset.iloc[:, :-1])
+ filtered = self.filter_dataframe(dataset.iloc[:, :-1])
if len(filtered > 0):
predictions = predictor.predict(filtered)
self._output = mode(predictions)
self._diversity = 1 - sum(prediction == self.output for prediction in predictions) / len(filtered)
+ means = filtered.describe().loc['mean']
+ self._barycenter = Point(means.index.values, means.values)
def copy(self) -> ClassificationCube:
- return ClassificationCube(self.dimensions.copy())
+ return ClassificationCube(self.dimensions.copy(), self._limits.copy(), self._output)
class ClosedCube(HyperCube):
diff --git a/psyke/extraction/hypercubic/iter/__init__.py b/psyke/extraction/hypercubic/iter/__init__.py
index 7f2ca76d..1e6d8237 100644
--- a/psyke/extraction/hypercubic/iter/__init__.py
+++ b/psyke/extraction/hypercubic/iter/__init__.py
@@ -5,7 +5,6 @@
import pandas as pd
from sklearn.base import ClassifierMixin
from tuprolog.theory import Theory
-from psyke import PedagogicalExtractor
from psyke.extraction.hypercubic import HyperCube, HyperCubeExtractor
from psyke.extraction.hypercubic.hypercube import GenericCube
from psyke.extraction.hypercubic.utils import MinUpdate, Expansion
diff --git a/psyke/tuning/orchid/__init__.py b/psyke/tuning/orchid/__init__.py
index d1dfe6c8..cf76eefa 100644
--- a/psyke/tuning/orchid/__init__.py
+++ b/psyke/tuning/orchid/__init__.py
@@ -57,7 +57,8 @@ def __search_threshold(self, depth):
(EvaluableModel.Task.CLASSIFICATION, EvaluableModel.ClassificationScore.INVERSE_ACCURACY) \
if self.output == Target.CLASSIFICATION else \
(EvaluableModel.Task.REGRESSION, EvaluableModel.RegressionScore.MAE)
- p, n = clustering.score(self.dataframe, None, False, False, task, [metric])[metric][0], clustering.n_rules
+ p, n = clustering.score(self.dataframe, None, False, False, task=task,
+ scoring_function=[metric])[metric][0], clustering.n_rules
print(f"Predictive loss = {p:.2f}, {n} rules")
diff --git a/psyke/tuning/pedro/__init__.py b/psyke/tuning/pedro/__init__.py
index feb57e5e..9e6aae3b 100644
--- a/psyke/tuning/pedro/__init__.py
+++ b/psyke/tuning/pedro/__init__.py
@@ -4,10 +4,10 @@
from psyke import Extractor
from psyke.extraction.hypercubic import Grid, FeatureRanker
from psyke.extraction.hypercubic.strategy import AdaptiveStrategy, FixedStrategy
-from psyke.tuning import Objective, Optimizer
+from psyke.tuning import Objective, GridOptimizer
-class PEDRO(Optimizer):
+class PEDRO(GridOptimizer):
class Algorithm(Enum):
GRIDEX = 1,
GRIDREX = 2
@@ -71,7 +71,7 @@ def __search_depth(self, strategy, critical, max_partitions):
for iterations in range(self.max_depth):
grid = Grid(iterations + 1, strategy)
p = self.__search_threshold(grid, critical, max_partitions)
- b = Optimizer._best(p)[1]
+ b = GridOptimizer._best(p)[1]
print()
improvement = self._depth_improvement(
[best[0], best[1]], [b[0], b[1]]
diff --git a/psyke/utils/logic.py b/psyke/utils/logic.py
index d606252d..e56da90a 100644
--- a/psyke/utils/logic.py
+++ b/psyke/utils/logic.py
@@ -134,6 +134,10 @@ def create_variable_list(features: list[DiscreteFeature], dataset: pd.DataFrame
return values
+def last_in_body(body: Struct) -> Struct:
+ return body.args[-1] if body.args[-1].functor == 'is' else last_in_body(body.args[-1])
+
+
def create_head(functor: str, variables: Iterable[Var], output) -> Struct:
if isinstance(output, Var):
variables += [output]
diff --git a/psyke/utils/plot.py b/psyke/utils/plot.py
index 2bcbca82..3d69f60f 100644
--- a/psyke/utils/plot.py
+++ b/psyke/utils/plot.py
@@ -7,10 +7,81 @@
from matplotlib.lines import Line2D
from tuprolog.solve.prolog import prolog_solver
from tuprolog.theory import Theory, mutable_theory
-from psyke.utils.logic import data_to_struct, pretty_theory, get_in_rule, get_not_in_rule
+
+from psyke.extraction.hypercubic import HyperCubeExtractor
+from psyke.utils.logic import data_to_struct, get_in_rule, get_not_in_rule
import matplotlib
-matplotlib.use('TkAgg')
+#matplotlib.use('TkAgg')
+
+
+def plot_init(xlim, ylim, xlabel, ylabel, size=(4, 3), equal=False):
+ plt.figure(figsize=size)
+ if equal:
+ plt.gca().set_aspect(1)
+ plt.xlim(xlim)
+ plt.ylim(ylim)
+ plt.gca().set_xlabel(xlabel)
+ plt.gca().set_ylabel(ylabel)
+ plt.gca().set_rasterized(True)
+
+
+def plot_point(x, y, color, marker):
+ plt.scatter(x, y, c=color, marker=marker)
+
+
+def plot_classification_samples(dataframe, classes, colors, markers, labels, loc, name, show=True):
+ marks = [Line2D([0], [0], color=c, marker=m, lw="0") for c, m in zip(colors, markers)]
+
+ for cl, c, m in zip(classes, colors, markers):
+ df = dataframe[dataframe.target == cl]
+ plot_point(df["petal length"], df["petal width"], c, m)
+
+ plt.gca().legend(marks, labels, loc=loc)
+ plt.savefig("plot/{}.pdf".format(name), dpi=500, bbox_inches='tight')
+ if show:
+ plt.show()
+
+
+def plot_boundaries(extractor: HyperCubeExtractor, x: str, y: str, colors: dict[str, str],
+ a: float = .5, h: str = '////////', ls='-', e=.05):
+ for cube in extractor._hypercubes:
+ plt.gca().fill_between((cube[x][0] - e, cube[x][1] + e), cube[y][0] - e, cube[y][1] + e,
+ fc='none', ec=colors[cube.output], alpha=a, hatch=h, linestyle=ls)
+
+
+def plot_surfaces(extractor: HyperCubeExtractor, x: str, y: str, colors: dict[str, str], ec='r', e=.05):
+ for cube in extractor._hypercubes:
+ plt.gca().fill_between((cube[x][0] - e, cube[x][1] + e), cube[y][0] - e, cube[y][1] + e,
+ fc='none', ec=ec)
+
+
+def plot_perimeters(extractor: HyperCubeExtractor, x: str, y: str, colors: dict[str, str], n: int = 5,
+ ec: str = 'r', m: str = '*', s: int = 60, z: float = 1e10, lw: float = 0.8):
+ for cube in extractor._hypercubes:
+ for corner in cube.perimeter_samples(n):
+ plt.scatter(corner[x], corner[y], c=colors[cube.output], marker=m, edgecolor=ec, s=s, zorder=z, linewidth=lw)
+
+
+def plot_centers(extractor: HyperCubeExtractor, x: str, y: str, colors: dict[str, str],
+ ec: str = 'r', m: str = '*', s: int = 60, z: float = 1e10, lw: float = 0.8):
+ for cube in extractor._hypercubes:
+ center = cube.center
+ plt.scatter(center[x], center[y], c=colors[cube.output], marker=m, edgecolor=ec, s=s, zorder=z, linewidth=lw)
+
+
+def plot_corners(extractor: HyperCubeExtractor, x: str, y: str, colors: dict[str, str],
+ ec: str = 'r', m: str = '*', s: int = 60, z: float = 1e10, lw: float = 0.8):
+ for cube in extractor._hypercubes:
+ for corner in cube.corners():
+ plt.scatter(corner[x], corner[y], c=colors[cube.output], marker=m, edgecolor=ec, s=s, zorder=z, linewidth=lw)
+
+
+def plot_barycenters(extractor: HyperCubeExtractor, x: str, y: str, colors: dict[str, str],
+ ec: str = 'r', m: str = '*', s: int = 60, z: float = 1e10, lw: float = 0.8):
+ for cube in extractor._hypercubes:
+ center = cube.barycenter
+ plt.scatter(center[x], center[y], c=colors[cube.output], marker=m, edgecolor=ec, s=s, zorder=z, linewidth=lw)
def predict_from_theory(theory: Theory, data: pd.DataFrame) -> list[float or str]:
@@ -95,6 +166,7 @@ def color_fader(v: float = 0., c1: str = 'green', c2: str = 'red'):
pass
# ax.text2D(0., 0.88, pretty_theory(theory, new_line=False), transform=ax.transAxes, fontsize=8)
if isinstance(ys[0], str):
- custom_lines = [Line2D([0], [0], marker='o', markerfacecolor=get_color(c), markersize=20, color='w') for c in classes]
+ custom_lines = [Line2D([0], [0], marker='o', markerfacecolor=get_color(c),
+ markersize=20, color='w') for c in classes]
ax.legend(custom_lines, classes, loc='upper left', numpoints=1, ncol=3, fontsize=18, bbox_to_anchor=(0, 0))
plt.savefig(output, format='pdf')
diff --git a/requirements.txt b/requirements.txt
index e85d46d2..bee085c2 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -11,4 +11,4 @@ parameterized==0.9.0
protobuf==4.24.3
setuptools==68.2.2
kneed==0.8.5
-sympy==1.12
\ No newline at end of file
+sympy==1.12
diff --git a/test/psyke/extraction/hypercubic/test_hypercube.py b/test/psyke/extraction/hypercubic/test_hypercube.py
index d1ee273a..ef4fcec4 100644
--- a/test/psyke/extraction/hypercubic/test_hypercube.py
+++ b/test/psyke/extraction/hypercubic/test_hypercube.py
@@ -162,7 +162,7 @@ def test_filter_dataframe(self):
expected = (self.dataset.X >= self.x[0]) & (self.dataset.X < self.x[1]) & \
(self.dataset.Y >= self.y[0]) & (self.dataset.Y < self.y[1])
expected = self.dataset[expected].iloc[:, :-1]
- filtered = self.cube._filter_dataframe(self.dataset.iloc[:, :-1])
+ filtered = self.cube.filter_dataframe(self.dataset.iloc[:, :-1])
self.assertTrue(all(expected == filtered))
def test_update(self):
@@ -225,8 +225,8 @@ def test_diagonal(self):
self.assertEqual(self.cube.diagonal(), ((self.x[1] - self.x[0])**2 + (self.y[1] - self.y[0])**2)**0.5)
def test_center(self):
- self.assertEqual(self.cube.center(), Point(list(self.dimensions.keys()),
- [(val[0] + val[1]) / 2 for val in self.dimensions.values()]))
+ self.assertEqual(self.cube.center, Point(list(self.dimensions.keys()),
+ [(val[0] + val[1]) / 2 for val in self.dimensions.values()]))
def test_corners(self):
self.assertEqual(self.cube.corners(), [