From b9ace4871d33e72b6bcae627c32b67cc13323edd Mon Sep 17 00:00:00 2001 From: Denis Arrivault <denis.arrivault@lif.univ-mrs.fr> Date: Tue, 6 Feb 2018 16:04:38 +0100 Subject: [PATCH] Code refactoring : removing Learning class --- .gitignore | 1 + examples/3.pautomac_light.train.dot.gv.pdf | Bin 14746 -> 0 bytes ...train.dot.gv => 3.pautomac_light.train.gv} | 11 +- examples/3.pautomac_light.train.gv.pdf | Bin 0 -> 14552 bytes examples/GraphvizTests.ipynb | 707 +++--------------- .../graphivz-output/3.pautomac_light.train.gv | 48 -- .../3.pautomac_light.train.gv.pdf | Bin 14746 -> 0 bytes .../3.pautomac_light_man.train.gv.pdf | Bin 14746 -> 0 bytes examples/graphivz-output/round-table.gv | 9 - examples/graphivz-output/round-table.gv.pdf | Bin 15059 -> 0 bytes splearn/__init__.py | 2 +- splearn/automaton.py | 49 +- splearn/hankel.py | 116 ++- splearn/spectral.py | 269 +------ .../tests/datasets/3.pautomac_light.train.gv | 13 +- splearn/tests/test_automaton.py | 21 +- splearn/tests/test_hankel.py | 2 +- splearn/tests/test_spectral.py | 41 +- 18 files changed, 320 insertions(+), 969 deletions(-) delete mode 100644 examples/3.pautomac_light.train.dot.gv.pdf rename examples/{3.pautomac_light.train.dot.gv => 3.pautomac_light.train.gv} (91%) create mode 100644 examples/3.pautomac_light.train.gv.pdf delete mode 100644 examples/graphivz-output/3.pautomac_light.train.gv delete mode 100644 examples/graphivz-output/3.pautomac_light.train.gv.pdf delete mode 100644 examples/graphivz-output/3.pautomac_light_man.train.gv.pdf delete mode 100644 examples/graphivz-output/round-table.gv delete mode 100644 examples/graphivz-output/round-table.gv.pdf rename examples/graphivz-output/3.pautomac_light_man.train.gv => splearn/tests/datasets/3.pautomac_light.train.gv (89%) diff --git a/.gitignore b/.gitignore index 660e147..a5346ff 100644 --- a/.gitignore +++ b/.gitignore @@ -74,6 +74,7 @@ bin/* .coverage .cache +uml* skgilearn.egg-info/* htmlcov/ doc/_build/ diff --git a/examples/3.pautomac_light.train.dot.gv.pdf b/examples/3.pautomac_light.train.dot.gv.pdf deleted file mode 100644 index ec0f99e07bfcdac4b0e0c21fe5c94795515f90c1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14746 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 I>hHz{00+7hwg3PC diff --git a/examples/3.pautomac_light.train.dot.gv b/examples/3.pautomac_light.train.gv similarity index 91% rename from examples/3.pautomac_light.train.dot.gv rename to examples/3.pautomac_light.train.gv index c3ac1dc..630afa0 100644 --- a/examples/3.pautomac_light.train.dot.gv +++ b/examples/3.pautomac_light.train.gv @@ -1,24 +1,17 @@ //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"] diff --git a/examples/3.pautomac_light.train.gv.pdf b/examples/3.pautomac_light.train.gv.pdf new file mode 100644 index 0000000000000000000000000000000000000000..13325f666807d2f6f0e6e5f37700589d688fa25b GIT binary patch literal 14552 zcmY!laB<T$)HCH$-THRjZ!Tj61BLvgEG`=x1%02?y!4U`1rr4Wg&-~k1qFS#%$$<c zA_aZ7oWzn;m(=9^lvFM|JFeoAqSVA(u8KKZqfW1TvQ6;rYway_B74rPdSu+K!^6VJ zlkza7L8nK7V_h=)v9}CmVn6@R30`s~Z>4GYWKV+wF%x}*o~*pSa#7v9eRJ#Q>6~BL zw)4rRCl{XaYaToL=+Ei<&+X6upOf-ze|+7X{lB7T)c?7z?)KlHb>{znKdOCxm`mMH z_~d`Nyng0kp=a;aIX}xkOW7roS=^N?nEUzdz2pdu+jCU(RA0{t5zjU{zU<$!t$&S< z3r(AGsziQLNvCeUch1|7lcrbuZ(F);m!9GBNz<ZIcI{tUo^Wbg|HaL3i*+{IpFI6% zIU~b?U%wu=yi{cAz4-gx+6Y5C6YWgD8=;q{WzV(0w`_gg4*|P`Cx1S+zl^Q;|8e=t zW*x1-;#nU>x?KKz`}^hY?*03w|N0RhIsf0MkF#Hv%h#)R-l>^BF^MT;dv*UdRqdA9 zN6t&K3iXzXePiz2`q#)?L-zevZgqtjueq{|_dH5{?O~A_x171SaKSO|WosWl-Pc}v zV%PDFhu#T<FBChgeZ}ya>#QRa_ybP==g4{$u_9nb#I&yM_tUa7PqIzzyTSf1>+mgI zr_v2GXQc7Uz7lz~$ilASKu1u|uNk$1nm;(DVwETOJ18ZnCS`U{b62QSEskAsY~7Pp zQ!KX~6F)MCamktWFEqV5BWB!^z45vKrN#T#-Uj{27H7^*n~-%#vD~1ZeJWed{!0Ca zciX=&%9&Pv`ZxcN_@5H|4N-5B%r$&E+#IgY3lR7IksX`Qp);HL{KcA?Tlvn)+RoaY zw(j%xZxx46?`_X#I+Wacvq9$9^0%^!nS-zSuCcwXc3kLpa?I5@?%Cg>cnUVv+|piO z*Z8UJ?uWe*O7g<T&u3gO-(S1x6W9Cs39%(SA(b*h?aNL%Pn3N*<w$I?fXAvYI~={= zYpw54QM|O9K|N#svt37e1g}jC`CQ93$Nv*&=(MyC4?k!tCOdG)?qqgdE>iYN=}_D+ z9-9Xf*yQDRE?xJGZ8lRz#^ECgTwx0PHPqcwE25w2^kn79OzFS6P-=?;cj8Au&h;zv zf{sUu`>vATRlRP*ljZYXUsrqT-`#!k$BcO=v<{|<l-m`k-|z~FTxD=c>^mb{yfUk! z(CoJ34cD&DUE`zecB$08dBTDjOoh&SZp`hzUcl0O^Ze}3l2dq;J1S*F9^7MGsxYlc zYQd7(%+rJtLSi_a{8lzs&M4<SQ`ootz?9(sDK$LqE{)x<x2c7DD9qa79MHbOWCcs8 z1(%GLiOHjgz{h+6*B`F?vq88$F#B^Zmw(jj#qWY$YE(m|ciBnb-QmDzs&n#|%|UO6 znJcFhW;&i%5fJ{KS@2^E1IK|6kJ9$VHOa)^eX7F6@a!aOEW_{2>mTHg*Kya|hCch{ zGPC=4$PHbkR}S-JgEpG4@q6)dimEZobiY`q+qd-P=GdC8i48IR^}e)otL?pyMehS% z?_0axKzm`AS+2gM?3DL6j@{b)wpwSS_3>1`&f|ho4}Ki%bh?(Dvq8U;S3x7{a^1D{ zDwFT8e`MLq_n=WRWckZQPv$K#{PI%p1Z(y=yB(i7{vDq_@xAQ}>$zeznhR28Gz)%l zP7GMR-Pkg{uH<XM1BOY{m}j?a?{0h2e9-cSLYTun4Q0KMw?`ZpB-(<v@GiSMSM^5h zt4+P{7Ae)ln|_^|^+NBJ#rs8_Uy3W%w4as!!Wi~rr^u_$xeac!dQ-F}I~`?H75k+z zr@djD)f_t)y`%Nzf({jj-5nz)y<8-+Pw~5Gmb+P!ldRH$oZ1>kt*ZqB363|LHW|4X zm^8dNC;a5*T9wf623v%F%wW5sko$4zZs*Vyt?yZ%9DKXxmzTQIVI|Sq!AAY>dN&@P zmKwItz`ctngg5H#ql+TDPw;)#>sqr-TWNB7obUYVts(_=4%1dFo_fjag5mP3H_8*0 z7|jor9N<Z8V1BLq&9ft6)|?!#1UJ?U&q)FnMn}6RySs?3`k2Y|aHbC<H={{`Zi`SN z>uSxSxaC&s*3Ufcu->i0?%Xc6l%^Sa3@hhftF>LU@?fpDK*Fh#+g3t9qL^kpXgqg& zcJP*n!v(7Mmb_nS>#&A7<7b@nhnLyKI{!D79<Z6f+IMqvz}wrqer?$nzwLT|Uukje zx4ie$A2S^<*Jyllxkd4xyl~r>v_lhEy117+o(jp9l<He^{eP8~<6rTYO_yrx<}lcO zsqc!MvuN3w7vZsMX9g}8l7H;j^jYiF73<&Jcbk|#zcS16Sjf&bk?Y(vKOH5-J0THE zJic8t|33Zd0kH#LnVfE|=H8;kt#NRtWbPx2_lta|^lp+`P&MoKUP-<u9Q#Y>om~`L zdT&b9{ko=$m+YS$w75G_A#Htb%bvh0N!!cUw#skXCR$;!Jkq-5CUZ)gNsrL-Wy&hP zdH)^c1g+;j<Kdh)d-8#^EE~&A)6N(LT?)T0$|dnWYisql!*jB4^uOKL_;+W#y&BgY zk1r;XcXIDP<5`<5bnHsE$=)?bmP`KpxOeYCyQ+5^-nXxL%lmDsvqP<e?dBEkEvw>~ zib{lh*k^_LU6o7b*(hk@JNK;0lAaXq87cGB3S1g$6GN|VI{44vrPQ0`-T4RpxruC0 zXARil^68kxtFwog&4cobyVOLL5+<=p9e-1loqzP$MdO|A>N7>OWSg~n+_-KX_MN<a z%I8foZi-V5v&>Yyzin>hms=;b*;2Oqsqto?+B(04_w>f(cVDA^K1e#IEw(MnP}YdA zajt6eGcI$fg*hH7wv|mv!Okkj+}jQ{sWEXZ(t5%4Ha^tW(`^0s34Z46mm>_Vyb~-> zWM@xc=yo;NzvKAQq0F7N@yn!;J32r3I-eEZa<xhRV^g*7JEwd2nMpa$Qxf7FtsH9| zI!^h7RzK4%=tz0uW2`OG()O1@bs{%oRi^8-XDpUh+Q!T8=;W6zHD6U`VO(^fVX4za zUN*-U4XK9xtB&p3S{=@D`+M5PieFC?<etUqioc#N`25e26O)T8ZgDQ$y_2;fZROk` z?MIT`rGhLijWblfZgiU=<Gg8aT=m0`5rU13(=52A>zv$Rz1>*H@$-bdgb>-E)10DO zStVC3UM}NxoMU?D{pl79Y<zZer0$wxb}Rjff(N_p$;*%W{vB)ZS|%!(ztX!!xkPp8 zSFxK<?|VF%`P)%=VuJ65K>MxNH=X3onf{Bjdt*S6X#Zob=P|MFlj0pW{Brr|D|IJ# z&ehEkOOm$EdwT7J7xU3$O8U=P*QXb%{#l~<LtuTn?6TOD^p8$UHu<}+dR)pra|yfJ zTTwO*!vJM2o$m%Ggmk7AM5^hWm>yltBA@<F>y2sGGr=4Ba!uk(+!xic&+oK}=`WCt zdmXxe|D;2w*;t&ql~Wh`ixxk>yC;v?=xh?t>&70#fWjh=d+d{(k^{2SUHUvNi~qhl zRsVXa-&fBwIq|=>EL2v1+}bDdxA2^)=GC)iFZL>ATi)ATr^Qxf_W8*53q}!35_+|M z_O5#N?o{L%*Ch`-j&-++SsymIdDKB8;PYt}6<M8Q2A^iT?N3n%47uCwCFrl3toujx z?ANVP;z7PkT1zrED7@n6mP>!J-LEJieogFMo5||JsW+FKuAi9lyfdI{74yHpOS<oQ z>U%!e^R9Z&kpxZq71|d1VTsQ>GZ&Xn$hov=_GC_ms3-UCy}ReeudQ;?SY}tESAW=} zrwv!)57rpWKkCExD0Gra_@&$13}32!eKob@T7i%INtSnM_AeiOb-j1uPW{uoPsK@R zW*nYz^0k3)v*XS+S#N8U+51bPu1pQ_w$NA_|Nr7?ar;R#zZPx3zP$anTJgiu*Dq6D z-hEX{y%rz-ymxy-oZQsVIG(RN1Z>}|x%a#9-qqb(Kcx0ORN1-g&B<vM*JEr?7f(%! z6%M$)qN6M>?BR^bhrf1cJWkUP?KrfxYx3%OYc*~f#Biis^zd82v2jl5`bzI3U*fj@ z(v>X>I=VUaYk-58)42@A(qFQ>7Ro=5y>g+hZ@WOPm$Q=mX+fW3YR@xII`j5l`16?a z>2uK~ixzP03A(ED_nT4wCgu~b8H{%;sO>jQ`*~#si_(P5xAz+UOxqr-!)N%=YPXJZ zs!935rDpqeSIa%DSgG)Lm(a8K-z^sSpMA7L_xAbS9ch{K+n-&2@|HvM_4hqL1sJZ_ zFMqI9`Rjx)GoOD@k+f1=Fg1l?O=1<R;xtDFrS<=`bmC@kZT{f)?5xp@dKN}L2TcRj zFt3Mao-FR~XfF9^HKjO`^J(v))$6nVG4}5gs}QN0QM}P@zWK6eotfVkT^BK)AG6pv z&TakWOF4P-_J8hXpJY1iQ03}#KFzGIZ7P$@*$a~c1^KvNxg}lApYY>p)AS}~&N*N8 zB_#?J*$sXf3(PE1E-0L0T@Zil=+0%ifhE#Tw+m&yU)FQdoX`0*cx_G5bH;v`dqGzx zpNw9wA-Zkm*3a3jYz5QKFU>i-R&QUKk7|{{0h#?ZNo?AcaoODkv%}6c_|*ANc@}eh z)|VT?u_>nOi&)DQ{zPc?o_bez>FVjeU2LC|{I$Q#*HV_5%r@<;WYp_lXC>|TB=%&^ zRaD(`^yBOMr`DXcuG^dZ$a2NCKPrNoGtF;te>me_>HMx-$^W79_Cu9FzD9U2UUJ^{ z<8BG*rIGi3ZE^}Oa?iJao)vlLp3D0?GtBk=zx^V=WntkIuGG8~X!j~LF9p;w1NFv0 zw1R?yv5BD(NCAjz1n;+jdupx~CGNo`i6yBDHZ~vuQ130#KmpXNb9PiPRM1aOR4`Pq zvjfRNNPV~byb>hUX}Siw1`4LIzMq{PsHX>YgBjd11^tl9f>Z_lfW-7vkXiZxiAAY- zB?^WxefqwsDVd2*`4tM$3I+-W3Kk{?3TB383bA0-&iQ#Isd**E3ZQN$q>t%dlwVqa z<PM1WU{R13kVk?Q^h1gg^NI^Vb|qKBggq5Xib}z*04Z_~R?v4zEz3+!4RUt^DS>)3 zD784hv?w{XSOFAdK}fzbNAeZ4>uUk`2DYv*$Qp=3Lj^-KBU6wq&`z_Fg1Lp68Ipjp zf~koq$TDbbR?K-@RT>g~`<Jdr*KRQlfjf8i?g;J@Zx>j?!ldF+5Vd57sK&dzrAND> z3$H)&yU28OYyZ6B^Dk}R-@9-B{_po=w<VRU-&^iCz5cy6d)?fW9)k-RS;ZdFjyjH9 z0`3y*{Oa2^91fp5cu8~>YvF~4junL&jX5!l{5urbn49}#d3b*1GfMDODTuF-Jrek3 zeL$r61lBi<6E-*4_FULl%IdNE76Zc`206Pxxw^nQK?Z&E?HA%31;hgzwsId4YIYQR z#8SR-^TyUrrhofb3|?ow+`M7q#{X^=E-o$%(?0B%XprH^N`K6e@TdI%^D8zc=Q%PC zeFlaNZ<u-5ZZk5PCG422E0U0y%DU;-(uL`aY&V%j-W(|N^Aj*<*sOEfK2%QV>BEW& z;R6W_8ci~edi<(?4L^jR7E#bMTVS8{Q0&oDW`o;@68sj$#9ZT_@>Rb}IP2_7j;2D} z45Jg)Q74^b>Qb4H9{6Dzaqb)|OO1xyxv%k6dG9$2%fI}}@7X$c@zwR53}Ng1Vs`bF zom;1ny3_tKqo06!!&X)aE~X0G4HEk^r3H8t4xBx$d+0bbgC(<roI~`wc*_?D<~r0* zs6Qaq7iJe%pZ()TWV4)~L|g#3xd6knM_ivi{wjYozg)t`hC$m}fhU1;)5hW>Ki2+Z zXkPPwPx$tRoi{2OdUjaK&*FOU@9VGMr=A?-3=?oS_*1^4t(BSMfNFN)bEcn%=iiaJ zv)@xvvV;9Vce8td#DRm_XP6&6tkdvqnJ)j}Gr!`2dTWCnCc1C_O})3@Q_DKanL(*O z?Bj)f^`T4;ihf_d%kV7zT^i$`;Q8LnOq-dT<a$1Dx9#1@x<h`>&w@uk*KhmF{(pPr z|MP!-d3%4Gekp(PKle7SbqOEj_on>2?AO3<A8ElPr^6b+{O6O%jYCiE*&{7(G(P-) zdBcB>>+FAbhW}T$Or3Gm+4NGM*@OL2d=EA?Yu%`9SYz@w!QpoO&2Ror*DrECVcJ&A zlIgUdZ2vrE20ppGcmL;J*|?SYmUYvD3+(Ct4>roI{b#8=eUGw0QtI;z<_DqzED<|) zL>w^OA<uJCTY=%jBSxDXl?lh?s~Ha*eaX>i%fo1~^H2=~f3^7I>5M-r7-Is|yW6kU zHvD(^!O9S`jh~yT=npR^(~da~dSwEu?@usjI4%5y=_hXo!w!YM{i$+7&zg4re<nYz zpF8a})35Cv?JL(RuG8DkxR3q7xwrR~e#lR%zTsPc-+l>O?S>2Q&&Xvx`&AtI&rME< z+3CQ9`-V;YpKtuB;%Kh(SN*i$$*<L?0~C%tJ<s|7V%UP!-KU#9|KCvOxBdV6-mQ0u zxsD3_0s@a;omF(Y^zYi`$%l^2klZL8%CfBLtni}?$IDYia=#e+^hvOkb|3cEzkc@Q zYSYW_FW%+vIrsAWE&cf=GX=B!f^5=C8$0>xF5GjrbP(GxSE2goT_e5)UsF}{B<!3g zcQ2NF$j!a&-ooSBdYyAmsXA+jx!+mdxUqj_`OW`lj>#We%^j_ne?!}bQUCDg1$#c- z4dQDmdG+mu*zr^yHL-UeMI?i*deiP26eWcJiFrA(W%UmJ=n$4izh>2ElrWV2tJZD0 zx9!-{-nW-RZcS5id~U{?a<h4^SW4#Y(?M_FU0F9p^3(CI(*kuzqff~GzvXf)<w=;Z z!j^4r(@pu$^7x2tIukc-z2sb9m+gsnwdD8Oe>ZyAE-7St@meIykEaILb6I#<PpPyo z44-j&>(-CnYO;^i*SH???>wbb)g;RKl113ncfUVd%+-L?=a0-e`2PHP`JZ7L0y{bs ziZ@KW(#ILZ694<oLestPwrI_m^xj7}M(g^)`<s2AUV78qQyFuTWjTk;-1eX+*B^;6 z_KK`v<dSt==R8eQ^6Uz`z>A@ts)@_H`e$<MX`C+7_#S(-QO4&{`jP9E-ZxHXJT`gC zW~*}W<zii4^VGKZZ_6(wUnz_`rGNi-aiM=%pKIjYqsGTqh929ukbO=IkL9cA8qT*# zZj7Zx-}ZADpWk$N&uP=0T}Ln9k;<F(rQdS-=etfvV^4m*<;Hxc!`><4am19Tr<^iR zZ~nTcj_qGylkWeszaNLpQ?QR#eYHz-MPK*FvjXaJD|T_koLy(dRmKrewzt%M;*Z22 zDgF7|+V4cw^35#hXf!<k+PL+$7?ZzzxS;c|^lNvTvaOSq{OxK*%bj1D=jtY&*0_6b zS7W7Xim_XiqllQV?5;#6g|GjXl<GWR7rbDz@Q2fd<rB}nE-qJF#rtCRu`Qi%me;L4 zCY~XC{&>|xOZ)7*^H`-ztro0paSInx-Fy2cgT&jf;WCkt3Ln#_gy!&FKV$#yYt-r4 z_o|<sQY-Unbx3GiecQ(C>9n>>68GOuHMn@}qyh6ciw=foGLqLtX9n&*mcJ!0n|J>w zx4rumR25I^XT5xT>D`Mr36oS)vXh?&9gP2E8nImL(f*((t0yItf4s4vWJUBZpT&I_ z-fCE;zx{6+`2S?Xyw-^diQ3vXclo~zv|>D&wD0qFlPh;NO-xuJ%>DVqr8<39?MtWo z!+m5K)vDJ#(La^BWrKx~vGSiIxeYG<Qq#DWO#F2xwncBr;?3s2CYZSN=QXcud@h#O z_BHlG`uXX5UJJ56QJJ{QZ`ln^?N+IaTb-6{TTpoatL(3Nn*xMg3+H@NFubEHSNKZh zxkA<1gJ;{z^AGXNn|7ur_czo2Szl8BOxeG=|3t;%r2dvD8KZC=p(PqV8?6`V+6YRv z3dEg%J-25<!OtJh7fv<$R=n!Wh31{7Gv_pTxmF~mZ_u+&|III`e=ud;idQ@MHfqjs znICa%)0>DV0U3{3qds0c)x&dT;hQ(kZ%+SKbXT5jvPOS}z2C#Pv$Q`*AL_PDJ-J}} z<@_tPSJ(5k*H74c_fymSw{<y(Ganmgo32^@^6T<)!`)M2O1UP4dTn+-5wrE${jMv| z#G-zh?Xe0xx;wBh<h|Lku01CgT{tx9=$36)ju-rGejKbH8FwkV=DN=P*1zhq7uSUP z2YSz#a(#QV-m}xM<pb+OE@Z#gnZ5nV+d0cc1ePCI5&wJP*7r-E?#w?>HZ`xx=H}7W zy(ikbj+k?va`xIZnNw|Rz})w#2S3<MUO2~L>7nNvw(sij*|7NZ^SJ!%_euxY{;KGF zo;Qj2()YL>9~h?<@?6coF=KiDYT=FBUadSP{&0htzNyCHA1|k8OP{o7y<WZR<@6Gj zMRSFtPk#w@HhLGfTj=Qe6E*@bxm6Sn`u6G?eLlk>x@I1e;)cV`o{x|0W2jC!(UxWA zF0kEK`e|M>|6H|AIqS@tUY}D@y~bqnJgKSZ-D86<KOJ&P*e=hTz|h{gipOsD?n`xz zm!pp~tiQv~<RVgfpCgo|MIyiWdA`YZxu1K~7R<jt_c@2_{=71^t9C_c<?~)DJ-%u` z@rQ~`q`ko%`B_Vsszm2{+gzKl^jP~fO{>}eVqzsH+Z((!e)@OC+^37qiiz_r_IUdI z(d3wq(_b$+`b;81eqK>jbluaG<PVG47T^1|DN(KS;JsGasFQQ|i!T3D^6kmL7SG4Q z63Tv+@qD)z_7pZM@Kvp9UA=E%)zu>#{#xw5XXYAK$m{cR^`m#kgeU#s@p&KqQMcji zzpmnJi-zbeDy7kX-2NXw^GB!n+3xdfTK&TI&z3HHvfuBD%H++Zx3uQ0+r@h3nqJa! z2ezYHbJk0U&;2b`A-;K&gVW23$-CEYTobhO?ZxDqUD31C410d)ZJDm+$)%MLy!qa1 z*^NAkcmHy1SrN#(aIX2S1N(mLn#XrHd$R8B(2}X!r~K@`a3J?eh`91A!|R7vm)O2f z`0pFA?K`7JqvpB`Gn`HD9$ELV#%#%kqYEpTcXltEb*Fhk*qcfB9&RiACAE3Qy9qYh zF_DgGfiANyT-TcWrKRbYZg1A7YwBO?GEdF-ope-Zrdise`y5Ha)2}_r(@hqz|8P_+ zGRNoDcAKC?F+QD;30_g(HQG2X$*POIJi-;F{fbGSlRMGg@TOJj!RIemneRHY#@a?< zi-y*=jm>YneAehLX6#+}L3smbW^Bp*iGDA(2yOmrvNZqonol>ZD;RF}&CH1ijN6iP zdnHS)yw}`-_$}&&m!}pPg^S7LuiC4_b6wMHRZ#Y&oY}njM?CnmuRL_mF^kc1Juu-~ zRqxfZhdEKUb%*qXyBAkX@I7IBz<T!XZlm0kN4Hm2>GN|*&j_(tb7WtnW_xeI$@hUi zM+9zcINbHmF4K_l@|BA>w}n1T=ivI?61Fr=aHsnj)wf3$%iI=YD|x>5{ROwLD-TO6 zm~Bg|*Hg~BD67rB>h7XRSALv&a$?hseOwDBIhkuNZ8rH8);hW6@n6e(uV=O8|75)( zctXarS8?g@_8)=K+X|k$>s%I1{W+suYOk`!?2E#zkACsUK3ukWY4O?FFOqZL{#^In z{>UZwMe{mWb<|J1S7lV@-#GuooXLB>r|m0!x4|icNn#mO@o5?L;^IASccghVz8v4Y zW!-VrJmvbppC!j1cOK(dA-($9<(m~peu^oZN8ZT!8GKJ>=c*$sWKS0t89v=*82Dz3 zl(nhYs&@Tf=l!O4Z7P_)M^Hbzcth%`$LaIx{zfr<P@G_rm(BZcSHMK=7eTovrhbdq z$$r@C0JE~H)AbV*S`Ci-R{TDi!zc0T|D)3)Q>V5B&iB5)!!NlfG_)}6w{BX`jw{(8 zcV2Mtb-dGkX3Cu_J`W--`18U_J$BY@PP9&%P_v_Y;Z0jPIrC4krM-f`p8FmAWx6bA zXJu<c%_G+J(gtl?_!sl$Hwd1#Zn~&oyV`<pd!cTP?Byp?I`gu^;~!*C-qdVj;ybmQ z_e9Or^1>IvjI~WqQl4r)?p-wR>e;KaB3q|Fp6{CbXr9Z`Ex#6S<SI~oFk5%#_1p#S z3pKb64DBN2#jMUGv0U(+=Vq^ZBX^BV8r$~0T|Hp|4~!a3<Zhc3^GlRzDk~)_n{GF> z-(53#*N4f@8jpTD*|3$%t~kc_deWs{--8)KujY15SdedU@Y&I)|09>Z^)&aq_58${ zexp?-I}dd5Ew9?<^!bg#ztjEu{NqxbT)17=8+W+XKCOLeJ+WEJ?UAeX=Cd8vKWZoJ zuRmlmN!e-6)I7JGaIFXqmXh+eN_E+bjCyzG+d0->I}l?LZ!N!a&TLgNowjR+AD0Dw z>UR9;FP3W?zHr+c1-Gom1UY8AojF>Dmb;4QeC1YmT`;NFYx}RKOD{dqI3$<yW$GOb z{ax7?zrPi~&^z;M&%Vkfi<l4Gar|IW5^>+C{!oi_xS7_m%*Yj;v0imH23!(beQLss zCpS6FIph0b>AaKQE9W%s>R>qUaqY2)!1>hs2OhAWajH9HTX{F_o#UNFyh^@RM~|wk z-&`&v-_JE)maqKY6b04U^N-lCQdYiv`Ol}#VK0_y{qNU~Rw{4va9J{g?`3x8uQMw( z^X1mudfNI$nq^{V(%c6>PX<r!x|edEDZ49q74tQ=$ERLC+@;;q!CR&;bva0KTe9vp zz5TlakL;B;kJ7A4k7K|6(pvY2|K^v@y4#;IhB9d<dI<^7Q=Yg=Vuzfiw)=hc*wf26 z4<_jx)47{uwp=W%VbiK@7Z*%jA|J7DZB&&?zx3(o-rbF#i)J0u*z{uV%D!Jyy0(ZO ze90~T-}yyRXki~mUhsw~R}&|tm&P^RV93;zezW;yy85$3o#)S^?i<fsJyGiG_o{c+ z^CENlE}Xt-aB1@@sat8WuNN&nb^d}_dcp~LE1xWmDe({a&)4~PbUhKArtQ1IxvsEL z{lG%8IEA2uKRf(*7q$3I$y?Vc`um8orSOs_Ypde6pNh_MclVrp@UO^r#*|B!+BF@I zKf7`*xN+6FN4@$%i<X}`Tlm1>>?H3Fll}$&yH#dSKEAhMYqpBGsM5Z9HEv-)Qy2Ml zdTic4KW!Pm-_mJ^o~Mg4Fy2(G)W34=hV$j%0^8<QYrgciDeo3rnY7^Zg@fOtx-=JS ziB@gC=2fm2c*uL*dG==yi%m~`s?y5VxqkDErAtlQ(U4tp{+!L<*H`dEwOe#1C#z~j zzVAcc-CmdLbZh@VeXw|qt8PK1hjfo{Y(Zs=@b#5TP8!^npWl$3Yn^Ffua@_YKgl#l zbk60%^Dgo8-p?s>He)>c{Mwzn7pw2hVBMRaE5UQfJAb<kx5=tQuWB-H{_RsKSAE2F zdw*eo&?ytC;$*q}r3({|^5;F5HRsQmf7C(3N`HE<U83xQ><h|vPi424O{^&qTgu61 zz4@}*ETyo69PE>0rd@1S-}BwWOF4mYS=$`Vwd*qyZ1sKpuTGCPQ@s4R{a})jk$b41 zwAW7ay2!VkcP)9#xQ<?&qo2GlC1(3-x5@X9_1`!lDa$n_+1|_V+UnlObopzW79Qx| zb4L5V&5^Y|Zxb_S&p7KY>yeZHukb;r$hkKi+c&KAkGc_D_&Bz{j^Y154e9M2Ow*rC zEsQpr|9oA=wJKMaH30>(##`0cJ3qHP4ZLFbNy_?S!$j!`{l^b4Y~G*xfahq=K37c+ z)1Wfb8r`inH#i=zX8l&j&a~|EZr9hkb2xvzwEMO9>6U5X($1^GwoA=Vn`WtfdEMhb z&(!0!r8OS$yUYGsR~xl#@6P3O-nMK#UT52M^wZN2TR)X6H<=vbzo=xLe~=q=_`2&H z6`$)q&i-4%N<>`O^rn1$BGh$$eXXd$y-9o4@BZ5-EO~Ns&8Ig;7sTtmCY|hhm*TM} zAwg)9{f>8n(dJ%r`&XZE+JEq>!@6%pv1i@3E_<|Ol2iOt^^SvTSx24<`n|VV{aVKL zh2NR4+9_veaq)beux4fRy>(TF`9Hm8O|+K1%Jclzg(njq)J8AvRGm6;`-H^@pKf8y z{<h=rk%C#@H~Br>{K0R_)3+@zvfnhksx9w%XZ9=l|K)FArQB|GvxJMzylWKtXTzGa zt7DkMj;77J_F{1>@9(~cPWBPggs*bVaW?jTax}Y0ZMW=`t!*p(AF}P-^e?(`jm^(Z z44KTr?zulxXP$qqk}q9p`nI{r>`VF91y)~Hy`1tr%q2eMVZl`?&Fg>4UH198R$kwA z>9x0i;D)~<S5(i=XtwXywJ2tv|FCAU_xmF=^Sw961%y;i`w;5A>h}Q!{|G0WX?ms# zIW<dX?s^=X*71uYT;+Yj@4~LVytgDL>y~=7UlZWl>fryuBzwo6pB|t7onbMbt2Z}a zYi@E*XY}spuf=OrrpkVwB^kMBM*-_ey-2^SzpY}5FShodblrUN;@${_1*O|ATCFW{ zd2%h&w@F2l>(}0+>k`s!%U&kS-pt>(zH;`r0`mgvyH`bg_7-i+W$@xWs`RwG(snv; z>wB)a<Ay)pUw;&!ylj6K-;D_^%FiTCTYbNo=Gpyy87x*hRo=p3oz;%^Y4Z*ytf&-` zu?kYY*;X`3Xr1#bY5CNem3P-aE#Q1}p=bZ`r<WY}Es*JS{<CPKa#=wKqlg^ur58Li zE*uYB<Y3{!oBn=U?rYBQoyVuiE&n^MF(G%KzsABtHZyzqojINy**jJA$Yq7}yz9K) z%WGV|KE4{g@sjV>Fuk1Y)?S(AYCVUhc6!xazjufG?ZKNB$0SRW=RdOGN=Z?ZD~p(( zT$-D5>CEq@bJmSKv&)#StPhQl`MFNvioCp<>yizM65p8h-?P{U`p(;aM~G+LHXX0i zaksZe)jhc79Ke_~@1v2!_ek|;+w5*n)%#N5kXda}(sz26=|y$<-Sz7)OjviIOMF&N zRlU!eXs3;9zP#P=(PYA`r<@z#8MOrO>wV#seq!?aieCnAmR^WsQ(tvJ?Yx%oRrcqy z4Kt=zoNv#yxTM@;s(x?b`kF&uE?Q>Aoiv#(l;#}w&uWKr)EVZU=3JHzdk(?Cb@gg` z;{RQujh?DV96fHc=$Xo;$4Atq9@U*Z?HF|I^TibXX-<z<J~`;&KPNY%LCE~<B$H!v zW^DMjFz2nI-0h!+VpG@LIkK=#q3PA?g?5uoUOt=ltwq7bmgRrzf@6tSrA*Fje0Ejr zp5ofOBJUq`+zHG&Z_Zd%?8oF=%IKK(kyB~+wB5X~g_E<7`OMZ*t?=FO$7^!doTE{5 zihcG;UYz*UQSPtEh3AWB?|O3fK+NVCxqnVfQCB?Qq+R=1!X3Ceyj`0iME^hMJHzG0 z5lns^{&Oq8&I${@x_7>R>e-*~*0EI;cBLBdJ~BR}>F}a~JMPk->q`pdr7vk--0|(| zazmk?KSP&Rhx{#V^C&l)?t0{iLAU%zA*H;SE1%wr`u1~f&YJS|YUReIfo@N{tB%cD zFMIEt_SAFpd;9es&z-5vSF>`-1d9*zjw}~mdgVvhi7Tz|3YbcxnQI<7WwL+N_5QWJ z<-5@;7WG}KQMM=Rg5Tz6ZA-8JS@*Fu_GF-fZg~0OH`A_V%y~Y!;^a-=?>gzdhjb42 zPRbUYcVPP+W8OV3I@Ytgd2_vPufM5nJ2CEQ+}jYznTwWhl{{v&ZlCp1kHvqa-v8R8 zw)^ng)3eR)%uDytT(H7lOlDel=&ffnw`4HqP3aV}j6DDC+N<p^N}T5gISS7ybz0Z@ z&g9F*^;VOETi5(PRK&U7DV6_=&G)4Rbv)1Be#_jD`AawFcu28M?kxXok6^}oo|7KT zjO4toxw$~@*8%>r?Ps``tepC!JFceVvFoCqN8%^+oAqy9u4=omsKffsdrLXrH_m;n z1$G)Qzpjz*D%@0a@k91kvu3BabLEeo;+Ew58T3V4HRXiP#f^z=U(aib8mi2VYM=Bi zW-m|AcX6+vmCRuuzr{{Ca#qzU$1`)%M1`#^l8+<H&hq=Qzg)h1>isDd+t$6mRlh;F z_fkgXez)J1g$GYdEZpz1I%aP3OVv|;cdm9#{F%*~8G5pO)fuMb*49kZ>oF@&u&=G# zdw#+9=iVolAGx^N<aCyGxa%3^+uEAP{<*lEXx=j8OJUV9wV*HM?o58{H(ZT%jBkIg z?0)}IQ+MO_wf?m_w?4P-PfOS)dWQe{Bgs?m*G$chIJ(j#{!7EFhzzkUCVO&fEz(r8 zsxzL&rk-sL&9F^h%9_2>{dZoaO{~5KgO>Kq<ecq4b68k2-&Jy)3H_{SE1S1-pX`(K zkNhXhUVP+_!Kvo<qZREd&2yvea)kfM)I4ubl)YON`|+)M#tP-TZF@@@o}JNCiqV#> zlS)ZRd@;{K=a1U`I}g(8@;R>9ryq)UcxjUIFx2_a4Ne1B&lfeHFD7{l`7Cd~y8Y|E z_PD(0=?dFlJbN-Rk8S<QjnPYZi@ANdxF<y|<S&q9dM3T}L-o|XFI|&&Oj=Y_t-I05 zY@JE&hKA64AK3o#?w9zgeP^nWLiPRYx|+*7dLs%i`_9cfn4Yb6IxVSbpP>z#tm~zF zpIf$TSk0XFYzw!^vYL4byVAST?z2^#ajIBm9A4s?f844_nThdhL{p`Jg7fZ|-H(>3 zJT_$xKk|)H=33Xx57YG+=gz%fv7t_G?e|yBW*az!_D?XCjI)(LA?delrttoin{M_w zbGx6G7h9sNyH?2e>gy@*mp?z`cUk*pz1|EHo7Jb5On<##!?M7@x;HVG*@BlTOfpyd z-IzRoX?4n)!(q|aXD<1_#8UW4;zrKHj9)6f3}j4vlWJdI@7?+(^T|S?Tz>~1v&jBR z%cmuO77FQAg+;Zhl{ovWIC}PlZDTaLshBFTX`abW6`m_*i6OSX)ZV&;tu4Pe{p%lI zwGB??pT8bh+Zz~evVP{0J!Y94pLzD56)jTeS*gPN`oyA+xi;$c%ocH9ZCzeV%NC17 ze7AkK@x(v=#_6}7$X6Vl<390tc3jo#uz&;eUC(Zwt9e7D#`5pA%)LEZy$>Y#YfRHf z{-g2oc&5dhv`Y~;OkOU!7+clSx}hngHvHz37wT(SlXy#?B+DOrDVe<0Vs8KDGvBI3 zW51VwSSiZz$MAp2<C2v1C3k;H|8J~mUU<?Z!*p@Foc~P5S4^IlYG?Nq?c_ff`=#;h zG4`ytMYDbziv%_|2}iDv5$gOkUoo%$%-ZXLy*zW2L}x16USc!4vUb}<vHmSgS0+ey zq&~`xzSw;DSX+DV*)sW+9UF6h3YdF(mR_AX>)rLuNp%lqywBM<HS+J4A9+n*lK)L# zAN^5IT|R(iwO^oId)xK7vuC_ZN<Xkg^x*0bb87hSXuP^)z4`b1-C6yis}uaA!}r)6 z(%N!p=4+p=A3COA6P#d^sA#<=N&ULqi8D>h-83(qe)zQ5=#1;Kf2)PL7F+i(%uP_6 z_hz2DHs`Ag|28*ot_##!xJ5knXQ=PfsTD5;uFv!FluPfI)D$fFX;^-w?(fQFoQcMb zb?dm!B%KSZ|E_gQD2R9aXS?T5KKdQKo9=pO&E(aUU%tzxap%weW9D2bxIt=vN@uuk z;6;}g?p3}%uQ*n5O?tF-_w(n^tB$Bo;5a5Yxne@Ysn4R~=a<-DnUO5qy2v$qmBstF zy*UoqzmLqHx^7aPO@#f6x6AKHKlaSKu`-o;WAuvO57ZY03TrTL7pZ)&ANF|Px9!$? zw!(ZpbA(M5Z$+=26+Bsvhuca_;^6NUDwhMe{P*p3o))=UCh?nvMBPKflW#XaJ^AS8 z3A4zA-?wMId)(H~%XaMjv;OVN<@L{e@HO4^W9>2B_Jvc{hp$}h9eeiDXGxikxAMV$ zd!}!Br8=v5viH=Z<w5yQ5`XQEFPWqAZ27DsmGje#PHdV|*Bx?mzjBGmBqjaqJImdE zZCuZE)xX5Gf9ITMk6#`<=<F7wVJ603UbWZZ;4S^>J8hmlP1w!*?cbS+%x5AV?w%QC zp4iEicE)(w)rv{+ZyhfbdKLYRt6k!(<ru4f<=eb(Q|C`%n6te){QSG+uT$RgoZq1l z|0tb*)pdvb7Osj%+K2l%9=$*H{M_<KpOwoeh8Vt|5XX4qT~DO8)aoY9t^4eF569SC z%Kjzyb!QRpWxhrED&Lh}-f?_&B~kSduX%=Rc!K>a*S{)}w;pdi?`!p8*QUvPq?A_5 zMiv)unKl1PZ)Z`Y#(Vaa)e{TuMx10U=yF`P`rR4TZVA`Ti!QbbFaG-XR{tdbntMD8 zZ`IFByU*3bQhiYR!j%Fu(Puqv7oR_z`hI%l<-gK<X8h(qxqbbQTQ^*59=zIjSyxM_ zx`Mmqz+G+I_{0~tx6VEwI8%)E%evjUe|jJ1tFb)Z^{mqQu9xjBzfAeVEl#_v&d<0Z zVCpEdum95Sjn~dD)pL8Px#;eNznhlH9-giez~J00U}x}m3!`OX_Tm{F1(jC}JRNVf z8k+L|VOn`-W`jb_YbS}BtE%k!wJP?=g_+)xUbayDr=i)_qy~ixU2lGEUBqyN{a~I* zX=K8-wI5@ga}{i_eJPq!kkN0kz4Wc2oY^|&^P165|HQcOJ2gFa$J3y5#Y%-+W^D3c zx;n|6cgmKiHfH;at9O@hcZbh?^zGT!pXGvYZ~d+QA@J_WYpw1XGJ?i4JMK@;Hmyie z<=p!%>B^d{I~8@ek{f>7)T@7c^5f<t-6Z?`<nx;B-}U6@*Gu*-_<!+eYsH6uhnH8K zDK{&$I;Nq_KUs-e)m!Sky8Zr3lh+^Jp?N8(b4O5sLGyaMM@iDoXC;Mig=xn&I?VB} zD(<L#(`^?2=<0T%HIn*ivTxS!3f$-YMaI`i;LXdL3d7{28Jk~mROEdR;SEsA*;4f3 z)byM2A8v52OY1!OUQNGhlcl=R%UGS&1-$a9ERFLE@7>>PlW$wLGg-o)MeKx;QtAWC z@39^$_La7uzO!xJlv#-n6yKgW`fZ2lV|@v;2dP(OO1D_r6;;fWQmgr7k~7PDtI^fh zZoLz3u5lA)D-JtuzW3O==^bU&_D|2T>FKAxcw(HVvrBnntj9U`6>;klJQj*v*;wJ~ z6_@!a>1oxUtPq>V+w(uIajRizP<L=xuygs#_I?4`-joN=gnW7C#5q_?$|(!&lHX|? z`26}&{jiXQ=9)cge(mW>?VstuRwe%8rPSI_g?Ikwtv){UTGWG{)kZyepB^7x@BRB` zVqQzOU{HMNzf#j_=k}d->06+mA@O-#$ohyA$4<VeN#%Qgp=j&T+0H$mo_<$#3yQkP zu-1abr?w+SeEVb9H#hHd{N;R7ZRmP$(e?GU5;_VG3e1D0KCOG`S^G+SZ|c&oX@6HR zo$9#O`%*_R+;%48^KAVG2{#=l>raXN==RUB?AYJ>%7j1ljsMkI8WJY7a`QY&c$n1x z@F`Q%AqBnt|6aB<e%#Mcns&0B3uD<5XeAA3osxorf`z4#8At($Yl*q$#t^hjC<wfC z2HT<=JEZ+4u@iUa9X8-`Ew5!gUc&LGYcfw;qf)HRm&RRx8C(|$F>cj4aq7YT^%`uN z7Y;rXtXwabQYaP2maZ%!pBSd>W^nCg!|57su7^G1uU$f$w`tuA|G8f6rR&5qk9WDu zVM|ZDSQ=2X?2*u6uG#6f^FMkrIDC{dVSBB&;ip~i9I5<!{~xsIIcffqGnuvJ?&>f3 zMNS%<Dy?6HY%jd4c6<J#?5`Z9ap5(prr9xjLL`>#Uhv}7ruK6);uc)~pA~v~+UCG; zNtf#rw&(;4#AX{UpYTcaxpvY?9pUR%#ax{eB|U>TFH^f`_`W0h*|aY;VZQ06Z*n(n zPt5D+KjZ$$_Vc_S2Wn3A@47#4o_le{7vH;19=fLwpW3@fFS5PA^4HDD+V%TQnkR~a zLK(W=2)c3$9Jru>S5QzevNQlG0PzeBk>UZe;tI4J%q6urxhS)sB)<p}9r<}Beu=rM z3i^TW5$*ww+J2e2Nu|X>`MG}imOi>csp+K<bvcRY#R?`6c79%o6J+_9uA!NQg07K; zp@N}-v7v&ckqLAam}g01PG+)WUV2Wdf&o~UV{tNQ6`7?G#1N1>Kzxv9u)K3(fk$d) zdPWJz6tGBeNosDGf(1l7h~oj{fIQ-snUksjTHl4d-V3z04di*yqBw+~A*Pikl~jV( zwSmM9!9q@n#i<~p2zoxVsJO&ABe6)q*a)oAClSiGge(vP83OVUBw!W5K@Umpu6fD% zDVcfc3i{!hd5(F-nJ@vcIpLWpB^kvE(F#VUpd5l78yg!#<xLF?6bNAh1tW7%#sryV zY6e<a2x5_sLH2<c_9^Ix<cH>Ef;NaLfU-Dpuwy1Q(Bi>juphlMQ$RihtuG9MCJyKP zQqX!r(9$_r8U`)ggGHQkQEFmIevyJka$;stzJj5ip^2WMfr3UxNlAf~zCKtqy(qCD zBQv>JFTW^VQxj}aKv8~5X>uw_`t0oB*#)#*5#|C=5>e21PAo~x$xnwEo|v9m3|#_= z&{R>Bn#N_IU}(Z+00#<Yrl!WG3TX-uF+*cZV{-+ttU?}C%)r>x2t&-kz|a&^oq-9O zn4z($nGu?pfw7sf8HShzC{2MZhTCgsWNBcGrq0mF(g<Czp|O!AroG07=x#PNF)%=P zi=m03F_KtGQDSCJY7uzvVQ^+uDk!W#Yb=BE^Gg&AL17NbC!Tp}`3i=hQ~*v_#U+VF UCE(CCG%>U=<x*93^>^a}0E#q`5C8xG literal 0 HcmV?d00001 diff --git a/examples/GraphvizTests.ipynb b/examples/GraphvizTests.ipynb index e5b19df..e4786fd 100644 --- a/examples/GraphvizTests.ipynb +++ b/examples/GraphvizTests.ipynb @@ -1,106 +1,9 @@ { "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", @@ -112,346 +15,6 @@ "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": [ @@ -461,269 +24,202 @@ "<!-- 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", + "<svg width=\"779pt\" height=\"544pt\"\n", + " viewBox=\"0.00 0.00 778.50 544.34\" 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 540.34)\">\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", + "<polygon fill=\"white\" stroke=\"none\" points=\"-4,4 -4,-540.34 774.504,-540.34 774.504,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", + "<ellipse fill=\"none\" stroke=\"black\" cx=\"468.504\" cy=\"-509.47\" rx=\"40.1111\" ry=\"26.7407\"/>\n", + "<text text-anchor=\"middle\" x=\"468.504\" y=\"-513.27\" font-family=\"Times,serif\" font-size=\"14.00\">0</text>\n", + "<text text-anchor=\"middle\" x=\"468.504\" y=\"-498.27\" font-family=\"Times,serif\" font-size=\"14.00\">______</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", + "<ellipse fill=\"none\" stroke=\"black\" cx=\"104.504\" cy=\"-404.73\" rx=\"40.1111\" ry=\"26.7407\"/>\n", + "<text text-anchor=\"middle\" x=\"104.504\" y=\"-408.53\" font-family=\"Times,serif\" font-size=\"14.00\">1</text>\n", + "<text text-anchor=\"middle\" x=\"104.504\" y=\"-393.53\" font-family=\"Times,serif\" font-size=\"14.00\">______</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", + "<path fill=\"none\" stroke=\"black\" d=\"M427.911,-507.623C372.424,-505.241 270.643,-496.46 190.504,-464.6 171.21,-456.93 151.934,-444.308 136.536,-432.714\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"138.454,-429.773 128.405,-426.417 134.168,-435.307 138.454,-429.773\"/>\n", + "<text text-anchor=\"middle\" x=\"208.004\" y=\"-453.4\" 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", + "<ellipse fill=\"none\" stroke=\"black\" cx=\"285.504\" cy=\"-289.383\" rx=\"40.1111\" ry=\"37.4533\"/>\n", + "<text text-anchor=\"middle\" x=\"285.504\" y=\"-300.683\" font-family=\"Times,serif\" font-size=\"14.00\">2</text>\n", + "<text text-anchor=\"middle\" x=\"285.504\" y=\"-285.683\" font-family=\"Times,serif\" font-size=\"14.00\">______</text>\n", + "<text text-anchor=\"middle\" x=\"285.504\" y=\"-270.683\" 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", + "<path fill=\"none\" stroke=\"black\" d=\"M428.131,-508.99C374.922,-507.114 284.447,-494.351 253.504,-431.6 242.941,-410.178 244.364,-399.926 253.504,-377.86 257.834,-367.407 266.158,-369.831 271.504,-359.86 275.306,-352.769 278.079,-344.767 280.101,-336.783\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"283.578,-337.264 282.281,-326.749 276.737,-335.778 283.578,-337.264\"/>\n", + "<text text-anchor=\"middle\" x=\"271.004\" y=\"-401.03\" 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", + "<path fill=\"none\" stroke=\"black\" d=\"M431.172,-498.825C397.71,-488.143 350.072,-467.491 324.504,-431.6 304.703,-403.804 294.945,-366.35 290.141,-337\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"293.584,-336.356 288.641,-326.985 286.661,-337.393 293.584,-336.356\"/>\n", + "<text text-anchor=\"middle\" x=\"344.504\" y=\"-401.03\" 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", + "<path fill=\"none\" stroke=\"black\" d=\"M447.446,-486.28C433.575,-471.28 415.308,-450.784 400.504,-431.6 382.941,-408.84 382.184,-400.529 364.504,-377.86 350.444,-359.833 333.611,-340.88 319.102,-325.243\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"321.576,-322.764 312.189,-317.852 316.463,-327.546 321.576,-322.764\"/>\n", + "<text text-anchor=\"middle\" x=\"418.004\" y=\"-401.03\" 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", + "<ellipse fill=\"none\" stroke=\"black\" cx=\"393.504\" cy=\"-163.43\" rx=\"40.1111\" ry=\"37.4533\"/>\n", + "<text text-anchor=\"middle\" x=\"393.504\" y=\"-174.73\" font-family=\"Times,serif\" font-size=\"14.00\">3</text>\n", + "<text text-anchor=\"middle\" x=\"393.504\" y=\"-159.73\" font-family=\"Times,serif\" font-size=\"14.00\">______</text>\n", + "<text text-anchor=\"middle\" x=\"393.504\" y=\"-144.73\" 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", + "<path fill=\"none\" stroke=\"black\" d=\"M464.903,-482.461C460.482,-455.379 451.522,-412.196 435.504,-377.86 431.332,-368.917 426.223,-369.001 422.504,-359.86 416.994,-346.317 405.959,-264.115 399.203,-210.725\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"402.673,-210.272 397.952,-200.787 395.728,-211.146 402.673,-210.272\"/>\n", + "<text text-anchor=\"middle\" x=\"442.504\" y=\"-348.66\" 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", + "<path fill=\"none\" stroke=\"black\" d=\"M472.228,-482.704C473.313,-472.417 474.073,-460.458 473.504,-449.6 471.056,-402.857 473.374,-390.387 462.504,-344.86 448.592,-286.591 435.945,-274.845 414.504,-218.907 413.194,-215.488 411.835,-211.949 410.467,-208.392\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"413.713,-207.08 406.855,-199.005 407.18,-209.594 413.713,-207.08\"/>\n", + "<text text-anchor=\"middle\" x=\"483.004\" y=\"-348.66\" 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", + "<path fill=\"none\" stroke=\"black\" d=\"M481.022,-483.724C495.647,-451.614 516.417,-393.894 504.504,-344.86 491.04,-289.442 453.16,-234.958 425.383,-200.611\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"427.971,-198.248 418.915,-192.749 422.565,-202.695 427.971,-198.248\"/>\n", + "<text text-anchor=\"middle\" x=\"526.504\" y=\"-348.66\" 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", + "<ellipse fill=\"none\" stroke=\"black\" cx=\"451.504\" cy=\"-37.4767\" rx=\"40.1111\" ry=\"37.4533\"/>\n", + "<text text-anchor=\"middle\" x=\"451.504\" y=\"-48.7767\" font-family=\"Times,serif\" font-size=\"14.00\">4</text>\n", + "<text text-anchor=\"middle\" x=\"451.504\" y=\"-33.7767\" font-family=\"Times,serif\" font-size=\"14.00\">______</text>\n", + "<text text-anchor=\"middle\" x=\"451.504\" y=\"-18.7767\" 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", + "<path fill=\"none\" stroke=\"black\" d=\"M489.442,-486.226C495.086,-479.575 500.897,-472.06 505.504,-464.6 532.125,-421.492 540.295,-409.486 550.504,-359.86 571.765,-256.513 513.67,-138.916 477.666,-78.6925\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"480.494,-76.608 472.309,-69.8811 474.513,-80.2442 480.494,-76.608\"/>\n", + "<text text-anchor=\"middle\" x=\"572.004\" y=\"-285.683\" 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", + "<path fill=\"none\" stroke=\"black\" d=\"M508.544,-504.666C564.551,-496.893 659.504,-473.693 659.504,-405.73 659.504,-405.73 659.504,-405.73 659.504,-162.43 659.504,-89.1608 563.085,-58.2029 501.54,-45.9054\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"502.086,-42.4466 491.609,-44.021 500.781,-49.3239 502.086,-42.4466\"/>\n", + "<text text-anchor=\"middle\" x=\"679.504\" y=\"-285.683\" 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", + "<path fill=\"none\" stroke=\"black\" d=\"M507.328,-501.894C581.38,-488.244 735.504,-454.032 735.504,-405.73 735.504,-405.73 735.504,-405.73 735.504,-162.43 735.504,-61.6993 583.574,-42.0094 501.961,-38.6991\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"502.005,-35.1987 491.893,-38.3592 501.769,-42.1947 502.005,-35.1987\"/>\n", + "<text text-anchor=\"middle\" x=\"753.004\" y=\"-285.683\" 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", + "<path fill=\"none\" stroke=\"black\" d=\"M142.076,-414.47C153.69,-414.274 162.809,-411.027 162.809,-404.73 162.809,-400.401 158.499,-397.513 152.031,-396.068\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"152.395,-392.587 142.076,-394.99 151.641,-399.546 152.395,-392.587\"/>\n", + "<text text-anchor=\"middle\" x=\"182.809\" y=\"-401.03\" 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", + "<path fill=\"none\" stroke=\"black\" d=\"M98.6025,-378.068C97.5137,-366.849 98.4802,-354.158 105.504,-344.86 135.321,-305.389 192.891,-293.557 234.921,-290.474\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"235.201,-293.964 244.977,-289.879 234.787,-286.976 235.201,-293.964\"/>\n", + "<text text-anchor=\"middle\" x=\"125.504\" y=\"-348.66\" 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", + "<path fill=\"none\" stroke=\"black\" d=\"M125.308,-381.505C137.194,-369.636 152.82,-355.355 168.504,-344.86 190.42,-330.195 216.912,-317.501 239.142,-308.064\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"240.491,-311.293 248.382,-304.223 237.804,-304.83 240.491,-311.293\"/>\n", + "<text text-anchor=\"middle\" x=\"188.504\" y=\"-348.66\" 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", + "<path fill=\"none\" stroke=\"black\" d=\"M140.147,-392.071C160.935,-384.463 187.176,-373.43 208.504,-359.86 223.87,-350.084 239.114,-337.187 251.934,-325.161\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"254.387,-327.658 259.184,-318.212 249.543,-322.605 254.387,-327.658\"/>\n", + "<text text-anchor=\"middle\" x=\"248.504\" y=\"-348.66\" 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", + "<path fill=\"none\" stroke=\"black\" d=\"M69.8367,-391.023C55.823,-384.043 40.982,-373.892 32.5041,-359.86 0.0558097,-306.155 -16.4967,-266.405 24.5041,-218.907 65.0444,-171.942 251.628,-164.763 342.916,-164.122\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"343.048,-167.622 353.032,-164.075 343.016,-160.622 343.048,-167.622\"/>\n", + "<text text-anchor=\"middle\" x=\"32.0041\" y=\"-285.683\" 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", + "<path fill=\"none\" stroke=\"black\" d=\"M78.7257,-383.814C71.6586,-377.003 64.7748,-368.818 60.5041,-359.86 33.431,-303.071 36.1141,-280.779 47.5041,-218.907 58.35,-159.99 48.895,-130.588 95.5041,-92.9533 141.549,-55.7741 314.163,-43.792 400.98,-40.0722\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"401.279,-43.563 411.128,-39.6584 400.993,-36.5688 401.279,-43.563\"/>\n", + "<text text-anchor=\"middle\" x=\"67.5041\" y=\"-222.707\" 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", + "<path fill=\"none\" stroke=\"black\" d=\"M94.5949,-378.563C91.8365,-367.928 90.5467,-355.555 94.5041,-344.86 120.094,-275.702 148.274,-268.875 202.504,-218.907 269.679,-157.011 358.29,-97.2526 409.676,-64.4244\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"411.646,-67.3195 418.209,-59.0021 407.892,-61.4114 411.646,-67.3195\"/>\n", + "<text text-anchor=\"middle\" x=\"220.004\" y=\"-222.707\" 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", + "<path fill=\"none\" stroke=\"black\" d=\"M323.915,-300.974C335.125,-300.573 343.809,-296.709 343.809,-289.383 343.809,-284.461 339.889,-281.102 333.917,-279.306\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"334.326,-275.828 323.915,-277.793 333.279,-282.749 334.326,-275.828\"/>\n", + "<text text-anchor=\"middle\" x=\"363.809\" y=\"-285.683\" 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", + "<path fill=\"none\" stroke=\"black\" d=\"M256.711,-262.59C245.271,-249.187 236.865,-232.758 246.504,-218.907 268.13,-187.829 309.659,-174.441 343.075,-168.693\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"343.802,-172.123 353.154,-167.144 342.738,-165.204 343.802,-172.123\"/>\n", + "<text text-anchor=\"middle\" x=\"266.504\" y=\"-222.707\" 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", + "<path fill=\"none\" stroke=\"black\" d=\"M293.063,-252.195C296.691,-240.736 301.954,-228.554 309.504,-218.907 319.972,-205.531 334.688,-194.429 348.883,-185.814\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"350.702,-188.805 357.612,-180.773 347.202,-182.743 350.702,-188.805\"/>\n", + "<text text-anchor=\"middle\" x=\"327.004\" y=\"-222.707\" 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", + "<path fill=\"none\" stroke=\"black\" d=\"M373.373,-195.918C364.991,-208.208 354.818,-222.142 344.504,-233.907 337.749,-241.612 330.01,-249.384 322.408,-256.548\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"319.867,-254.13 314.893,-263.485 324.615,-259.274 319.867,-254.13\"/>\n", + "<text text-anchor=\"middle\" x=\"375.504\" y=\"-222.707\" 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", + "<path fill=\"none\" stroke=\"black\" d=\"M415.803,-131.906C420.742,-124.317 425.647,-116.036 429.504,-107.953 433.147,-100.321 436.387,-91.9375 439.187,-83.7156\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"442.52,-84.7847 442.269,-74.1928 435.86,-82.6292 442.52,-84.7847\"/>\n", + "<text text-anchor=\"middle\" x=\"455.504\" y=\"-96.7533\" 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", + "<path fill=\"none\" stroke=\"black\" d=\"M418.585,-59.2899C407.522,-68.1794 396.48,-79.6052 390.504,-92.9533 387.244,-100.236 385.867,-108.39 385.618,-116.479\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"382.122,-116.703 385.85,-126.62 389.12,-116.543 382.122,-116.703\"/>\n", + "<text text-anchor=\"middle\" x=\"408.004\" y=\"-96.7533\" 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", + "<path fill=\"none\" stroke=\"black\" d=\"M491.563,-43.2292C501.965,-42.8756 509.809,-40.9581 509.809,-37.4767 509.809,-35.2464 506.59,-33.6579 501.541,-32.7113\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"501.859,-29.2257 491.563,-31.7241 501.17,-36.1917 501.859,-29.2257\"/>\n", + "<text text-anchor=\"middle\" x=\"527.309\" y=\"-33.7767\" 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", + "<path fill=\"none\" stroke=\"black\" d=\"M490.248,-48.1821C516.955,-50.9748 544.809,-47.4063 544.809,-37.4767 544.809,-28.7882 523.484,-24.97 500.26,-26.0221\"/>\n", + "<polygon fill=\"black\" stroke=\"black\" points=\"499.959,-22.5348 490.248,-26.7712 500.481,-29.5153 499.959,-22.5348\"/>\n", + "<text text-anchor=\"middle\" x=\"562.309\" y=\"-33.7767\" 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'" + "<graphviz.files.Source at 0x7f99d48d7630>" ] }, - "execution_count": 1, + "execution_count": 6, "metadata": {}, "output_type": "execute_result" } @@ -737,11 +233,12 @@ "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", + "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) " + "src.render(train_file + '.gv', view=False)\n", + "Source.from_file(train_file + '.gv')" ] }, { diff --git a/examples/graphivz-output/3.pautomac_light.train.gv b/examples/graphivz-output/3.pautomac_light.train.gv deleted file mode 100644 index 4e539a2..0000000 --- a/examples/graphivz-output/3.pautomac_light.train.gv +++ /dev/null @@ -1,48 +0,0 @@ -// 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 deleted file mode 100644 index ec0f99e07bfcdac4b0e0c21fe5c94795515f90c1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14746 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 I>hHz{00+7hwg3PC diff --git a/examples/graphivz-output/3.pautomac_light_man.train.gv.pdf b/examples/graphivz-output/3.pautomac_light_man.train.gv.pdf deleted file mode 100644 index ec0f99e07bfcdac4b0e0c21fe5c94795515f90c1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14746 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 I>hHz{00+7hwg3PC diff --git a/examples/graphivz-output/round-table.gv b/examples/graphivz-output/round-table.gv deleted file mode 100644 index 48aa015..0000000 --- a/examples/graphivz-output/round-table.gv +++ /dev/null @@ -1,9 +0,0 @@ -// 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 deleted file mode 100644 index ed7810cf4f968b2f4ccd117b59a3e01137c243bd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15059 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 Jb@g}S0sv+@iWdL? diff --git a/splearn/__init__.py b/splearn/__init__.py index 384681e..88d3dc0 100644 --- a/splearn/__init__.py +++ b/splearn/__init__.py @@ -1,5 +1,5 @@ from splearn.automaton import Automaton -from splearn.spectral import Learning +#from splearn.spectral import Learning from splearn.spectral import Spectral from splearn.hankel import Hankel __version__ = "1.1.0" diff --git a/splearn/automaton.py b/splearn/automaton.py index 44338b9..f5a09fe 100644 --- a/splearn/automaton.py +++ b/splearn/automaton.py @@ -4,7 +4,6 @@ import numpy as np - class Automaton(object): """ Define an automaton with parameters @@ -149,7 +148,7 @@ class Automaton(object): raise TypeError(mess) if (type_value == 'classic' or type_value == 'prefix' or type_value == 'suffix' or type_value == 'factor'): - self._type = type_value + self._type = type_value else: raise ValueError("type must be classic, prefix, suffix or factor.") @@ -286,6 +285,26 @@ class Automaton(object): lh[x+1][i, j] = self.val(w) dval[w] = lh[x+1][i, j] return lh + + def to_hankel(self, lrows, lcolumns, mode_quiet=False): + """ Return an Hankel instance (denses, classic and not partial) with matrices + built on lrows and lcolumns from an automaton + + - Input: + + :param list lrows: prefixes + :param list lcolumns: suffixes + :param boolean mode_quiet: (default value = False) True for no + output message. + + - Output: + + :returns: Hankel instance + :rtype: Hankel + """ + from splearn.hankel import Hankel + lhankels = self.BuildHankels(lrows, lcolumns) + return Hankel(mode_quiet=mode_quiet, lhankels=lhankels, rank=self.nbS) def mirror(self): """ Compute the mirror automaton @@ -637,15 +656,31 @@ class Automaton(object): 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" + if np.abs(self.initial[i]) > threshold and np.abs(self.final[i]) > threshold: + 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" + elif np.abs(self.initial[i]) > threshold: + label = "{0:d}\n______\n> {1:" + prec + "}" + label = label.format(i, self.initial[i]) + out += "\t{0:d} [label=\"".format(i) + out += label + "\"]\n" + elif np.abs(self.final[i]) > threshold: + label = "{0:d}\n______\n{1:" + prec + "} >" + label = label.format(i, self.final[i]) + out += "\t{0:d} [label=\"".format(i) + out += label + "\"]\n" + else: + label = "{0:d}\n______" + label = label.format(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): + 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) diff --git a/splearn/hankel.py b/splearn/hankel.py index b20f7bd..41d58ea 100644 --- a/splearn/hankel.py +++ b/splearn/hankel.py @@ -4,9 +4,9 @@ """ from __future__ import division, print_function import scipy.sparse as sps +import scipy.sparse.linalg as lin import numpy as np - class Hankel(object): """ A Hankel instance , compute the list of Hankel matrices @@ -25,7 +25,7 @@ class Hankel(object): - Input: - :param dict sample: sample dictionary + :param dict sample_instance: sample dictionary :param dict pref: prefix dictionary :param dict suff: suffix dictionary :param dict fact: factor dictionary @@ -47,26 +47,45 @@ class Hankel(object): matrix is sparse :param boolean mode_quiet: (default value = False) True for no output message. + :param list of all Hankel matrices. At least one of the two parameters + *sample_instance* or *lhankels* has to be not None. If *sample_instance* is given, + the **Hankel** instance is built directly from the sample dictionnary, + else it is deduced from the *lhankels* list of matrices. + :param int rank: the rank of the Hankel matrices. Required if **Hankel** is build from *lhankels*. """ def __init__( - self, sample_instance, + self, sample_instance=None, lrows=[], lcolumns=[], version="classic", partial=False, - sparse=False, mode_quiet=False): - # Size of the alphabet - self.nbL = sample_instance.nbL - # Number of samples - self.nbEx = sample_instance.nbEx + sparse=False, mode_quiet=False, lhankels=None, rank = -1): + self.version = version self.partial = partial self.sparse = sparse - self.lhankel = self.build(sample=sample_instance.sample, - pref=sample_instance.pref, - suff=sample_instance.suff, - fact=sample_instance.fact, - lrows=lrows, lcolumns=lcolumns, - mode_quiet=mode_quiet) + self.buildFromSample = True + if sample_instance is not None: + # Size of the alphabet + self.nbL = sample_instance.nbL + # Number of samples + self.nbEx = sample_instance.nbEx + self.lhankel = self.build(sample=sample_instance.sample, + pref=sample_instance.pref, + suff=sample_instance.suff, + fact=sample_instance.fact, + lrows=lrows, lcolumns=lcolumns, + mode_quiet=mode_quiet) + elif lhankels is not None: + # Size of the alphabet + self.nbL = len(lhankels) - 1 + # Number of samples + if rank == -1: + raise ValueError("Building an Hankel instance from list of hankel matrices required a valid rank.") + self.nbS = rank + self.lhankel = lhankels + self.buildFromSample = False + else: + raise ValueError("At least sample_instance or lhankel has to be not None.") @property def nbL(self): @@ -245,3 +264,72 @@ class Hankel(object): dcolumns = {lcolumns[i]: i for i in range(nbColumns)} return (drows, dcolumns) + + def to_automaton(self, rank, mode_quiet): + """ Return an automaton from the current Hankel matrix + + - Input: + + :param int rank: the ranking number + :param boolean mode_quiet: True for no output message. + + - Output: + + :returns: An automaton instance + :rtype: Automaton + """ + from splearn.automaton import Automaton + if not mode_quiet: + print("Start Building Automaton from Hankel matrix") + matrix_shape =min(self.lhankel[0].shape) + if (min(self.lhankel[0].shape) < rank) : + raise ValueError("The value of parameter rank ("+ str(rank) + + ") should be less than " + + "the smaller dimension of the Hankel Matrix (" + + str(matrix_shape) + ")") + if not self.sparse: + hankel = self.lhankel[0] + [u, s, v] = np.linalg.svd(hankel) + u = u[:, :rank] + v = v[:rank, :] + # ds = np.zeros((rank, rank), dtype=complex) + ds = np.diag(s[:rank]) + pis = np.linalg.pinv(v) + del v + pip = np.linalg.pinv(np.dot(u, ds)) + del u, ds + init = np.dot(hankel[0, :], pis) + term = np.dot(pip, hankel[:, 0]) + trans = [] + for x in range(self.nbL): + hankel = self.lhankel[x+1] + trans.append(np.dot(pip, np.dot(hankel, pis))) + + else: + hankel = self.lhankel[0] + [u, s, v] = lin.svds(hankel, k=rank) + ds = np.diag(s) + pis = np.linalg.pinv(v) + del v + pip = np.linalg.pinv(np.dot(u, ds)) + del u, ds + init = hankel[0, :].dot(pis)[0, :] + term = np.dot(pip, hankel[:, 0].toarray())[:, 0] + trans = [] + for x in range(self.nbL): + hankel = self.lhankel[x+1] + trans.append(np.dot(pip, hankel.dot(pis))) + + A = Automaton(nbL=self.nbL, nbS=rank, initial=init, final=term, + transitions=trans, type=self.version) + if self.buildFromSample: + A.initial = A.initial / self.nbEx + if self.version == "prefix": + A = A.transformation(source="prefix", target="classic") + if self.version == "factor": + A = A.transformation(source="factor", target="classic") + if self.version == "suffix": + A = A.transformation(source="suffix", target="classic") + if not mode_quiet: + print ("End of Automaton computation") + return A diff --git a/splearn/spectral.py b/splearn/spectral.py index ce8e027..883ffdf 100644 --- a/splearn/spectral.py +++ b/splearn/spectral.py @@ -6,12 +6,9 @@ """ from __future__ import division, print_function import numpy as np -import scipy.sparse as sps -import scipy.sparse.linalg as lin import math from splearn.datasets.data_sample import Splearn_array from splearn.hankel import Hankel -from splearn.automaton import Automaton from sklearn.base import BaseEstimator from sklearn.utils import check_array from sklearn.utils.validation import NotFittedError @@ -33,7 +30,7 @@ class Spectral(BaseEstimator): Start Building Automaton from Hankel matrix End of Automaton computation Spectral(lcolumns=6, lrows=6, partial=True, rank=5, smooth_method='trigram', sparse=True, version='classic') - >>> sp.Automaton.initial + >>> sp.automaton.initial array([-0.00049249, 0.00304676, -0.04405996, -0.10765322, -0.08660063]) >>> sp.predict(data.data) array([ 4.38961058e-04, 1.10616861e-01, 1.35569353e-03, ..., @@ -91,6 +88,8 @@ class Spectral(BaseEstimator): self.smooth_method = smooth_method self._rule_smooth_method(smooth_method) self.mode_quiet = mode_quiet + self._automaton = None + self._hankel = None def get_params(self, deep=True): # suppose this estimator has parameters @@ -110,6 +109,23 @@ class Spectral(BaseEstimator): "smooth_method" : self.smooth_method, "mode_quiet" : self.mode_quiet } + @property + def automaton(self): + """Automaton build by the fit method. None by default""" + return self._automaton + + @automaton.setter + def automaton(self, automaton): + pass + + @property + def hankel(self): + """Hankel build by the fit method. None by default""" + return self._hankel + + @hankel.setter + def hankel(self, hankel): + pass def _rule_smooth_method(self, value): if self.smooth_method not in ['none', 'trigram']: @@ -157,16 +173,16 @@ class Spectral(BaseEstimator): check_array(X) if not isinstance(X, Splearn_array): - self.Automaton = None + self._hankel = None + self._automaton = None return self X = self._polulate_dictionnaries(X) - learn = Learning(data=X) - self.Automaton = learn.LearnAutomaton(rank=self.rank, - lrows=self.lrows, lcolumns=self.lcolumns, - version=self.version, - partial=self.partial, - sparse=self.sparse, - mode_quiet = self.mode_quiet) + self._hankel = Hankel(sample_instance=X, + lrows=self.lrows, lcolumns=self.lcolumns, + version=self.version, + partial=self.partial, sparse=self.sparse, + mode_quiet=self.mode_quiet) + self._automaton = self._hankel.to_automaton(self.rank, self.mode_quiet) # for smooth option compute trigram dictionnary if self.smooth == 1: self.trigram = self._threegramdict(X.sample) @@ -421,10 +437,13 @@ class Spectral(BaseEstimator): """ check_array(X) - if not hasattr(self, 'Automaton'): + if not hasattr(self, 'automaton'): raise NotFittedError("This %(name)s instance is not fitted " "yet" % {'name': type(self).__name__}) - if self.Automaton is None: + if self._automaton is None: + print("No Automaton has been computed, " + "check the format of the input fit data") + warnings.warn("check the format of the input fit data", UserWarning) return X Y = self.predict_proba(X) @@ -447,12 +466,12 @@ class Spectral(BaseEstimator): """ #check_is_fitted(self, "classes_") X = check_array(X) - if not hasattr(self, 'Automaton'): + if not hasattr(self, 'automaton'): raise NotFittedError("This %(name)s instance is not fitted " "yet" % {'name': type(self).__name__}) # if Automaton is None because the fit pass through doing nothing - if self.Automaton is None: + if self._automaton is None: print("No Automaton has been computed, " "check the format of the input fit data") warnings.warn("check the format of the input fit data", UserWarning) @@ -472,10 +491,10 @@ class Spectral(BaseEstimator): w = X[line, :] w = w[w >= 0] w = tuple([int(x) for x in w[0:]]) - val = self.Automaton.val(w) + val = self._automaton.val(w) if self.smooth == 1 and val <= 0: - Y[i] = self._trigramprobability(w, trigram_test) - trigram_index[i] = True + Y[i] = self._trigramprobability(w, trigram_test) + trigram_index[i] = True else: Y[i] = val i += 1 @@ -569,214 +588,4 @@ class Spectral(BaseEstimator): raise ValueError(msg) return perplexity else: - return - self.loss(X, y, normalize=True) - -class Learning(object): - """ A learning instance - - :Example: - - >>> from splearn.spectral import Learning, Spectral - >>> train_file = '0.spice.train' - >>> from splearn.datasets.base import load_data_sample - >>> from splearn.tests.datasets.get_dataset_path import get_dataset_path - >>> train_file = '3.pautomac_light.train' # '4.spice.train' - >>> data_sample = load_data_sample(adr=get_dataset_path(train_file)) - >>> from splearn.spectral import Learning, Spectral - >>> cl = Spectral() - >>> cl.set_params(partial=True, lcolumns=7, lrows=7) - Spectral(lcolumns=[], lrows=[], partial=True, rank=5, sparse=False, version='classic') - >>> cl.fit(data_sample.data) - >>> S_app = Learning(data=data_sample.data) - - - Input: - - :param Splearn_array data: an instance of Splearn_array - (ndarray, nbL, nbEx, and dictionaries ) - - """ - - def __init__(self, data): - - # # Size of the alphabet - # self.nbL = sample_instance.nbL - # # Number of samples - # self.nbEx = sample_instance.nbEx - # # The dictionary that contains the sample - # self.sample = sample_instance.sample - # # The dictionary that contains the prefixes - # self.pref = sample_instance.pref - # # The dictionary that contains the suffixes - # self.suff = sample_instance.suff - # # The dictionary that contains the factors - # self.fact = sample_instance.fact - # The pLearn that contains Samples dictionaries - self.splearn_object = data - - @property - def splearn_object(self): - """Sample object, contains dictionaries""" - - return self._splearn_object - - @splearn_object.setter - def splearn_object(self, splearn_object): - if not isinstance(splearn_object, Splearn_array): - raise TypeError("sample_object should be a Splearn_array") - self._splearn_object = splearn_object - - @staticmethod - def BuildAutomatonFromHankel(lhankel, nbL, rank, mode_quiet, - sparse=True, version='classic', - ): - """ Build an automaton from Hankel matrix - - - Input: - - :param list lhankel: list of Hankel matrix - :param int nbL: the number of letters - :param int rank: the ranking number - :param boolean sparse: (default value = False) True if Hankel - matrix is sparse - :param version: version of Automaton - :param boolean mode_quiet: True for no output message. - - - Output: - - :returns: An automaton instance - :rtype: Automaton - """ - if not mode_quiet: - print("Start Building Automaton from Hankel matrix") - if not sparse: - hankel = lhankel[0] - [u, s, v] = np.linalg.svd(hankel) - u = u[:, :rank] - v = v[:rank, :] - # ds = np.zeros((rank, rank), dtype=complex) - ds = np.diag(s[:rank]) - pis = np.linalg.pinv(v) - del v - pip = np.linalg.pinv(np.dot(u, ds)) - del u, ds - init = np.dot(hankel[0, :], pis) - term = np.dot(pip, hankel[:, 0]) - trans = [] - for x in range(nbL): - hankel = lhankel[x+1] - trans.append(np.dot(pip, np.dot(hankel, pis))) - - else: - hankel = lhankel[0] - [u, s, v] = lin.svds(hankel, k=rank) - ds = np.diag(s) - pis = np.linalg.pinv(v) - del v - pip = np.linalg.pinv(np.dot(u, ds)) - del u, ds - init = hankel[0, :].dot(pis)[0, :] - term = np.dot(pip, hankel[:, 0].toarray())[:, 0] - trans = [] - for x in range(nbL): - hankel = lhankel[x+1] - trans.append(np.dot(pip, hankel.dot(pis))) - - A = Automaton(nbL=nbL, nbS=rank, initial=init, final=term, - transitions=trans, type=version) - # ms=np.linalg.pinv(vt) - # init=h.dot(ms)/self.nbEx - # print(type(init),init.shape) - # mp=np.linalg.pinv(u.dot(np.diag(s))) - # v=v.todense() - # term=np.dot(mp,v) - # trans=[] # a suivre - if not mode_quiet: - print ("End of Automaton computation") - return A - - def LearnAutomaton(self, rank, lrows=[], lcolumns=[], version="classic", - partial=False, sparse=False, - mode_quiet=False): - """ Learn Automaton from sample - - - Input: - - :param int rank: the ranking number - :param lrows: number or list of rows, - a list of strings if partial=True; - otherwise, based on self.pref if version="classic" or - "prefix", self.fact otherwise - :type lrows: int or list of int - :param lcolumns: number or list of columns - a list of strings if partial=True ; - otherwise, based on self.suff if version="classic" or "suffix", - self.fact otherwise - :type lcolumns: int or list of int - :param string version: (default = "classic") version name - :param boolean partial: (default value = False) build - of partial Hankel matrix - :param boolean sparse: (default value = False) True if Hankel - matrix is sparse - :param boolean mode_quiet: (default value = False) True for no - output message. - - - Output: - - :returns: An automaton instance - :rtype: Automaton - - """ - lhankel = Hankel(sample_instance=self.splearn_object, - lrows=lrows, lcolumns=lcolumns, - version=version, - partial=partial, sparse=sparse, - mode_quiet=mode_quiet).lhankel - matrix_shape =min(lhankel[0].shape) - if (min(lhankel[0].shape) < rank) : - raise ValueError("The value of parameter rank ("+ str(rank) - + ") should be less than " + - "the smaller dimension of the Hankel Matrix (" + - str(matrix_shape) + ")") - A = self.BuildAutomatonFromHankel(lhankel=lhankel, - nbL=self.splearn_object.nbL, - rank=rank, - sparse=sparse, - version=version, - mode_quiet=mode_quiet) - - - A.initial = A.initial / self.splearn_object.nbEx - if version == "prefix": - A = A.transformation(source="prefix", target="classic") - if version == "factor": - A = A.transformation(source="factor", target="classic") - if version == "suffix": - A = A.transformation(source="suffix", target="classic") - return A - -# @staticmethod -# def Perplexity(A, adr): -# """ Perplexity calculation """ -# Cible = Automaton.load_Spice_Automaton("./" + adr + ".target") -# Test = Learning(adr="./"+adr+".test") -# sA, sC = 0, 0 -# for w in Test.sample_object.sample: -# sA = sA + abs(A.val(w)) -# sC = sC + abs(Cible.val(w)) -# s = 0 -# for w in Test.sample_object.sample: -# s = s + Cible.val(w)/sC*math.log(abs(A.val(w))/sA) -# p = math.exp(-s) -# return p - -# if __name__ == '__main__': -# from sksplearn.datasets.get_dataset_path import get_dataset_path -# adr = get_dataset_path("essai") -# P = Learning(adr=adr, type='SPiCe') -# -# print("nbL = " + str(P.nbL)) -# print("nbEx = " + str(P.nbEx)) -# print("samples = " + str(P.sample)) -# print("prefixes = " + str(P.pref)) -# print("suffixes = " + str(P.suff)) -# print("factors = " + str(P.fact)) + return - self.loss(X, y, normalize=True) \ No newline at end of file diff --git a/examples/graphivz-output/3.pautomac_light_man.train.gv b/splearn/tests/datasets/3.pautomac_light.train.gv similarity index 89% rename from examples/graphivz-output/3.pautomac_light_man.train.gv rename to splearn/tests/datasets/3.pautomac_light.train.gv index d0bd11b..630afa0 100644 --- a/examples/graphivz-output/3.pautomac_light_man.train.gv +++ b/splearn/tests/datasets/3.pautomac_light.train.gv @@ -1,24 +1,17 @@ -//automata.dot +//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"] diff --git a/splearn/tests/test_automaton.py b/splearn/tests/test_automaton.py index 69dd1e8..72416fa 100644 --- a/splearn/tests/test_automaton.py +++ b/splearn/tests/test_automaton.py @@ -6,7 +6,8 @@ import math from splearn.automaton import Automaton from splearn.tests.datasets.get_dataset_path import get_dataset_path - +from splearn.datasets.base import load_data_sample +from splearn import Spectral class UnitaryTest(unittest.TestCase): @@ -259,9 +260,9 @@ class UnitaryTest(unittest.TestCase): A = Automaton(nbl, nbe, i, t, trans) np.testing.assert_almost_equal(A.sum(), 1) - def test_load_Spice_Automaton(self): + def test_load_Pautomac_Automaton(self): adr = get_dataset_path("pautomac3.txt") - A = Automaton.load_Spice_Automaton(adr) + A = Automaton.load_Pautomac_Automaton(adr) r = A.nbL, A.nbS self.assertEqual(r, (4, 25)) # à compléter @@ -289,6 +290,20 @@ class UnitaryTest(unittest.TestCase): dic = A.calc_prefix_completion_weights([-1]) self.assertEqual(set(dic.keys()), {0, 1, -1}, "test_calc_prefix_completion_weights failed") + + def test_get_dot(self): + 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) + print(dot) + gold_file = train_file + ".gv" + gold_str = "" + with open(get_dataset_path(gold_file), 'r') as f: + gold_str = f.read() + self.assertEqual(dot, gold_str, "test_get_dot failed") if __name__ == '__main__': unittest.main() diff --git a/splearn/tests/test_hankel.py b/splearn/tests/test_hankel.py index 8e6e34e..1057439 100644 --- a/splearn/tests/test_hankel.py +++ b/splearn/tests/test_hankel.py @@ -5,7 +5,7 @@ import unittest from splearn.datasets.base import load_data_sample from splearn.automaton import Automaton -from splearn.spectral import Spectral, Learning +from splearn.spectral import Spectral from splearn.hankel import Hankel from splearn.tests.datasets.get_dataset_path import get_dataset_path import numpy as np diff --git a/splearn/tests/test_spectral.py b/splearn/tests/test_spectral.py index ce71a71..20ab7ec 100644 --- a/splearn/tests/test_spectral.py +++ b/splearn/tests/test_spectral.py @@ -5,7 +5,7 @@ import numpy as np import unittest from splearn.datasets.base import load_data_sample from splearn.automaton import Automaton -from splearn.spectral import Learning, Spectral +from splearn.spectral import Spectral from splearn.tests.datasets.get_dataset_path import get_dataset_path @@ -17,14 +17,14 @@ class UnitaryTest(unittest.TestCase): cl = Spectral(partial=False, sparse=False, version="prefix") X = data.data cl.fit(X=X) - np.testing.assert_almost_equal(cl.Automaton.initial, + np.testing.assert_almost_equal(cl.automaton.initial, np.array([-1.21159819e+00, -1.78488894e-01, 1.30974719e-02, -1.66533454e-16, -3.70074342e-17])) cl = Spectral(partial=False, sparse=False, version="suffix") cl.fit(X=X) - np.testing.assert_almost_equal(cl.Automaton.initial, + np.testing.assert_almost_equal(cl.automaton.initial, np.array( [-3.16481225e-01, -1.95397796e-01, 2.89623130e-01, 1.85499764e-15, @@ -32,7 +32,7 @@ class UnitaryTest(unittest.TestCase): cl = Spectral(partial=False, sparse=False, version="factor", mode_quiet=False) cl.fit(X=X) - np.testing.assert_almost_equal(cl.Automaton.final, + np.testing.assert_almost_equal(cl.automaton.final, np.array([ -4.35303631e-01, 1.49070953e+00, 4.80783716e-01, @@ -55,7 +55,7 @@ class UnitaryTest(unittest.TestCase): self.assertEqual(param.get("partial"),False) X = np.array([[1, 2, 3, 6],[0, 0, 2, 5]]) cl.fit(X=X) - self.assertEqual(cl.Automaton, None) + self.assertEqual(cl.automaton, None) def test_fit_spectral_notsparse(self): adr = get_dataset_path("essai") @@ -63,7 +63,7 @@ class UnitaryTest(unittest.TestCase): data = load_data_sample(adr=adr) cl = Spectral(partial=False, sparse=False) cl.fit(X=data.data) - self.assertIsInstance(cl.Automaton,Automaton,"fit function fails") + self.assertIsInstance(cl.automaton,Automaton,"fit function fails") def test_fit_spectral_sparse(self): adr = get_dataset_path("essai") @@ -71,7 +71,7 @@ class UnitaryTest(unittest.TestCase): data = load_data_sample(adr=adr) cl = Spectral(partial=False, sparse=True, rank=4) cl.fit(X=data.data) - self.assertIsInstance(cl.Automaton,Automaton,"fit function fails") + self.assertIsInstance(cl.automaton,Automaton,"fit function fails") def test_predict_spectral(self): @@ -108,28 +108,6 @@ class UnitaryTest(unittest.TestCase): self.assertAlmostEquals(p, -1.7917594692280561) - def test_constructor_learning(self): - adr = get_dataset_path("essai") - # adr = get_dataset_path("3.pautomac.train") - data = load_data_sample(adr=adr) - cl = Spectral() - cl._polulate_dictionnaries(data.data) - # adr = get_dataset_path("essai") - L = Learning(data=data.data) - with self.assertRaises(TypeError): - data.nbL = 2.0 - # nbEx assignment - with self.assertRaises(TypeError): - data.nbEx = 6.0 - # # sample assignment - # self.assertRaises(TypeError, L.splearn_object.sample, "sample") - # # pref assignment - # self.assertRaises(TypeError, L.splearn_object.pref, "pref") - # # suff assignment - # self.assertRaises(TypeError, L.splearn_object.suff, "suff") - # # fact assignment - # self.assertRaises(TypeError, L.splearn_object.fact, "fact") - def test_trigram(self): adr = get_dataset_path("3.pautomac.train") data = load_data_sample(adr=adr) @@ -216,9 +194,8 @@ class UnitaryTest(unittest.TestCase): def test_BuildAutomatonFromHankel(self): # a suivre A = Automaton.SimpleExample() - lh = A.BuildHankels([(), (0,), (1,)], [(), (0,), (1,)]) - B = Learning.BuildAutomatonFromHankel(lh, nbL=2, rank=2, sparse=False, - mode_quiet=False) + H = A.to_hankel([(), (0,), (1,)], [(), (0,), (1,)], mode_quiet=False) + B = H.to_automaton(rank=2, mode_quiet=False) np.testing.assert_almost_equal(A.val([]), B.val([])) np.testing.assert_almost_equal(A.val([0]), B.val([0])) np.testing.assert_almost_equal(A.val([0, 0]), B.val([0, 0])) -- GitLab