From 96cce70e7d071929065a69735993b5d6c25d7c8c Mon Sep 17 00:00:00 2001 From: Denis Arrivault <denis.arrivault@lif.univ-mrs.fr> Date: Fri, 2 Feb 2018 16:18:33 +0100 Subject: [PATCH] Adding a get_dot function in Automata + jupyter example --- VERSION | 2 +- examples/3.pautomac_light.train.dot.gv | 48 ++ examples/3.pautomac_light.train.dot.gv.pdf | Bin 0 -> 14746 bytes examples/GraphvizTests.ipynb | 776 ++++++++++++++++++ .../graphivz-output/3.pautomac_light.train.gv | 48 ++ .../3.pautomac_light.train.gv.pdf | Bin 0 -> 14746 bytes .../3.pautomac_light_man.train.gv | 48 ++ .../3.pautomac_light_man.train.gv.pdf | Bin 0 -> 14746 bytes examples/graphivz-output/round-table.gv | 9 + examples/graphivz-output/round-table.gv.pdf | Bin 0 -> 15059 bytes setup.py | 34 - splearn/__init__.py | 2 +- splearn/automaton.py | 81 +- splearn/datasets/data_sample.py | 34 - splearn/hankel.py | 34 - splearn/spectral.py | 34 - splearn/tests/datasets/get_dataset_path.py | 34 - splearn/tests/test_automaton.py | 34 - splearn/tests/test_base.py | 34 - splearn/tests/test_data_sample.py | 34 - splearn/tests/test_hankel.py | 34 - splearn/tests/test_spectral.py | 34 - 22 files changed, 978 insertions(+), 376 deletions(-) create mode 100644 examples/3.pautomac_light.train.dot.gv create mode 100644 examples/3.pautomac_light.train.dot.gv.pdf create mode 100644 examples/GraphvizTests.ipynb create mode 100644 examples/graphivz-output/3.pautomac_light.train.gv create mode 100644 examples/graphivz-output/3.pautomac_light.train.gv.pdf create mode 100644 examples/graphivz-output/3.pautomac_light_man.train.gv create mode 100644 examples/graphivz-output/3.pautomac_light_man.train.gv.pdf create mode 100644 examples/graphivz-output/round-table.gv create mode 100644 examples/graphivz-output/round-table.gv.pdf diff --git a/VERSION b/VERSION index ad13d99..e19bf06 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -splearn:1.0.1 \ No newline at end of file +splearn:1.1.0 \ No newline at end of file diff --git a/examples/3.pautomac_light.train.dot.gv b/examples/3.pautomac_light.train.dot.gv new file mode 100644 index 0000000..c3ac1dc --- /dev/null +++ b/examples/3.pautomac_light.train.dot.gv @@ -0,0 +1,48 @@ +//3.pautomac_light.train.dot +digraph { + 0 [label="0 +______ +> -0.00 +0.08 >"] + 1 [label="1 +______ +> 0.00 +-0.02 >"] + 2 [label="2 +______ +> -0.04 +-0.45 >"] + 3 [label="3 +______ +> -0.11 +0.63 >"] + 4 [label="4 +______ +> -0.09 +-0.55 >"] + 0 -> 1 [label="0:-0.24"] + 0 -> 2 [label="0:0.35"] + 0 -> 3 [label="0:-0.28"] + 0 -> 4 [label="0:-0.21"] + 1 -> 1 [label="0:-0.30"] + 1 -> 2 [label="0:0.21"] + 1 -> 4 [label="0:-0.56"] + 2 -> 3 [label="0:-0.21"] + 4 -> 4 [label="0:0.24"] + 0 -> 2 [label="1:-0.30"] + 0 -> 3 [label="1:0.28"] + 0 -> 4 [label="1:0.20"] + 1 -> 2 [label="1:0.26"] + 0 -> 2 [label="2:0.38"] + 0 -> 3 [label="2:-0.22"] + 0 -> 4 [label="2:-0.23"] + 1 -> 4 [label="2:0.35"] + 1 -> 2 [label="3:0.28"] + 1 -> 3 [label="3:-0.24"] + 2 -> 2 [label="3:-0.63"] + 2 -> 3 [label="3:0.47"] + 3 -> 2 [label="3:-0.37"] + 3 -> 4 [label="3:0.65"] + 4 -> 3 [label="3:-0.38"] + 4 -> 4 [label="3:0.66"] +} diff --git a/examples/3.pautomac_light.train.dot.gv.pdf b/examples/3.pautomac_light.train.dot.gv.pdf new file mode 100644 index 0000000000000000000000000000000000000000..ec0f99e07bfcdac4b0e0c21fe5c94795515f90c1 GIT binary patch literal 14746 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 I>hHz{00+7hwg3PC literal 0 HcmV?d00001 diff --git a/examples/GraphvizTests.ipynb b/examples/GraphvizTests.ipynb new file mode 100644 index 0000000..e5b19df --- /dev/null +++ b/examples/GraphvizTests.ipynb @@ -0,0 +1,776 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from graphviz import Digraph\n", + "from graphviz import Source\n", + "from splearn.datasets.base import load_data_sample\n", + "from splearn.tests.datasets.get_dataset_path import get_dataset_path" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "train_file = '3.pautomac_light.train'\n", + "data = load_data_sample(adr=get_dataset_path(train_file))" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "4" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "data.nbL" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "5000" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "data.nbEx" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Splearn_array([[ 3., 0., 3., ..., -1., -1., -1.],\n", + " [ 3., 3., -1., ..., -1., -1., -1.],\n", + " [ 3., 2., 0., ..., -1., -1., -1.],\n", + " ...,\n", + " [ 3., 1., 3., ..., -1., -1., -1.],\n", + " [ 3., 0., 3., ..., -1., -1., -1.],\n", + " [ 3., 3., 1., ..., -1., -1., -1.]])" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "data.data" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "from splearn import Learning, Hankel , Spectral" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Start Hankel matrix computation\n", + "End of Hankel matrix computation\n", + "Start Building Automaton from Hankel matrix\n", + "End of Automaton computation\n" + ] + }, + { + "data": { + "text/plain": [ + "Spectral(lcolumns=7, lrows=7, mode_quiet=False, partial=True, rank=5,\n", + " smooth_method='none', sparse=True, version='classic')" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sp = Spectral()\n", + "sp.fit(X=data.data)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "A = sp.Automaton" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([-0.00049344, 0.00306347, -0.04407393, -0.10777703, -0.08663914])" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "A.initial" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([ 0.07757137, -0.02422029, -0.44681254, 0.62773208, -0.55467443])" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "A.final" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[array([[ 0.04512121, -0.2403897 , 0.34945 , -0.28116807, -0.21402523],\n", + " [ 0.06925801, -0.30062293, 0.20641375, -0.14960814, -0.55805732],\n", + " [ 0.02980115, -0.13866481, 0.18362213, -0.20969545, -0.14481622],\n", + " [ 0.00569934, -0.02338583, -0.06600665, 0.10749935, -0.15103655],\n", + " [-0.02008655, 0.09026348, -0.00552559, -0.03135532, 0.24329022]]),\n", + " array([[ 0.07744772, 0.09007074, -0.30472201, 0.27676245, 0.20289396],\n", + " [-0.0990298 , -0.08061847, 0.25853171, -0.1208633 , -0.11085208],\n", + " [-0.06171079, -0.06244152, 0.12007655, 0.00250637, -0.15679675],\n", + " [-0.00273697, -0.00900572, -0.00046003, -0.00855043, -0.05375465],\n", + " [ 0.03098733, 0.0397268 , -0.04997113, 0.00357694, 0.14182576]]),\n", + " array([[-0.06791915, -0.11357938, 0.37955393, -0.2178498 , -0.22977695],\n", + " [ 0.11596642, 0.14914957, -0.13357508, -0.00891606, 0.34841537],\n", + " [ 0.01173082, 0.0192738 , 0.04142658, -0.03534659, 0.02316491],\n", + " [ 0.00732891, 0.00553651, -0.02245608, 0.03611543, -0.03851434],\n", + " [-0.01058989, -0.01062662, -0.00054311, -0.02556748, 0.04984889]]),\n", + " array([[ 0.07276211, -0.01571956, 0.07428593, -0.10369862, 0.02475347],\n", + " [-0.05607105, -0.08896207, 0.27638225, -0.23711256, 0.07372294],\n", + " [-0.00739129, -0.0487418 , -0.62912397, 0.46816277, 0.09251699],\n", + " [-0.00711022, -0.05623318, -0.36606659, -0.0132978 , 0.64910332],\n", + " [ 0.00233552, -0.02156115, 0.09096243, -0.38438823, 0.66164772]])]" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "A.transitions" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'classic'" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "A.type" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "4" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "A.nbL" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "5" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "A.nbS" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "th = 0.2\n", + "wa = Digraph(comment='3.pautomac_light.train')\n", + "for i in range(A.nbS):\n", + " label = \"{0:d}\\n______\\n> {1:.2f}\\n{2:.2f} >\".format(i, A.initial[i], A.final[i])\n", + " wa.node(str(i),label)\n", + "for l in range(A.nbL):\n", + " for i in range(A.nbS):\n", + " for j in range(A.nbS):\n", + " weight = A.transitions[l][i,j]\n", + " if (np.abs(weight) > th):\n", + " label = \"{0:d}:{1:.2f}\".format(l,weight)\n", + " wa.edge(str(i), str(j), label)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "// 3.pautomac_light.train\n", + "digraph {\n", + "\t0 [label=\"0\n", + "______\n", + "> -0.00\n", + "0.08 >\"]\n", + "\t1 [label=\"1\n", + "______\n", + "> 0.00\n", + "-0.02 >\"]\n", + "\t2 [label=\"2\n", + "______\n", + "> -0.04\n", + "-0.45 >\"]\n", + "\t3 [label=\"3\n", + "______\n", + "> -0.11\n", + "0.63 >\"]\n", + "\t4 [label=\"4\n", + "______\n", + "> -0.09\n", + "-0.55 >\"]\n", + "\t0 -> 1 [label=\"0:-0.24\"]\n", + "\t0 -> 2 [label=\"0:0.35\"]\n", + "\t0 -> 3 [label=\"0:-0.28\"]\n", + "\t0 -> 4 [label=\"0:-0.21\"]\n", + "\t1 -> 1 [label=\"0:-0.30\"]\n", + "\t1 -> 2 [label=\"0:0.21\"]\n", + "\t1 -> 4 [label=\"0:-0.56\"]\n", + "\t2 -> 3 [label=\"0:-0.21\"]\n", + "\t4 -> 4 [label=\"0:0.24\"]\n", + "\t0 -> 2 [label=\"1:-0.30\"]\n", + "\t0 -> 3 [label=\"1:0.28\"]\n", + "\t0 -> 4 [label=\"1:0.20\"]\n", + "\t1 -> 2 [label=\"1:0.26\"]\n", + "\t0 -> 2 [label=\"2:0.38\"]\n", + "\t0 -> 3 [label=\"2:-0.22\"]\n", + "\t0 -> 4 [label=\"2:-0.23\"]\n", + "\t1 -> 4 [label=\"2:0.35\"]\n", + "\t1 -> 2 [label=\"3:0.28\"]\n", + "\t1 -> 3 [label=\"3:-0.24\"]\n", + "\t2 -> 2 [label=\"3:-0.63\"]\n", + "\t2 -> 3 [label=\"3:0.47\"]\n", + "\t3 -> 2 [label=\"3:-0.37\"]\n", + "\t3 -> 4 [label=\"3:0.65\"]\n", + "\t4 -> 3 [label=\"3:-0.38\"]\n", + "\t4 -> 4 [label=\"3:0.66\"]\n", + "}\n" + ] + } + ], + "source": [ + "print(wa.source)" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "//automata.dot\n", + "digraph {\n", + "\t0 [label=\"0\n", + "______\n", + "> -0.00\n", + "0.08 >\"]\n", + "\t1 [label=\"1\n", + "______\n", + "> 0.00\n", + "-0.02 >\"]\n", + "\t2 [label=\"2\n", + "______\n", + "> -0.04\n", + "-0.45 >\"]\n", + "\t3 [label=\"3\n", + "______\n", + "> -0.11\n", + "0.63 >\"]\n", + "\t4 [label=\"4\n", + "______\n", + "> -0.09\n", + "-0.55 >\"]\n", + "\t0 -> 1 [label=\"0:-0.24\"]\n", + "\t0 -> 2 [label=\"0:0.35\"]\n", + "\t0 -> 3 [label=\"0:-0.28\"]\n", + "\t0 -> 4 [label=\"0:-0.21\"]\n", + "\t1 -> 1 [label=\"0:-0.30\"]\n", + "\t1 -> 2 [label=\"0:0.21\"]\n", + "\t1 -> 4 [label=\"0:-0.56\"]\n", + "\t2 -> 3 [label=\"0:-0.21\"]\n", + "\t4 -> 4 [label=\"0:0.24\"]\n", + "\t0 -> 2 [label=\"1:-0.30\"]\n", + "\t0 -> 3 [label=\"1:0.28\"]\n", + "\t0 -> 4 [label=\"1:0.20\"]\n", + "\t1 -> 2 [label=\"1:0.26\"]\n", + "\t0 -> 2 [label=\"2:0.38\"]\n", + "\t0 -> 3 [label=\"2:-0.22\"]\n", + "\t0 -> 4 [label=\"2:-0.23\"]\n", + "\t1 -> 4 [label=\"2:0.35\"]\n", + "\t1 -> 2 [label=\"3:0.28\"]\n", + "\t1 -> 3 [label=\"3:-0.24\"]\n", + "\t2 -> 2 [label=\"3:-0.63\"]\n", + "\t2 -> 3 [label=\"3:0.47\"]\n", + "\t3 -> 2 [label=\"3:-0.37\"]\n", + "\t3 -> 4 [label=\"3:0.65\"]\n", + "\t4 -> 3 [label=\"3:-0.38\"]\n", + "\t4 -> 4 [label=\"3:0.66\"]\n", + "}\n", + "\n" + ] + } + ], + "source": [ + "nb_dec = 2\n", + "threshold = th\n", + "filename = \"automata.dot\"\n", + "prec = \".{:d}f\".format(nb_dec)\n", + "out = \"//{:s}\\ndigraph {{\\n\".format(filename)\n", + "for i in range(A.nbS):\n", + " label = \"{0:d}\\n______\\n> {1:\" + prec + \"}\\n{2:\" + prec + \"} >\"\n", + " label = label.format(i, A.initial[i], A.final[i])\n", + " out += \"\\t{0:d} [label=\\\"\".format(i)\n", + " out += label + \"\\\"]\\n\"\n", + "for l in range(A.nbL):\n", + " for i in range(A.nbS):\n", + " for j in range(A.nbS):\n", + " weight = A.transitions[l][i,j]\n", + " if (np.abs(weight) > threshold):\n", + " label = \"{0:d}:{1:\" + prec + \"}\"\n", + " label = label.format(l,weight)\n", + " out += \"\\t{0:d} -> {1:d} [label=\\\"\".format(i,j)\n", + " out += label + \"\\\"]\\n\"\n", + "out += \"}\\n\"\n", + "print(out)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n", + "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n", + " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n", + "<!-- Generated by graphviz version 2.38.0 (20140413.2041)\n", + " -->\n", + "<!-- Title: %3 Pages: 1 -->\n", + "<svg width=\"769pt\" height=\"693pt\"\n", + " viewBox=\"0.00 0.00 769.23 692.83\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n", + "<g id=\"graph0\" class=\"graph\" transform=\"scale(1 1) rotate(0) translate(4 688.833)\">\n", + "<title>%3</title>\n", + "<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-688.833 765.226,-688.833 765.226,4 -4,4\"/>\n", + "<!-- 0 -->\n", + "<g id=\"node1\" class=\"node\"><title>0</title>\n", + "<ellipse fill=\"none\" stroke=\"black\" cx=\"454.226\" cy=\"-636.749\" rx=\"40.1111\" ry=\"48.1667\"/>\n", + "<text text-anchor=\"middle\" x=\"454.226\" y=\"-655.549\" font-family=\"Times,serif\" font-size=\"14.00\">0</text>\n", + "<text text-anchor=\"middle\" x=\"454.226\" y=\"-640.549\" font-family=\"Times,serif\" font-size=\"14.00\">______</text>\n", + "<text text-anchor=\"middle\" x=\"454.226\" y=\"-625.549\" font-family=\"Times,serif\" font-size=\"14.00\">> -0.00</text>\n", + "<text text-anchor=\"middle\" x=\"454.226\" y=\"-610.549\" font-family=\"Times,serif\" font-size=\"14.00\">0.08 ></text>\n", + "</g>\n", + "<!-- 1 -->\n", + "<g id=\"node2\" class=\"node\"><title>1</title>\n", + "<ellipse fill=\"none\" stroke=\"black\" cx=\"91.2259\" cy=\"-489.583\" rx=\"40.1111\" ry=\"48.1667\"/>\n", + "<text text-anchor=\"middle\" x=\"91.2259\" y=\"-508.383\" font-family=\"Times,serif\" font-size=\"14.00\">1</text>\n", + "<text text-anchor=\"middle\" x=\"91.2259\" y=\"-493.383\" font-family=\"Times,serif\" font-size=\"14.00\">______</text>\n", + "<text text-anchor=\"middle\" x=\"91.2259\" y=\"-478.383\" font-family=\"Times,serif\" font-size=\"14.00\">> 0.00</text>\n", + "<text text-anchor=\"middle\" x=\"91.2259\" y=\"-463.383\" font-family=\"Times,serif\" font-size=\"14.00\">-0.02 ></text>\n", + "</g>\n", + "<!-- 0->1 -->\n", + "<g id=\"edge1\" class=\"edge\"><title>0->1</title>\n", + "<path fill=\"none\" stroke=\"black\" d=\"M413.762,-633.458C356.474,-628.716 249.94,-614.281 171.226,-570.666 154.111,-561.183 138.209,-546.963 125.164,-533.125\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"127.545,-530.542 118.221,-525.509 122.371,-535.257 127.545,-530.542\"/>\n", + "<text text-anchor=\"middle\" x=\"191.226\" y=\"-559.466\" font-family=\"Times,serif\" font-size=\"14.00\">0:-0.24</text>\n", + "</g>\n", + "<!-- 2 -->\n", + "<g id=\"node3\" class=\"node\"><title>2</title>\n", + "<ellipse fill=\"none\" stroke=\"black\" cx=\"271.226\" cy=\"-342.416\" rx=\"40.1111\" ry=\"48.1667\"/>\n", + "<text text-anchor=\"middle\" x=\"271.226\" y=\"-361.216\" font-family=\"Times,serif\" font-size=\"14.00\">2</text>\n", + "<text text-anchor=\"middle\" x=\"271.226\" y=\"-346.216\" font-family=\"Times,serif\" font-size=\"14.00\">______</text>\n", + "<text text-anchor=\"middle\" x=\"271.226\" y=\"-331.216\" font-family=\"Times,serif\" font-size=\"14.00\">> -0.04</text>\n", + "<text text-anchor=\"middle\" x=\"271.226\" y=\"-316.216\" font-family=\"Times,serif\" font-size=\"14.00\">-0.45 ></text>\n", + "</g>\n", + "<!-- 0->2 -->\n", + "<g id=\"edge2\" class=\"edge\"><title>0->2</title>\n", + "<path fill=\"none\" stroke=\"black\" d=\"M413.716,-631.974C360.806,-624.502 271.16,-602.428 239.226,-537.666 220.324,-499.332 225.355,-481.927 239.226,-441.5 242.515,-431.913 248.899,-432.665 253.226,-423.5 256.729,-416.079 259.567,-407.944 261.862,-399.793\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"265.308,-400.444 264.4,-389.888 258.527,-398.706 265.308,-400.444\"/>\n", + "<text text-anchor=\"middle\" x=\"256.726\" y=\"-485.883\" font-family=\"Times,serif\" font-size=\"14.00\">0:0.35</text>\n", + "</g>\n", + "<!-- 0->2 -->\n", + "<g id=\"edge10\" class=\"edge\"><title>0->2</title>\n", + "<path fill=\"none\" stroke=\"black\" d=\"M416.405,-620.115C383.087,-604.321 335.967,-576.672 310.226,-537.666 283.416,-497.041 274.329,-441.975 271.563,-400.846\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"275.049,-400.494 270.989,-390.707 268.06,-400.889 275.049,-400.494\"/>\n", + "<text text-anchor=\"middle\" x=\"330.226\" y=\"-485.883\" font-family=\"Times,serif\" font-size=\"14.00\">1:-0.30</text>\n", + "</g>\n", + "<!-- 0->2 -->\n", + "<g id=\"edge14\" class=\"edge\"><title>0->2</title>\n", + "<path fill=\"none\" stroke=\"black\" d=\"M426.805,-600.768C413.418,-582.624 397.756,-559.695 386.226,-537.666 365.062,-497.233 372.828,-481.147 350.226,-441.5 338.394,-420.744 322.27,-399.838 307.674,-382.691\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"310.287,-380.362 301.096,-375.092 304.994,-384.943 310.287,-380.362\"/>\n", + "<text text-anchor=\"middle\" x=\"403.726\" y=\"-485.883\" font-family=\"Times,serif\" font-size=\"14.00\">2:0.38</text>\n", + "</g>\n", + "<!-- 3 -->\n", + "<g id=\"node4\" class=\"node\"><title>3</title>\n", + "<ellipse fill=\"none\" stroke=\"black\" cx=\"379.226\" cy=\"-195.25\" rx=\"40.1111\" ry=\"48.1667\"/>\n", + "<text text-anchor=\"middle\" x=\"379.226\" y=\"-214.05\" font-family=\"Times,serif\" font-size=\"14.00\">3</text>\n", + "<text text-anchor=\"middle\" x=\"379.226\" y=\"-199.05\" font-family=\"Times,serif\" font-size=\"14.00\">______</text>\n", + "<text text-anchor=\"middle\" x=\"379.226\" y=\"-184.05\" font-family=\"Times,serif\" font-size=\"14.00\">> -0.11</text>\n", + "<text text-anchor=\"middle\" x=\"379.226\" y=\"-169.05\" font-family=\"Times,serif\" font-size=\"14.00\">0.63 ></text>\n", + "</g>\n", + "<!-- 0->3 -->\n", + "<g id=\"edge3\" class=\"edge\"><title>0->3</title>\n", + "<path fill=\"none\" stroke=\"black\" d=\"M452.202,-588.563C449.086,-548.16 441.192,-489.137 421.226,-441.5 417.411,-432.398 411.851,-432.678 408.226,-423.5 402.101,-407.994 391.559,-315.319 385.014,-253.21\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"388.482,-252.721 383.959,-243.14 381.52,-253.45 388.482,-252.721\"/>\n", + "<text text-anchor=\"middle\" x=\"428.226\" y=\"-412.3\" font-family=\"Times,serif\" font-size=\"14.00\">0:-0.28</text>\n", + "</g>\n", + "<!-- 0->3 -->\n", + "<g id=\"edge11\" class=\"edge\"><title>0->3</title>\n", + "<path fill=\"none\" stroke=\"black\" d=\"M458.728,-588.765C459.333,-577.901 459.626,-566.385 459.226,-555.666 456.78,-490.122 460.9,-472.853 448.226,-408.5 437.216,-352.597 416.089,-290.887 400.1,-248.485\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"403.294,-247.039 396.464,-238.94 396.753,-249.531 403.294,-247.039\"/>\n", + "<text text-anchor=\"middle\" x=\"467.726\" y=\"-412.3\" font-family=\"Times,serif\" font-size=\"14.00\">1:0.28</text>\n", + "</g>\n", + "<!-- 0->3 -->\n", + "<g id=\"edge15\" class=\"edge\"><title>0->3</title>\n", + "<path fill=\"none\" stroke=\"black\" d=\"M469.799,-592.029C484.073,-546.158 501.295,-472.031 489.226,-408.5 477.258,-345.499 439.666,-281.229 411.741,-240.172\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"414.503,-238.013 405.941,-231.772 408.743,-241.99 414.503,-238.013\"/>\n", + "<text text-anchor=\"middle\" x=\"511.226\" y=\"-412.3\" font-family=\"Times,serif\" font-size=\"14.00\">2:-0.22</text>\n", + "</g>\n", + "<!-- 4 -->\n", + "<g id=\"node5\" class=\"node\"><title>4</title>\n", + "<ellipse fill=\"none\" stroke=\"black\" cx=\"442.226\" cy=\"-48.0833\" rx=\"40.1111\" ry=\"48.1667\"/>\n", + "<text text-anchor=\"middle\" x=\"442.226\" y=\"-66.8833\" font-family=\"Times,serif\" font-size=\"14.00\">4</text>\n", + "<text text-anchor=\"middle\" x=\"442.226\" y=\"-51.8833\" font-family=\"Times,serif\" font-size=\"14.00\">______</text>\n", + "<text text-anchor=\"middle\" x=\"442.226\" y=\"-36.8833\" font-family=\"Times,serif\" font-size=\"14.00\">> -0.09</text>\n", + "<text text-anchor=\"middle\" x=\"442.226\" y=\"-21.8833\" font-family=\"Times,serif\" font-size=\"14.00\">-0.55 ></text>\n", + "</g>\n", + "<!-- 0->4 -->\n", + "<g id=\"edge4\" class=\"edge\"><title>0->4</title>\n", + "<path fill=\"none\" stroke=\"black\" d=\"M477.607,-597.504C482.438,-588.842 487.257,-579.57 491.226,-570.666 507.101,-535.055 530.584,-456.273 535.226,-423.5 551.99,-305.134 500.17,-169.815 467.252,-98.7205\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"470.36,-97.1038 462.941,-89.5402 464.024,-100.08 470.36,-97.1038\"/>\n", + "<text text-anchor=\"middle\" x=\"558.226\" y=\"-338.716\" font-family=\"Times,serif\" font-size=\"14.00\">0:-0.21</text>\n", + "</g>\n", + "<!-- 0->4 -->\n", + "<g id=\"edge12\" class=\"edge\"><title>0->4</title>\n", + "<path fill=\"none\" stroke=\"black\" d=\"M493.889,-625.691C551.161,-608.509 650.226,-567.65 650.226,-490.583 650.226,-490.583 650.226,-490.583 650.226,-194.25 650.226,-117.288 553.282,-77.7506 491.761,-60.4088\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"492.406,-56.9574 481.839,-57.7163 490.573,-63.7131 492.406,-56.9574\"/>\n", + "<text text-anchor=\"middle\" x=\"667.726\" y=\"-338.716\" font-family=\"Times,serif\" font-size=\"14.00\">1:0.20</text>\n", + "</g>\n", + "<!-- 0->4 -->\n", + "<g id=\"edge16\" class=\"edge\"><title>0->4</title>\n", + "<path fill=\"none\" stroke=\"black\" d=\"M494.488,-632.238C569.076,-623.292 721.226,-592.546 721.226,-490.583 721.226,-490.583 721.226,-490.583 721.226,-194.25 721.226,-92.4819 573.338,-61.9517 492.904,-52.8728\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"492.809,-49.3435 482.497,-51.7751 492.075,-56.3048 492.809,-49.3435\"/>\n", + "<text text-anchor=\"middle\" x=\"741.226\" y=\"-338.716\" font-family=\"Times,serif\" font-size=\"14.00\">2:-0.23</text>\n", + "</g>\n", + "<!-- 1->1 -->\n", + "<g id=\"edge5\" class=\"edge\"><title>1->1</title>\n", + "<path fill=\"none\" stroke=\"black\" d=\"M130.19,-503.016C141.132,-502.428 149.531,-497.95 149.531,-489.583 149.531,-484.092 145.914,-480.276 140.335,-478.135\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"140.676,-474.636 130.19,-476.15 139.332,-481.505 140.676,-474.636\"/>\n", + "<text text-anchor=\"middle\" x=\"169.531\" y=\"-485.883\" font-family=\"Times,serif\" font-size=\"14.00\">0:-0.30</text>\n", + "</g>\n", + "<!-- 1->2 -->\n", + "<g id=\"edge6\" class=\"edge\"><title>1->2</title>\n", + "<path fill=\"none\" stroke=\"black\" d=\"M92.1967,-441.117C94.4462,-429.435 98.6615,-417.663 106.226,-408.5 134.628,-374.095 183.729,-357.787 221.004,-350.112\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"222.011,-353.483 231.177,-348.168 220.698,-346.607 222.011,-353.483\"/>\n", + "<text text-anchor=\"middle\" x=\"123.726\" y=\"-412.3\" font-family=\"Times,serif\" font-size=\"14.00\">0:0.21</text>\n", + "</g>\n", + "<!-- 1->2 -->\n", + "<g id=\"edge13\" class=\"edge\"><title>1->2</title>\n", + "<path fill=\"none\" stroke=\"black\" d=\"M118.753,-454.187C131.671,-439.203 147.818,-422.016 164.226,-408.5 183,-393.035 205.798,-378.658 225.518,-367.371\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"227.338,-370.363 234.337,-362.41 223.905,-364.263 227.338,-370.363\"/>\n", + "<text text-anchor=\"middle\" x=\"181.726\" y=\"-412.3\" font-family=\"Times,serif\" font-size=\"14.00\">1:0.26</text>\n", + "</g>\n", + "<!-- 1->2 -->\n", + "<g id=\"edge18\" class=\"edge\"><title>1->2</title>\n", + "<path fill=\"none\" stroke=\"black\" d=\"M128.266,-469.839C149.989,-457.997 177.369,-441.554 199.226,-423.5 212.595,-412.456 225.728,-398.902 237.041,-386.107\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"239.931,-388.117 243.835,-378.268 234.641,-383.532 239.931,-388.117\"/>\n", + "<text text-anchor=\"middle\" x=\"231.726\" y=\"-412.3\" font-family=\"Times,serif\" font-size=\"14.00\">3:0.28</text>\n", + "</g>\n", + "<!-- 1->3 -->\n", + "<g id=\"edge19\" class=\"edge\"><title>1->3</title>\n", + "<path fill=\"none\" stroke=\"black\" d=\"M58.6787,-460.48C48.705,-449.963 38.8801,-437.212 33.2259,-423.5 5.7168,-356.787 -20.957,-316.781 25.2259,-261.333 63.262,-215.666 240.22,-201.931 328.651,-197.887\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"328.885,-201.381 338.724,-197.451 328.582,-194.387 328.885,-201.381\"/>\n", + "<text text-anchor=\"middle\" x=\"39.2259\" y=\"-338.716\" font-family=\"Times,serif\" font-size=\"14.00\">3:-0.24</text>\n", + "</g>\n", + "<!-- 1->4 -->\n", + "<g id=\"edge7\" class=\"edge\"><title>1->4</title>\n", + "<path fill=\"none\" stroke=\"black\" d=\"M70.1223,-448.415C66.6297,-440.348 63.433,-431.796 61.2259,-423.5 42.6367,-353.625 36.8748,-332.742 48.2259,-261.333 59.0265,-193.388 44.5356,-159.569 96.2259,-114.167 139.484,-76.1709 306.454,-58.8513 391.628,-52.3534\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"392.13,-55.8259 401.844,-51.5961 391.612,-48.845 392.13,-55.8259\"/>\n", + "<text text-anchor=\"middle\" x=\"68.2259\" y=\"-265.133\" font-family=\"Times,serif\" font-size=\"14.00\">0:-0.56</text>\n", + "</g>\n", + "<!-- 1->4 -->\n", + "<g id=\"edge17\" class=\"edge\"><title>1->4</title>\n", + "<path fill=\"none\" stroke=\"black\" d=\"M88.146,-441.308C88.5952,-430.35 90.0294,-418.866 93.2259,-408.5 116.165,-334.105 136.66,-319.658 188.226,-261.333 253.622,-187.364 345.645,-117.08 399.099,-78.852\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"401.214,-81.6427 407.337,-72.9962 397.158,-75.9373 401.214,-81.6427\"/>\n", + "<text text-anchor=\"middle\" x=\"205.726\" y=\"-265.133\" font-family=\"Times,serif\" font-size=\"14.00\">2:0.35</text>\n", + "</g>\n", + "<!-- 2->2 -->\n", + "<g id=\"edge20\" class=\"edge\"><title>2->2</title>\n", + "<path fill=\"none\" stroke=\"black\" d=\"M310.19,-355.85C321.132,-355.261 329.531,-350.783 329.531,-342.416 329.531,-336.925 325.914,-333.109 320.335,-330.969\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"320.676,-327.469 310.19,-328.983 319.332,-334.339 320.676,-327.469\"/>\n", + "<text text-anchor=\"middle\" x=\"349.531\" y=\"-338.716\" font-family=\"Times,serif\" font-size=\"14.00\">3:-0.63</text>\n", + "</g>\n", + "<!-- 2->3 -->\n", + "<g id=\"edge8\" class=\"edge\"><title>2->3</title>\n", + "<path fill=\"none\" stroke=\"black\" d=\"M241.048,-310.41C229.908,-295.145 222.187,-276.756 232.226,-261.333 253.475,-228.687 295.245,-212.293 328.845,-204.133\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"329.99,-207.463 338.979,-201.856 328.455,-200.634 329.99,-207.463\"/>\n", + "<text text-anchor=\"middle\" x=\"252.226\" y=\"-265.133\" font-family=\"Times,serif\" font-size=\"14.00\">0:-0.21</text>\n", + "</g>\n", + "<!-- 2->3 -->\n", + "<g id=\"edge21\" class=\"edge\"><title>2->3</title>\n", + "<path fill=\"none\" stroke=\"black\" d=\"M279.828,-295.156C283.373,-283.464 288.328,-271.386 295.226,-261.333 305.522,-246.328 320.355,-233.224 334.7,-222.783\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"336.858,-225.545 343.051,-216.949 332.849,-219.806 336.858,-225.545\"/>\n", + "<text text-anchor=\"middle\" x=\"312.726\" y=\"-265.133\" font-family=\"Times,serif\" font-size=\"14.00\">3:0.47</text>\n", + "</g>\n", + "<!-- 3->2 -->\n", + "<g id=\"edge22\" class=\"edge\"><title>3->2</title>\n", + "<path fill=\"none\" stroke=\"black\" d=\"M356.967,-235.908C349.033,-249.115 339.703,-263.678 330.226,-276.333 323.577,-285.212 315.943,-294.3 308.422,-302.76\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"305.688,-300.565 301.577,-310.33 310.88,-305.26 305.688,-300.565\"/>\n", + "<text text-anchor=\"middle\" x=\"360.226\" y=\"-265.133\" font-family=\"Times,serif\" font-size=\"14.00\">3:-0.37</text>\n", + "</g>\n", + "<!-- 3->4 -->\n", + "<g id=\"edge23\" class=\"edge\"><title>3->4</title>\n", + "<path fill=\"none\" stroke=\"black\" d=\"M404.82,-157.78C410.438,-148.714 415.971,-138.82 420.226,-129.167 423.653,-121.39 426.668,-112.95 429.28,-104.564\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"432.691,-105.368 432.16,-94.7864 425.977,-103.39 432.691,-105.368\"/>\n", + "<text text-anchor=\"middle\" x=\"442.726\" y=\"-117.967\" font-family=\"Times,serif\" font-size=\"14.00\">3:0.65</text>\n", + "</g>\n", + "<!-- 4->3 -->\n", + "<g id=\"edge24\" class=\"edge\"><title>4->3</title>\n", + "<path fill=\"none\" stroke=\"black\" d=\"M407.931,-73.4177C395.491,-84.3055 382.871,-98.2815 376.226,-114.167 373.096,-121.649 371.547,-129.877 371.021,-138.122\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"367.522,-138.081 370.85,-148.139 374.521,-138.201 367.522,-138.081\"/>\n", + "<text text-anchor=\"middle\" x=\"396.226\" y=\"-117.967\" font-family=\"Times,serif\" font-size=\"14.00\">3:-0.38</text>\n", + "</g>\n", + "<!-- 4->4 -->\n", + "<g id=\"edge9\" class=\"edge\"><title>4->4</title>\n", + "<path fill=\"none\" stroke=\"black\" d=\"M482.285,-54.7636C492.687,-54.353 500.531,-52.1262 500.531,-48.0833 500.531,-45.4932 497.312,-43.6486 492.263,-42.5493\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"492.619,-39.0672 482.285,-41.4029 491.82,-46.0214 492.619,-39.0672\"/>\n", + "<text text-anchor=\"middle\" x=\"518.031\" y=\"-44.3833\" font-family=\"Times,serif\" font-size=\"14.00\">0:0.24</text>\n", + "</g>\n", + "<!-- 4->4 -->\n", + "<g id=\"edge25\" class=\"edge\"><title>4->4</title>\n", + "<path fill=\"none\" stroke=\"black\" d=\"M481.459,-60.5739C508.016,-63.7077 535.531,-59.5442 535.531,-48.0833 535.531,-38.0997 514.652,-33.6535 491.715,-34.7445\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"491.136,-31.2804 481.459,-35.5926 491.713,-38.2566 491.136,-31.2804\"/>\n", + "<text text-anchor=\"middle\" x=\"553.031\" y=\"-44.3833\" font-family=\"Times,serif\" font-size=\"14.00\">3:0.66</text>\n", + "</g>\n", + "</g>\n", + "</svg>\n" + ], + "text/plain": [ + "<graphviz.files.Source at 0x7f25558204a8>" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "wa.render('graphivz-output/3.pautomac_light.train.gv', view=False)\n", + "Source.from_file(\"graphivz-output/3.pautomac_light.train.gv\")" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [], + "source": [ + "src = Source(out)" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'graphivz-output/3.pautomac_light_man.train.gv.pdf'" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "src.render('graphivz-output/3.pautomac_light_man.train.gv', view=True) " + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Start Hankel matrix computation\n", + "End of Hankel matrix computation\n", + "Start Building Automaton from Hankel matrix\n", + "End of Automaton computation\n" + ] + }, + { + "data": { + "text/plain": [ + "'3.pautomac_light.train.dot.gv.pdf'" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from splearn.datasets.base import load_data_sample\n", + "from splearn.tests.datasets.get_dataset_path import get_dataset_path\n", + "from splearn import Spectral\n", + "train_file = '3.pautomac_light.train'\n", + "data = load_data_sample(adr=get_dataset_path(train_file))\n", + "sp = Spectral()\n", + "sp.fit(X=data.data)\n", + "dotfile = \"3.pautomac_light.train.dot\"\n", + "dot = sp.Automaton.get_dot(threshold = 0.2, title = dotfile)\n", + "# To display the dot string one can use graphviz:\n", + "from graphviz import Source\n", + "src = Source(dot)\n", + "src.render(dotfile + '.gv', view=True) " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "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.6.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/examples/graphivz-output/3.pautomac_light.train.gv b/examples/graphivz-output/3.pautomac_light.train.gv new file mode 100644 index 0000000..4e539a2 --- /dev/null +++ b/examples/graphivz-output/3.pautomac_light.train.gv @@ -0,0 +1,48 @@ +// 3.pautomac_light.train +digraph { + 0 [label="0 +______ +> -0.00 +0.08 >"] + 1 [label="1 +______ +> 0.00 +-0.02 >"] + 2 [label="2 +______ +> -0.04 +-0.45 >"] + 3 [label="3 +______ +> -0.11 +0.63 >"] + 4 [label="4 +______ +> -0.09 +-0.55 >"] + 0 -> 1 [label="0:-0.24"] + 0 -> 2 [label="0:0.35"] + 0 -> 3 [label="0:-0.28"] + 0 -> 4 [label="0:-0.21"] + 1 -> 1 [label="0:-0.30"] + 1 -> 2 [label="0:0.21"] + 1 -> 4 [label="0:-0.56"] + 2 -> 3 [label="0:-0.21"] + 4 -> 4 [label="0:0.24"] + 0 -> 2 [label="1:-0.30"] + 0 -> 3 [label="1:0.28"] + 0 -> 4 [label="1:0.20"] + 1 -> 2 [label="1:0.26"] + 0 -> 2 [label="2:0.38"] + 0 -> 3 [label="2:-0.22"] + 0 -> 4 [label="2:-0.23"] + 1 -> 4 [label="2:0.35"] + 1 -> 2 [label="3:0.28"] + 1 -> 3 [label="3:-0.24"] + 2 -> 2 [label="3:-0.63"] + 2 -> 3 [label="3:0.47"] + 3 -> 2 [label="3:-0.37"] + 3 -> 4 [label="3:0.65"] + 4 -> 3 [label="3:-0.38"] + 4 -> 4 [label="3:0.66"] +} diff --git a/examples/graphivz-output/3.pautomac_light.train.gv.pdf b/examples/graphivz-output/3.pautomac_light.train.gv.pdf new file mode 100644 index 0000000000000000000000000000000000000000..ec0f99e07bfcdac4b0e0c21fe5c94795515f90c1 GIT binary patch literal 14746 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 I>hHz{00+7hwg3PC literal 0 HcmV?d00001 diff --git a/examples/graphivz-output/3.pautomac_light_man.train.gv b/examples/graphivz-output/3.pautomac_light_man.train.gv new file mode 100644 index 0000000..d0bd11b --- /dev/null +++ b/examples/graphivz-output/3.pautomac_light_man.train.gv @@ -0,0 +1,48 @@ +//automata.dot +digraph { + 0 [label="0 +______ +> -0.00 +0.08 >"] + 1 [label="1 +______ +> 0.00 +-0.02 >"] + 2 [label="2 +______ +> -0.04 +-0.45 >"] + 3 [label="3 +______ +> -0.11 +0.63 >"] + 4 [label="4 +______ +> -0.09 +-0.55 >"] + 0 -> 1 [label="0:-0.24"] + 0 -> 2 [label="0:0.35"] + 0 -> 3 [label="0:-0.28"] + 0 -> 4 [label="0:-0.21"] + 1 -> 1 [label="0:-0.30"] + 1 -> 2 [label="0:0.21"] + 1 -> 4 [label="0:-0.56"] + 2 -> 3 [label="0:-0.21"] + 4 -> 4 [label="0:0.24"] + 0 -> 2 [label="1:-0.30"] + 0 -> 3 [label="1:0.28"] + 0 -> 4 [label="1:0.20"] + 1 -> 2 [label="1:0.26"] + 0 -> 2 [label="2:0.38"] + 0 -> 3 [label="2:-0.22"] + 0 -> 4 [label="2:-0.23"] + 1 -> 4 [label="2:0.35"] + 1 -> 2 [label="3:0.28"] + 1 -> 3 [label="3:-0.24"] + 2 -> 2 [label="3:-0.63"] + 2 -> 3 [label="3:0.47"] + 3 -> 2 [label="3:-0.37"] + 3 -> 4 [label="3:0.65"] + 4 -> 3 [label="3:-0.38"] + 4 -> 4 [label="3:0.66"] +} diff --git a/examples/graphivz-output/3.pautomac_light_man.train.gv.pdf b/examples/graphivz-output/3.pautomac_light_man.train.gv.pdf new file mode 100644 index 0000000000000000000000000000000000000000..ec0f99e07bfcdac4b0e0c21fe5c94795515f90c1 GIT binary patch literal 14746 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 I>hHz{00+7hwg3PC literal 0 HcmV?d00001 diff --git a/examples/graphivz-output/round-table.gv b/examples/graphivz-output/round-table.gv new file mode 100644 index 0000000..48aa015 --- /dev/null +++ b/examples/graphivz-output/round-table.gv @@ -0,0 +1,9 @@ +// The Round Table +digraph { + A [label="King Arthur"] + B [label="Sir Bedevere the Wise"] + L [label="Sir Lancelot the Brave"] + A -> B + A -> L + B -> L [constraint=false] +} diff --git a/examples/graphivz-output/round-table.gv.pdf b/examples/graphivz-output/round-table.gv.pdf new file mode 100644 index 0000000000000000000000000000000000000000..ed7810cf4f968b2f4ccd117b59a3e01137c243bd GIT binary patch literal 15059 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 Jb@g}S0sv+@iWdL? literal 0 HcmV?d00001 diff --git a/setup.py b/setup.py index 66e014e..cbb1d50 100755 --- a/setup.py +++ b/setup.py @@ -1,39 +1,5 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -# ######### COPYRIGHT ######### -# -# Copyright(c) 2016 -# ----------------- -# -# * LabEx Archimède: http://labex-archimede.univ-amu.fr/ -# * Laboratoire d'Informatique Fondamentale : http://www.lif.univ-mrs.fr/ -# -# Contributors: -# ------------ -# -# * François Denis <francois.denis_AT_lif.univ-mrs.fr> -# * Rémy Eyraud <remy.eyraud_AT_lif.univ-mrs.fr> -# * Denis Arrivault <contact.dev_AT_lif.univ-mrs.fr> -# * Dominique Benielli <dominique.benielli_AT_univ-amu.fr> -# -# Description: -# ----------- -# -# scitkit-splearn is a toolbox in -# python for spectral learning algorithms. -# -# Version: -# ------- -# -# * splearn version = 1.0.1 -# -# Licence: -# ------- -# -# License: 3-clause BSD -# -# -# ######### COPYRIGHT ######### from __future__ import print_function import os diff --git a/splearn/__init__.py b/splearn/__init__.py index 056f036..384681e 100644 --- a/splearn/__init__.py +++ b/splearn/__init__.py @@ -2,4 +2,4 @@ from splearn.automaton import Automaton from splearn.spectral import Learning from splearn.spectral import Spectral from splearn.hankel import Hankel -__version__ = "1.0.1" +__version__ = "1.1.0" diff --git a/splearn/automaton.py b/splearn/automaton.py index 98375c8..44338b9 100644 --- a/splearn/automaton.py +++ b/splearn/automaton.py @@ -1,38 +1,4 @@ # -*- coding: utf-8 -*- -# ######### COPYRIGHT ######### -# -# Copyright(c) 2016 -# ----------------- -# -# * LabEx Archimède: http://labex-archimede.univ-amu.fr/ -# * Laboratoire d'Informatique Fondamentale : http://www.lif.univ-mrs.fr/ -# -# Contributors: -# ------------ -# -# * François Denis <francois.denis_AT_lif.univ-mrs.fr> -# * Rémy Eyraud <remy.eyraud_AT_lif.univ-mrs.fr> -# * Denis Arrivault <contact.dev_AT_lif.univ-mrs.fr> -# * Dominique Benielli <dominique.benielli_AT_univ-amu.fr> -# -# Description: -# ----------- -# -# scitkit-splearn is a toolbox in -# python for spectral learning algorithms. -# -# Version: -# ------- -# -# * splearn version = 1.0.1 -# -# Licence: -# ------- -# -# License: 3-clause BSD -# -# -# ######### COPYRIGHT ######### """This module contains the Automaton class """ @@ -639,3 +605,50 @@ class Automaton(object): toReturn.update({i: max(w, 0)}) toReturn.update({-1: max(p_w, 0)}) return toReturn + + def get_dot(self, threshold = 0., nb_dec = 2, title = "Weighted Automata"): + """ Return a string that contains the Automata into dot (graphviz) format + :Example: + + >>> from splearn.datasets.base import load_data_sample + >>> from splearn.tests.datasets.get_dataset_path import get_dataset_path + >>> from splearn import Spectral + >>> train_file = '3.pautomac_light.train' + >>> data = load_data_sample(adr=get_dataset_path(train_file)) + >>> sp = Spectral() + >>> sp.fit(X=data.data) + >>> dotfile = "3.pautomac_light.train.dot" + >>> dot = sp.Automaton.get_dot(threshold = 0.2, title = dotfile) + >>> # To display the dot string one can use graphviz: + >>> from graphviz import Source + >>> src = Source(dot) + >>> src.render(dotfile + '.gv', view=True) + + - Input: + + :param Automaton self + :param float threshold for the value to keep. If |weight| < threshold, the + corresponding transition is not kept as an edge in the final dot string. + :param int nb_dec is the number of decimals to keep for the weights. + :param string title corresponds to the top comment of the string + + :returns: a string with the current Automata in dot format + """ + prec = ".{:d}f".format(nb_dec) + out = "//{:s}\ndigraph {{\n".format(title) + for i in range(self.nbS): + label = "{0:d}\n______\n> {1:" + prec + "}\n{2:" + prec + "} >" + label = label.format(i, self.initial[i], self.final[i]) + out += "\t{0:d} [label=\"".format(i) + out += label + "\"]\n" + for l in range(self.nbL): + for i in range(self.nbS): + for j in range(self.nbS): + weight = self.transitions[l][i,j] + if (np.abs(weight) > threshold): + label = "{0:d}:{1:" + prec + "}" + label = label.format(l,weight) + out += "\t{0:d} -> {1:d} [label=\"".format(i,j) + out += label + "\"]\n" + out += "}\n" + return out diff --git a/splearn/datasets/data_sample.py b/splearn/datasets/data_sample.py index 1305b04..26746e3 100644 --- a/splearn/datasets/data_sample.py +++ b/splearn/datasets/data_sample.py @@ -1,38 +1,4 @@ # -*- coding: utf-8 -*- -# ######### COPYRIGHT ######### -# -# Copyright(c) 2016 -# ----------------- -# -# * LabEx Archimède: http://labex-archimede.univ-amu.fr/ -# * Laboratoire d'Informatique Fondamentale : http://www.lif.univ-mrs.fr/ -# -# Contributors: -# ------------ -# -# * François Denis <francois.denis_AT_lif.univ-mrs.fr> -# * Rémy Eyraud <remy.eyraud_AT_lif.univ-mrs.fr> -# * Denis Arrivault <contact.dev_AT_lif.univ-mrs.fr> -# * Dominique Benielli <dominique.benielli_AT_univ-amu.fr> -# -# Description: -# ----------- -# -# scitkit-splearn is a toolbox in -# python for spectral learning algorithms. -# -# Version: -# ------- -# -# * splearn version = 1.0.1 -# -# Licence: -# ------- -# -# License: 3-clause BSD -# -# -# ######### COPYRIGHT ######### """This module contains the DataSample class and Splearn_array class The DataSample class encapsulates a sample 's components nbL and nbEx numbers, diff --git a/splearn/hankel.py b/splearn/hankel.py index 446d4a5..b20f7bd 100644 --- a/splearn/hankel.py +++ b/splearn/hankel.py @@ -1,38 +1,4 @@ # -*- coding: utf-8 -*- -# ######### COPYRIGHT ######### -# -# Copyright(c) 2016 -# ----------------- -# -# * LabEx Archimède: http://labex-archimede.univ-amu.fr/ -# * Laboratoire d'Informatique Fondamentale : http://www.lif.univ-mrs.fr/ -# -# Contributors: -# ------------ -# -# * François Denis <francois.denis_AT_lif.univ-mrs.fr> -# * Rémy Eyraud <remy.eyraud_AT_lif.univ-mrs.fr> -# * Denis Arrivault <contact.dev_AT_lif.univ-mrs.fr> -# * Dominique Benielli <dominique.benielli_AT_univ-amu.fr> -# -# Description: -# ----------- -# -# scitkit-splearn is a toolbox in -# python for spectral learning algorithms. -# -# Version: -# ------- -# -# * splearn version = 1.0.1 -# -# Licence: -# ------- -# -# License: 3-clause BSD -# -# -# ######### COPYRIGHT ######### """This module contains the Hankel class """ diff --git a/splearn/spectral.py b/splearn/spectral.py index 64e4a02..ce8e027 100644 --- a/splearn/spectral.py +++ b/splearn/spectral.py @@ -1,38 +1,4 @@ # -*- coding: utf-8 -*- -# ######### COPYRIGHT ######### -# -# Copyright(c) 2016 -# ----------------- -# -# * LabEx Archimède: http://labex-archimede.univ-amu.fr/ -# * Laboratoire d'Informatique Fondamentale : http://www.lif.univ-mrs.fr/ -# -# Contributors: -# ------------ -# -# * François Denis <francois.denis_AT_lif.univ-mrs.fr> -# * Rémy Eyraud <remy.eyraud_AT_lif.univ-mrs.fr> -# * Denis Arrivault <contact.dev_AT_lif.univ-mrs.fr> -# * Dominique Benielli <dominique.benielli_AT_univ-amu.fr> -# -# Description: -# ----------- -# -# scitkit-splearn is a toolbox in -# python for spectral learning algorithms. -# -# Version: -# ------- -# -# * splearn version = 1.0.1 -# -# Licence: -# ------- -# -# License: 3-clause BSD -# -# -# ######### COPYRIGHT ######### """This module contains the Spectral and Learning class .. module author:: François Denis diff --git a/splearn/tests/datasets/get_dataset_path.py b/splearn/tests/datasets/get_dataset_path.py index 1a37ebb..f497951 100644 --- a/splearn/tests/datasets/get_dataset_path.py +++ b/splearn/tests/datasets/get_dataset_path.py @@ -1,38 +1,4 @@ # -*- coding: utf-8 -*- -# ######### COPYRIGHT ######### -# -# Copyright(c) 2016 -# ----------------- -# -# * LabEx Archimède: http://labex-archimede.univ-amu.fr/ -# * Laboratoire d'Informatique Fondamentale : http://www.lif.univ-mrs.fr/ -# -# Contributors: -# ------------ -# -# * François Denis <francois.denis_AT_lif.univ-mrs.fr> -# * Rémy Eyraud <remy.eyraud_AT_lif.univ-mrs.fr> -# * Denis Arrivault <contact.dev_AT_lif.univ-mrs.fr> -# * Dominique Benielli <dominique.benielli_AT_univ-amu.fr> -# -# Description: -# ----------- -# -# scitkit-splearn is a toolbox in -# python for spectral learning algorithms. -# -# Version: -# ------- -# -# * splearn version = 1.0.1 -# -# Licence: -# ------- -# -# License: 3-clause BSD -# -# -# ######### COPYRIGHT ######### """Module to get the absolute path of a reference dataset for tests .. moduleauthor:: Denis Arrivault diff --git a/splearn/tests/test_automaton.py b/splearn/tests/test_automaton.py index c9df0f8..69dd1e8 100644 --- a/splearn/tests/test_automaton.py +++ b/splearn/tests/test_automaton.py @@ -1,38 +1,4 @@ # -*- coding: utf-8 -*- -# ######### COPYRIGHT ######### -# -# Copyright(c) 2016 -# ----------------- -# -# * LabEx Archimède: http://labex-archimede.univ-amu.fr/ -# * Laboratoire d'Informatique Fondamentale : http://www.lif.univ-mrs.fr/ -# -# Contributors: -# ------------ -# -# * François Denis <francois.denis_AT_lif.univ-mrs.fr> -# * Rémy Eyraud <remy.eyraud_AT_lif.univ-mrs.fr> -# * Denis Arrivault <contact.dev_AT_lif.univ-mrs.fr> -# * Dominique Benielli <dominique.benielli_AT_univ-amu.fr> -# -# Description: -# ----------- -# -# scitkit-splearn is a toolbox in -# python for spectral learning algorithms. -# -# Version: -# ------- -# -# * splearn version = 1.0.1 -# -# Licence: -# ------- -# -# License: 3-clause BSD -# -# -# ######### COPYRIGHT ######### from __future__ import division, print_function import unittest import numpy as np diff --git a/splearn/tests/test_base.py b/splearn/tests/test_base.py index e7684c0..1fbe062 100644 --- a/splearn/tests/test_base.py +++ b/splearn/tests/test_base.py @@ -1,38 +1,4 @@ # -*- coding: utf-8 -*- -# ######### COPYRIGHT ######### -# -# Copyright(c) 2016 -# ----------------- -# -# * LabEx Archimède: http://labex-archimede.univ-amu.fr/ -# * Laboratoire d'Informatique Fondamentale : http://www.lif.univ-mrs.fr/ -# -# Contributors: -# ------------ -# -# * François Denis <francois.denis_AT_lif.univ-mrs.fr> -# * Rémy Eyraud <remy.eyraud_AT_lif.univ-mrs.fr> -# * Denis Arrivault <contact.dev_AT_lif.univ-mrs.fr> -# * Dominique Benielli <dominique.benielli_AT_univ-amu.fr> -# -# Description: -# ----------- -# -# scitkit-splearn is a toolbox in -# python for spectral learning algorithms. -# -# Version: -# ------- -# -# * splearn version = 1.0.1 -# -# Licence: -# ------- -# -# License: 3-clause BSD -# -# -# ######### COPYRIGHT ######### from __future__ import division, print_function import numpy as np diff --git a/splearn/tests/test_data_sample.py b/splearn/tests/test_data_sample.py index f7cf18f..326ca5f 100644 --- a/splearn/tests/test_data_sample.py +++ b/splearn/tests/test_data_sample.py @@ -1,38 +1,4 @@ # -*- coding: utf-8 -*- -# ######### COPYRIGHT ######### -# -# Copyright(c) 2016 -# ----------------- -# -# * LabEx Archimède: http://labex-archimede.univ-amu.fr/ -# * Laboratoire d'Informatique Fondamentale : http://www.lif.univ-mrs.fr/ -# -# Contributors: -# ------------ -# -# * François Denis <francois.denis_AT_lif.univ-mrs.fr> -# * Rémy Eyraud <remy.eyraud_AT_lif.univ-mrs.fr> -# * Denis Arrivault <contact.dev_AT_lif.univ-mrs.fr> -# * Dominique Benielli <dominique.benielli_AT_univ-amu.fr> -# -# Description: -# ----------- -# -# scitkit-splearn is a toolbox in -# python for spectral learning algorithms. -# -# Version: -# ------- -# -# * splearn version = 1.0.1 -# -# Licence: -# ------- -# -# License: 3-clause BSD -# -# -# ######### COPYRIGHT ######### from __future__ import division, print_function import numpy as np diff --git a/splearn/tests/test_hankel.py b/splearn/tests/test_hankel.py index 86d4865..8e6e34e 100644 --- a/splearn/tests/test_hankel.py +++ b/splearn/tests/test_hankel.py @@ -1,38 +1,4 @@ # -*- coding: utf-8 -*- -# ######### COPYRIGHT ######### -# -# Copyright(c) 2016 -# ----------------- -# -# * LabEx Archimède: http://labex-archimede.univ-amu.fr/ -# * Laboratoire d'Informatique Fondamentale : http://www.lif.univ-mrs.fr/ -# -# Contributors: -# ------------ -# -# * François Denis <francois.denis_AT_lif.univ-mrs.fr> -# * Rémy Eyraud <remy.eyraud_AT_lif.univ-mrs.fr> -# * Denis Arrivault <contact.dev_AT_lif.univ-mrs.fr> -# * Dominique Benielli <dominique.benielli_AT_univ-amu.fr> -# -# Description: -# ----------- -# -# scitkit-splearn is a toolbox in -# python for spectral learning algorithms. -# -# Version: -# ------- -# -# * splearn version = 1.0.1 -# -# Licence: -# ------- -# -# License: 3-clause BSD -# -# -# ######### COPYRIGHT ######### from __future__ import division, print_function import unittest diff --git a/splearn/tests/test_spectral.py b/splearn/tests/test_spectral.py index b0c9bee..ce71a71 100644 --- a/splearn/tests/test_spectral.py +++ b/splearn/tests/test_spectral.py @@ -1,38 +1,4 @@ # -*- coding: utf-8 -*- -# ######### COPYRIGHT ######### -# -# Copyright(c) 2016 -# ----------------- -# -# * LabEx Archimède: http://labex-archimede.univ-amu.fr/ -# * Laboratoire d'Informatique Fondamentale : http://www.lif.univ-mrs.fr/ -# -# Contributors: -# ------------ -# -# * François Denis <francois.denis_AT_lif.univ-mrs.fr> -# * Rémy Eyraud <remy.eyraud_AT_lif.univ-mrs.fr> -# * Denis Arrivault <contact.dev_AT_lif.univ-mrs.fr> -# * Dominique Benielli <dominique.benielli_AT_univ-amu.fr> -# -# Description: -# ----------- -# -# scitkit-splearn is a toolbox in -# python for spectral learning algorithms. -# -# Version: -# ------- -# -# * splearn version = 1.0.1 -# -# Licence: -# ------- -# -# License: 3-clause BSD -# -# -# ######### COPYRIGHT ######### from __future__ import division, print_function import numpy as np -- GitLab