From 421f07854e35f03ec25b5bfada47e6bb519f76f4 Mon Sep 17 00:00:00 2001 From: saudzahirr Date: Sun, 10 May 2026 18:08:04 +0500 Subject: [PATCH] Remove old docs and revision history --- .claude/settings.local.json | 9 + .gitignore | 3 + doc/Makefile | 90 --------- doc/_static/favicon.ico | Bin 9918 -> 0 bytes doc/_static/logo.png | Bin 25387 -> 0 bytes doc/_static/lstsq_fit.png | Bin 27183 -> 0 bytes doc/_templates/layout.html | 89 --------- doc/index.rst | 233 ----------------------- doc/index_TOC.rst | 10 - doc/linalg.rst | 285 ---------------------------- doc/make.bat | 112 ----------- doc/user_guide.rst | 359 ------------------------------------ docs/api.md | 23 +-- docs/index.md | 6 +- docs/quickstart.md | 41 ++-- revision_history.txt | 86 --------- 16 files changed, 47 insertions(+), 1299 deletions(-) create mode 100644 .claude/settings.local.json delete mode 100644 doc/Makefile delete mode 100644 doc/_static/favicon.ico delete mode 100644 doc/_static/logo.png delete mode 100644 doc/_static/lstsq_fit.png delete mode 100644 doc/_templates/layout.html delete mode 100644 doc/index.rst delete mode 100644 doc/index_TOC.rst delete mode 100644 doc/linalg.rst delete mode 100644 doc/make.bat delete mode 100644 doc/user_guide.rst delete mode 100644 revision_history.txt diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 0000000..55411f8 --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,9 @@ +{ + "permissions": { + "allow": [ + "Bash(uv run pytest -sv)", + "Bash(uv run ruff check .')", + "Bash(uv run ruff format --check .')" + ] + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore index b3ec7d5..9054a00 100644 --- a/.gitignore +++ b/.gitignore @@ -218,3 +218,6 @@ __marimo__/ # Streamlit .streamlit/secrets.toml + +# Claude local settings +!.claude/*.json diff --git a/doc/Makefile b/doc/Makefile deleted file mode 100644 index 544991e..0000000 --- a/doc/Makefile +++ /dev/null @@ -1,90 +0,0 @@ -# Makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -PAPER = - -# Internal variables. -PAPEROPT_a4 = -D latex_paper_size=a4 -PAPEROPT_letter = -D latex_paper_size=letter -ALLSPHINXOPTS = -d _build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . - -.PHONY: help clean html dirhtml pickle json htmlhelp qthelp changes linkcheck doctest # latex - -help: - @echo "Please use \`make ' where is one of" - @echo " html to make standalone HTML files" - @echo " dirhtml to make HTML files named index.html in directories" - @echo " pickle to make pickle files" - @echo " json to make JSON files" - @echo " htmlhelp to make HTML files and a HTML help project" - @echo " qthelp to make HTML files and a qthelp project" -# @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" - @echo " changes to make an overview of all changed/added/deprecated items" - @echo " linkcheck to check all external links for integrity" - @echo " doctest to run all doctests embedded in the documentation (if enabled)" - -clean: - -rm -rf _build/* - -# The HTML needs latex because the PDF version is linked to: -html: # latex -# (cd _build/latex; make all-pdf) - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) _build/html - @echo - @echo "Build finished. The HTML pages are in _build/html." - -dirhtml: - $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) _build/dirhtml - @echo - @echo "Build finished. The HTML pages are in _build/dirhtml." - -pickle: - $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) _build/pickle - @echo - @echo "Build finished; now you can process the pickle files." - -json: - $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) _build/json - @echo - @echo "Build finished; now you can process the JSON files." - -htmlhelp: - $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) _build/htmlhelp - @echo - @echo "Build finished; now you can run HTML Help Workshop with the" \ - ".hhp project file in _build/htmlhelp." - -qthelp: - $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) _build/qthelp - @echo - @echo "Build finished; now you can run "qcollectiongenerator" with the" \ - ".qhcp project file in _build/qthelp, like this:" - @echo "# qcollectiongenerator _build/qthelp/uncertaintiesPythonpackage.qhcp" - @echo "To view the help file:" - @echo "# assistant -collectionFile _build/qthelp/uncertaintiesPythonpackage.qhc" - -# latex: -# $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) _build/latex -# @echo -# @echo "Build finished; the LaTeX files are in _build/latex." -# @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ -# "run these through (pdf)latex." - -changes: - $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) _build/changes - @echo - @echo "The overview file is in _build/changes." - -linkcheck: - $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) _build/linkcheck - @echo - @echo "Link check complete; look for any errors in the above output " \ - "or in _build/linkcheck/output.txt." - -doctest: - $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) _build/doctest - @echo "Testing of doctests in the sources finished, look at the " \ - "results in _build/doctest/output.txt." diff --git a/doc/_static/favicon.ico b/doc/_static/favicon.ico deleted file mode 100644 index 2fca2a72e6253c63b34c35e63dec1bfe860b04e6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9918 zcmeI2XP6Xaw#NYp5+sNyf`DNSEMZnx5H5&{Ai{!(F1n&Cf|3?d)T=C#(-3FK!!R>2 zIp@gaoD-9C&N=6R_g7UtMbq7*+zsG-NM-h3kWTepCD0yZ76@-+t@AcdxgzgW? zT5DU|0o>lx%Vcip7p?I7@}&neM*@Z|`b48(IO$-?;;IE}3Uf4pxSQ?R?ADo^On3lzNcvgOFesM}k1(-`4no%;7xdl&9C|0BN0o_PX0iKFe zwfFQ4_*HLrUq3LIz}g1@D-cV!qZTHkCDa9s_=1vv)J&I{M62M)+rB|Y-hq6Z2ZlLB z#Cav8gl6R4Eh@{ct}Ab9!5P{_HxPvns#G4vbD0AY9)$BWc68Race2=;*7n-A4*Uuu zvT&r~bxaeYfP2JcN`^oiU44Dbsc34+s;r63E^v=aGVu#JWn#7Fi_P;FFMWQ_yamfw zez0ZR0X@U(Zr&Dw;hqV}s5-5z63z3hmac9jD4-4~Q2ti}iJ}0&OyE^Ex8g#1HFbDY zW<@m*Wz_|>4VbB_rIocajpc}F`;mhLFcUZ|5ObqRKsrYy+;I0<{rQ)}M~qO(6^{%b zuJz_yKk8fst!-Gee@bRTVF`X))!f?L*#!*IT_4b@3{tWeZVw(77?)ohmYElrnuQQ- z7o46QnNxtY^zteulsC4ZVbCHIoRTe&z!D1U8o1Xj_O70r_u^G+R1hkk4twO0w>JF! zoQ*R&#|>igidY~jYU+3Zs$eY9%>d8iFf>oks;I%q{gN}BqTBFZhHC|c=;Rq z2IFHc(TV&Nl~X_zuzY0V4B|?EL$|=jEmKP?e3Q~|c?WLXwMQA%VB=?J&)t9Hmcg9> zx7ehpoI)&!+YCS@5CqraTiK~FG2Y@DlgLx{UA(?@&ALC$)0+PL3-cB)U9s`At@{t_ z*tvokOZg%ZBhWAA1b5Jtd~qcA$lFKuilRXRt-U$AwaF!_n!7oz^_ zs4-){K78_qr@w3L-RRsRBA1Yq0#*ueVke`#ijXn!3w}ta;wi7ZzVM)d=}j+xjDj2% zi^qm%L!hlg(PL7 z2OT??NmB$0@{pg$CO!V;zC)sO_K{=ptALbDLofe#1~>YIDNnt<>8nkLPJDUn?D8+R zj(dEv%Cp9fpYYQaeIuXXJ9pEt4h~=4+FnPhY-uCJLNap9{6jbG{aNL%KRg{ebm)L{ zwvo;5B&J?-@tVEh4UIRBe`3l%_8tD=s=*;+t7GPN2X9;Lxv2NzYYS8+Pnj|EsELhf zV7OmOW>QH-L0v;xQ)^*;V^T>u^6^ZqCCgN9d6-jhViz(}QgIn+Q`g@0$!BJ2yz$*l zoA>D(>pFSd@(VEwisbu}%bi2Ft>*mKn=12PeD(FScCJ>T(Loux$)%Oq)%6*bHBq@m zj*;=_ZJZx}>S>kv^6AJ&M^Afc_T=d^)cuN#fwz|lK~zGzIBVrN=CSeejq+gB=rMaP zT-9-Kvkr^#PRWgCY(Z z7z=z@)91-&U-)$Y(QRig?$*`Yaqh~J4>yh;_n16U5$p}kY(owavDy}PBS$?d|0)lj zo2PZi$o#f%F!17w%F@cKQB-73p+`c>E#DB_VAkxp@?-`>hYkDc;Bh^#0LPfS0U3Eg zS^4gXX)NlSBd3(7$zwFR@uy#Zx^8sR%JG7u$9a3V6BhRP*!*ShNOJ_7UEPq(*t{Y# z{3&x=9wFZ@544uObK270E<6ToL_|qLb4g<}1LE2|>H#64R_B6E3-Wuix>l@*H{m>|CuMuNvq$dYA@9*heKeL?u`RN9uX{owRgV zvt)*I+oTZGF7s-uodPMI7KI3ar6FYw@{BMe?Iuv z-jntox}E{&-TV%i*)Ll6k@Bzd_{(39Tz2+!jZKQlFUhQ|&8?}=tgIok1*B!!hR0lS z^;Y-KQKLu8x66a~zu0os#nU@6mGlL+)-Hj^vKvZ#HM627G&9d8Eatp}`>XG)l<#6N zcH*Qxdd3H=T{ynGX{NPeweqj>_`CC$+0Fe@GSbScN*i0qx|PjsMfHtoWmTb>xdg0w zyp#Xs+vUOXjh{(4VJ~cm@BtRc#w}4b(nV@nrGIKBY4ezw?UWg_qttWY6WB!V}`kwuqTL6H;$_2kttp^N13=X1wm#6Pt8zeyn}zg{6x4 zl_fJEOb!{ELPX(v?6$z8JVXP0!&jyHLfVgDVyUH-p7F_-9X(#udR1A7G+was{Y#GS zOu#>xtiUN&i&%tHw(`81`l#GO$LNI1uHMT({ajhd)IZN(b4+LD0qt2!-d4UYjUOE| z_Q)-B%b@Vc?0kqiWCM^rLWv>R3pNW>C?c>iC1eJM%)Ykpz4z5c&0qQ!swUo1J8^`6 zqDeTR#DNjWW&wWc)8LF;%g|_TTbE~E6nY)5JZyugHTDqedOQZDAE0 z0sAeiZ9s=ot&P2;DgdYwNu~^eGzO(*8QlrkunqAWokjGz3(2~%sEkSGcPT#>xQlBJ4ODu3`F?818UYwKh3i=AVWF1z`z z_~I*B0)y$RKAiO0V&yCH_>h4KlrkbKzo51ryWbbCDBpxW1{W2nKCj3=Jcg}v?1Txj z1ZhC>rw)RZg=OaERo4+XD3CRxPo;`gVSUn+X#JQ|wysm3dqEa8dg?Rd=d1E7>DOPb z>LVNi3>6gov!_>5f*@Qh1JSJ%@_1cxak)oa67e$obq&;R^S=*MlK7`&kSK^6!W@fm zyNFaQu0_g?cTpO^=Z z#X3$1B_0g`|Ktq7tlP3(S%@?ygK_u4p2ME5Q5tR_$38uogrYJJY6K6zjek^Y zP+ID{`}ifLi%!+1juWt=@O$KHvZ!GClnh#4pYHil1t+H)c6>{(hFwWyBQ4}iMRt=)(AW(RpH-W_l;ubR3gYiCTtVCD972LX zxPhor!8r${3HcdqumsX6K2JICNL#?pb#IC)_P6Wp%Qp2BZ!M z7rHkJ$u#=l1J)r?$4#u%xzp<_R?(wyjEsXGqf!#7s8Ru&WGCrgRH|5bb1U48+SAA< zXrJCK_6rq+(&@x0Po6TfAxJ5IO6r@i1-BDON?|HM6^teB`;xJe#Txd8hwu7ryHv!| zO!!652$ezxpf0Rk2z*8RS3oKq;Dkuvr7(X;Z$wU^O?a%fwbSaYJ5>Zqr&#KUp_yf% zNJZqWb71YtT9u4N_QqHwTPQjmvvao2)1Lp6isXf>{&vpR#WpO49ylcuv>7ugx?cBN z?t+VQy#{Icd|olR^t^+|E}iSsXU|a)D4p&+e%jb4h-8vmRV$fEIn~Qh(S@W^gyW?& z7->S@@(KF(jIK&0!v3=L@X2d#KD3gsJ|z-R(JDboeg+<0<&NH79A@Fe(a_LpqJMVs? zT6|4;X69jID?^_kkNA|>f?`NGxfc^Rc60%lZx9k?g>^#VfYDv!lJ&g<4;Wkh^Z2=W zE7uGkIZ9on3s;du7mr21CwPR|6}Cn2dZWjX|Q^UE%SCjV0Rq? zs~21pOlqG2>kByw>!TbBcFJKPQJ>bKAFCq#jkO>Cddrdkp)4{FjJ-*E(Z^ec>@>}AdZd^VFA{g92X=X7yug>NFJ_f?3MscZ=9y;RYih)3MISd=IzD4 zTv|aZl1*eV7nJ}jtS=@O-nQUuY^FrF1a-`KRTj;I#!Y;D=Ipsz@2s4=^zE6m=R7t@ zK9?bB96UQ`9-Sqp=)3WSW%PxbI)xWfGGSI$rUIwv6vV!?O%u7$ExZn>2Ht`HeMSF? z=`%Dw=;1Gp9HZ(&+)IIc*u>g8B97KgeqCcduXw~4XPP`zfqKAEg#wLD3aDt6Y)RM4 zBp~dJjq{@S*J|uU{UOvzPfvUElP}ip`B`IFZP@jld3an%PEk&6V=aZe_|oKeZ~|9M zQ&MG0f2NCMPK8d=V6%p*UH9ISg^^JeIY5K!8qcvN1 zj!^4iLP#v45`%M#vuYZv+dAoD{l1G1IDo`X`zfr1O|Z3{{Ew4|W#zfYC(~Y|_x0Vm zOXyZTYe{HFj2t!NrB|SrKk8m%x4r7-ee+JBflrX0mp_fTA9Sz5=u{m3;B|xW!m^yY z=9+e)+Xhb#XK+^c1L5!FExvUD$gZ0iF?6JUv%F!LpJE0 z$It9Kdg_v`V?udNVN+{;XHN$VN8Bit5Dhw%9DtMy)r6?9GqPJzBJqlZ?22w-!h{&i zgw8gJowhTFiGQeNaD;t$EL{|+0$W>LK?&OybrVNwSyg;tX?S)4nB5anonn)n;#1v| zvjTF8VoR&C>zgauI-BSUim$eR-#?Xc6IM(nMZgWn6{J?`U(mu8;UT=pJC1_^{azeCy}bG^4g8|=xZ?7J(yG*|y4?Ea z^45-quAX+W%fu_~hsP;lmV5xk;@c28(6YTkIS4VFfz69e0oY^)4#*+fA8Mx=$cpH~ zVF*$;cX2S_bl~0=vSo2&OG#5}c}qKP+1S<7*3;K5^x1>}(YSRgt5JO{-Nd~D+CIT) z*jBv!h+Lt5!h>F#cjmX>aimhN0|>F!jz8&=@XfA4em8EVi~oJSkzmU90-hvslh$_AaI|#uG;y(j^Yrv&vvII>H8XLtU~_b_%03e! zg@dDpla~_L^!jnq%je|{hE?YNyS0#$id zm4y&DP9{mA1P(5lo`x`%hBD#&*h^XsCjmkevjb*7MV002$8}JUOAeDL2vTAQbrTRi zg!1=)523ijAdHn}iV4wVM$*zsn%q}oPF1a4ycb#kgT5=gE3fpC+WYUl@modOEVS9< zlu3`cPqbWPL>dH0F@@AgazXpva>De*@r9Q<`5fy0TDc@u=^%0d`QjVheL2}1Z%qc6^pNe;!*R3iYc(T+#( z%9Uapbs(sasm`7(t2B7uTdHU}o+ZtG)eWI5?`k1`pTGZsS{^TEh*rIVfG6NvK?+TfL7CqR!HGL>UU8EF5}9VJr)1|cNVPuq(0X3s8(nK7hB)Zz;Wlg+8h@bhdI*l&9ojE z@`FjxK)%j=5x1KUm`j2egwS4dA2--hpvu$>2GOUC3eR2*z(bsYvnE{aVrHjfpl=G4e$}XHkK{w%%&F*Jxn{QB9;>PD zP7r%^@Esl+eTqCm?2yU&25x)4dIems)c4a=1*8&nv_m&i;Ejb$5@{9+8$m78!1RYu z-*gS@vqieJ3Dwo?qM{6_YMwQ)AS}hL+~Kz+%_$2}<{g}|Wh!kXb4%dGy-OMG#uaPX zOekcUa;Ipop^~KZBNR_` zKm!KxQ(2$$nv~{K3oTZ)3*$6D#2H1sRWUitnycN4D{s_1anu}$Oa)B9BFB41k8zJu zjrBX_J=*hr;V=60PVL^1i7*z}q~s7x@_F3deCGi$h?L@2;A?)*Kq$E+;*ZnKV-MB= zDPJnSit6TUb_$;4)pKt+V^>#KCf3rLWB3}3{9D@*hdJK2QF;vE*49ff5P>v_q-*wn zr+(1Z*FT~5!82|$Vw}7No-hAgB^&blOz-ak>KD@ z2*q(`zq*Te-D;1&f33lY=*z9W*GHPBQ2u=rv+oT|ba`crOWU{capj*iHI!aCK)@PY zTU$$V@)+aeD!?xo6rVXY|0ps7|3jg~noFMWX6w@Y3#wOkY*Q0Au$F}Bq6f-D%HBkn zZB{us?Y?2Iko)Elt|$EgzN2* zmbEfwP;6yq=-eezZ_{==p*{pgYknfIk-i()7B4#$)=2>gG0U#AM`$h?sCU=?jNd#T zW=rNojvsIP=7JY}Ox5AIGzbWhsS27!E{%oyY?~ZD#Wn*4QqEyuWaWDb`btJ1v2b-M z&D18-i!a^=%V0!E&>XbKYcflRo2I~5*i!u=1(L|AR9}u83*oUfq|u)2(XV?5(NvX| z`ZQvIKE)8&1;9L1R!ZO?9^J?WEZEM<5Xu#9FvOfXKoE!0iP-eT+Vo4$ja0cZlo){6 ztNRsNuWh%5*>A!jMGg_ynn$oA#fp)W3Sv3m8pcGxrTK=RDb3f6l}vaaVvTI94L07| zAA2v?zV1wsx0YjYgrwDwH-d+EoqzuPnXk%#MX%wc%maf-%y9h+`$$cBqOB1mX=eaF!N?^$WOAV6AX{8%b%A~Nk znOVpL6cKY7bQ#qL9%JDcM5;^#K!IYTx3RLKi?S?JG>s*}xJiaspc>^cf`vZADWcxW z7EdLL)q6R+!$2+@d7R;7htX^X3!8ukVJuqof={DGiQ;!lmMIqR;v1D)1KM*;^qt5f zRkg*K2;LA82IKUGycyttBW?w@ptnQHQ*lFBc6N5;=Q(JD(xOUogJ}Q5M{q$p)Z(CB z#0jRLD(^kDix-W^oT`A4N#$YEXz%;e+>nJ3n2qvm%E@bOJ-uV=H_I6Gh1fA$eDSLq z?-if)u|v%{qCb48`Bw5*CCy@NeB9k{6a1|vlX6B{yn*7>{>ys&sAc2GUzd^n>;D2) zJCnPwgRd|Y)&zMs`zk|XLxhfm8sc;@5-k}g6HD!G=R{#K*N+Z&X9?R-$1>xd1yF7qxdi=;h;`VBv|psT??)`W5Mg7b^5|p zeKr(nwenAg`K)~*)MB$--=Tl8dO~baGQo0VE+OZECF;RUF^TkOqvkG0yvzu=K2z{+ zi6bEy_#o1fbcGT^qIT1IzKaZ5y!m*+p;S3~pho+YBjA1zX>MkQ00d~(TFI!NdWhrB zYg12A5DTyw@o+GYU;~Rr2p7m~^Zlhchy3~_mSBTR4~8pmiiX5l@(3m~r|@ z-^6wjzcH{G`I?be?ZhhNjfwF~3qp4#wvce+casDV2#w*x&iLx=F`DiBI54%--azNJ z`53ephHj7bT3`FlX)}L70-weMF(NR7G0}_-MDl$C9YRr+7{!T!jK+%V1Ek>~lL!|qj-i>oru9+4A9R!nW@cu)ZSn{0H5!G)T))Y< zXc<_!>7Qsjs{V`6KYx;Yy0;PxMrxwu|T)HyKTP) zX6&)9=Y~G#4BUo0FxYjVK~;^pNHqU)Y&B+;Rdt1BFzC2Mr{3kW~uAo8Td` zFd^)Ay79j*s#>Yd^GnTfx3}&;p^j@qm zZ^LLbEQm80v^$ku?||wd>}JRDZ^H>vZ;~ZoX$D`Zh2#i}6O}S`KyImJrR(BKFpJg+ z8=wj6r_nBrD|HZ?b^CR$?)wRG#&D ziEqz5C{};3@M&Gj>J&0)`VlzVmz5Y&eoavR%TI&;jo&1?6rw_e86b|hN(?55*YDQh zXuhUQY6_iop$rlYyT5@ro9Gf6`fPLMjyj6f@LXJY=8DX<>7@0|>tx9-3%g2ZG7+MQWj}BcNoKk z(Q?X(3*PEqKr&87#s|gCn_zqH)HUjsnfY%%-@?$$-Ex?-Br%u8rb_6L+?@qNUIK>qjf= zv}RYJ1a(z;5e)N!D9ElP6-?1EfjVXMA@4e4Gh(l)q|JCcDEzqLVLQDWhw9}aRFXgN zE6tmD3~zU@^dFP>18s1`M3awmf&*auxG9Wq_*)yscOB1IQ8W^>TcieT>1DKEPmyUW zvGAHID*=S##;MMnYApl0SO_zev<9w98ev_&u(tkNArtUlpcZx0H?7mMpNdSdLw-uq zxv=^pw5}UE(yvJQqq@4)Mu1< zE&ufw3l#VyVBc3AH9u!O1If|@=ZVk9A!XDYa`SAT zKM#<0P-s!%(Zk{0%azJzHG~Jt{0*oxd9L`i4Gg4tvZVop2^1SynI8yafxG*)CTN2x zwORMQ_?`SY@5cuK14hOSk2usAg?&1DOE19a=mKMqNT#>Wk|DA*WstBGysx@mJa%8< z0rq?->X*--RoT)HCo({w!!PG(q>bc+MO+!U($1T?3jjz0LIS~%|6+P5pR`=zZ^BGHIETs!ig>?%%QmBL_Mmk$tyIE zRA1h#gV{neyTEd37CjI*nCI^Aqd(W)K#8u-kxn0Ni7dyOD0Pt_`tlGATee>v9*QNh zImYtN1+eQ(CTJ#;i_-VRcWVjE7cVRIZTIHXQ_OLpu1jlJ@MX1j+u-~K%=1A|c(MV<^QmNJp^O=UkA6`rO7Am3?De4uC=Rim=qwx0S+ZB4)ic4wb9A^4(UeJmxyN zKJWOpQprb^aMTEBQ2WKQ6BSBku9kmr-La6T*jNEv3{WjvN5JS$DSu*Og#?6cI_?mw zff(_kqhoon6e9pi=R>>%Wl#f`Hfu(ngXbh1&33POH4;?{f>CH(P`a2=S4YxEedW;Xrx9(1rv9_Xpe@=|7x2oE?4n z&Sm*X+~}22SDC0aFbJqBqrbDG^qC-NBu{4$a-d-4yHH8zfO9_G|3Kvd-T2o1{(H3) z@%u(nAcvBSBv;t?u6KW_Hp@pJnX`p7X2^7LoHUwY1DJN^^qv8!f*YXGS<<7pj4uhobMDV zwKHm-Tq+nlM0?h{8;_6|>V-y+hxVjfOfN|Y1=cr)=LQ-Po299j5@ljt8)}5 zycZ2R^p3?qSu%7(69+xgB#UA2E2f^hW7Ex5^e$?o_eDV1!~<|}z36}HQ2FhX6|~D| z-l(&(QBnC-F<*m)5TN!X1er%%i8>7%0#3j53fQ@EHq#9A{&i_Hvlj$KSv&%yk=$4g zR%|q$KwXtNmQP~>UNNPVjLjzu8RZCb6XdCeSR{c}UgW-3kfj6n;I1?C#x`HgKx{C} zaD^uNkg0RNl|c6R%<@qoQ*$w{Jmc`nN*2+_j^3*)^sRO$0~85*__Q}a5`*f@`t~q0 zOy00S`@wEu-nc9fvuhd0$%hnZ>=sfV{$O|~YL0~?h4@-ArbUR(?=4cPh*aW;U?77l zg8RDdc8tAMsjByMi@?e zvJjGuqBwpB7L7pEw5;HW62jF#a)yEV4=dKMb{wEkFTaIdkHv7_&Y@eMIRllky>>Q< z(z9_M6cmVwQ`d~%2Uk5F$s*VIReK%ZniT%N)`gzX5OY<`fnET+mG?+q@YCJi+c34* zWFgBZm-j&W`{51tBi|0G=*4tVXow#aAy)_zq9gsRu2z1Vi9k7;rce?*>NGcf9{@gN z+Wm}pNWpLpV}jHoujbBhS4^y+K*FON{<{x^$kgrDo>pno|0VA1wu)`{h8aMIb7_ zh8I>-$qX9keZ1Z;s~ig2$~WgbJMa}HF6kS?Z8w{lhNtmJ81Cvx%3pUT{|^>7sJ71d z_Nh$xVp#Hx(Gj3a{>YRra6+=H|K|3D2mqg*#zwQ&>`@coF_Z3Oo!EwwA_beGS0lil z6P{y_nf%+y7H2ZQBO9(4GR3&O+eSqm2D*L}()!^U+buuHQ(?k6o9H9hpRxUS^YFF3 zhWB-?K?#`S4@1Yo*yF`S)E9=&LbNh!skTn~L@fX|$jofr?B09-GnDzr#y}Mtp2O+L z5~)6dHB|w>HZMh-+58S+`sP>4Kk@oSoGhEz9Y-{Y9+EmEj+4~Stm)9Xv$SuBZrRMWh;o5=x1=E0*fm$G3Z@AyC@ zc#DGS>;Sc$NFV(bd05BNtA=c>wdR;x<95cjt^4^w1kqp+y=nIr>w>hXKj19oUmrNX z@smMW>KLY^Y{gm!Y!IhN& z%U}>^UTX8*ZqvqAmY5xtgp$B~MGa?gxni?lT(e+6Aw`r3)3Q8yH9-V7ND z8V#=6C0F5UP_aS@Jhb6}1#hNM=`46|;U3;*m98iwJv|)|Z|;TSr7mo3Z2=}1{@s&L z*C(sOZ|JhPPv5t|=1lTJ?K_5yUBQ9cL;+lXU+_Fk2AS*pRY71uo)e zxReECA4?;SpQbA?7BA%&?4KJsy>5#XBHkbj!-%-TFgxA0ZsCZq_=zaAj>Zx0C&W&* zWZbg*)Doe;8kL|171)ph49es}`}p{{@GyUhTgbhL==04iUz%L62YGS&48YvSsE3+l znE5&|+A|?|k$6XuQgk6N{t2=yMn! zV(#Spa2QW zpBDw#z|zEX_N*Bk_|i$GBLH*T@p%AzfF*bU-JrZhlokk`dvtIJ%`}c#3*KFFqFAM4 z7QOmq4}A?>WwhwQI>YCOx@;}sXtVvnBr$1QU*34(|FLDeLa5JYC^X?^KH+Q<$m2!K zh5!b&WP^z%41`;4Xvi>JYI)jJpf@$sP1{R6{zk-kBP08Q`mhGBtxd7tPSJaBD zV=Kwqpkn7J70TzkFq>tr!irGW7lhPHOByFpF+aS(z$-7AX&CmFAQ{&g;2`~lvAC3r zLe}KhRO&>#pLM8973se+E-J`tZn(VZj&XW$Y&l}W<$ELxCkg*T5~AJyInF+ zEV9$=Xg`rn(|KR11C228(Wz$pKQ3)))8Xc&?kzb@_N%`l7BLRpvKAJxukt?$91$aa z-}=WiPxldEvHF{Z0$rdpHh*j~Bko-xrQ8k*d-_Y~6?=V2q7^U_rcAvXcg)_VH^WGf z2GnrxumRk#Ms3WW4DCStX#I%0k{r*GuUt7ufi;$*$x+J~@lgBK8rKR{q7D6^3 z4>N}wb~hnbhT}PMC#ff)^jm`ETtZBpDDaIX;1C8)Idf;Vg+$cFX)lv92r}X#JjnpKuB|N^0Dsc0vmqX#)j&uC3QXFyyJkV1G`$TnW6ztLt1Avo ztrAf^BO_Vn)FXbdjW$p}TT-GDNEfujHEave-n{S6H_w3n1tdFxVe8~|p2=&9BrjNG zBbhUHp?1$9$Pyk=HfqgTDQ_-o1M#DQbmJlJcM~p?1LcH7)>xSX7H9}YI4;&DP`4wB zBTmZpV&H}i!1GPO%K76lXXi{vm5C#eXRZ6|mFs@)6BFVVMMXKo#j7wI*7UqR|9>w4 z7s!gZ_|w;WtZL6yfNi`&sXSl?8HCqV-54rMMp|UnvBX-UYNtsu5!}rkc5bbkF@eBA zX4$G_TIILQa}gm|x2L&ZfJzDh+R)d~sj^p{Ry+8WD`nJ8*)_RA6=hmgIRv3MxRP0w zj9X66VoVB2s3`!qOr-}7gbz=w613kALJUTMG?-BT&1ckMl0Qbxk?{`Kg^)SV99EX=pRMOEWBoF}}SnLVTZsYSS=Kmyip7`hHelJE^c(x#@@%lH}ROt zRYjjuoSItS81Qx&Vh(^avfmciC`(xtmM;*DF><0FAp(M22hQU0ZQ2lvwt}%fQH||@ zJIkOM?c5Wgo#K$`S6oFX(Z%3BRWGB+t@pnL$7g{p7h_^9KfZ7O3r$lHI(uL!AHQd6 z>Y4J^SJBI}hQ0mf&=K7`VyUP`P&|8B!EkLj#f1q_r4)rV1!72^QrhGRkcxES z(cO@7WC{nid3fZ`fZ>UL#DbaS-u8Eg|pnZ4uw& z{B_M6+kQ}MI~!+RB%7KeCB-DUUBLo&ebWk7_od3_z?YXxwSQaDK=STdWlCTl+rGj0 z?6jEEvU`@ED@{)u6pS%zEm3o}b-0$A3z?vb-JPq@;PbvBNXB5Ko*3)nVh!^~UY+3q z4MKyPv0y(rUgeP2%x;YawDlx|10#|mpt5jRYvxG+}%?>_LWYpx=?_OWvl0u zLwDo>_+rq*bwf&kJP0VGa>-KXyh~LocEbRf)q5@UmLdTINOl%{OeD#q-n9l?nYPNq zX1Ri%ScOb8ujgO#=rv+jQmgQ+u2%n0tjdm~ z=oOORIg0On9(<5Ph8OdfL5((Ak>||X?XlAjt@pXttxo$kbs&UUuFG}VykVH=%{#6R zsamT~d4mR?8(6CiTYMdb9YJz0`Me#9d(B1)U`;M=q}wN~qu)GVwa~P@F^pPYj~|xG zC?)<5zxc#E+G#nPRmIc>UONx&(w=qKMNs(;=?oT{%#pe4v)$Y|O%|u%_(^6)5lah+ zV9?;bAx6F)r9ZkwZU}*sPd*TOaJV??bnUK>V?T4X=Zi;!@N8)-&%H&P&rvof%!{P@ zw?&)VrrF!E@ff&0-gChK)*o>kK#UFpKWP#Cnvq zTJn-=;Aora)B>ECKsqXnNhLx+P#5!4-3_h>nJ}Atw-c$2YrZ9*X#L38+(AQ@h&dJ{c`Y0 zOQ=5JZRX9#e-Fa@iH1K0P(-f8zHp!f4ygx4Fh5rcM~DS!B<j(B51WuL-5$96=i0**R_RXFYaIdI zF8z&uC57T_e=7E$VRW%JJtv9B?Q-;c9;r_Or9=4l+$K7tb{a$TANVg!h=7X?xJ-Xl z`M0qeNFfRvUhH*#vtZG=APBZD|2m0eIQy$$iAg240OZt~b#DT>-S~<6vN5u`+L+yJ zuOYZ%xDu+i9W_-3LU}jfB@_=xh7EbSfB0(57E#^qgEl{OWhj(9l?vVWQy)I5g%n#- zKx#AfkU^5SGZVM=BZ6;F>>O#+q1&FXThB~}WVuxu6`i5j0sm|>qOVk&&U*B6vA1Q< zx(B`(M8ZWBv6|AytntF@pr#iu-y;8t_|{HqV&#j!I>XTI^!nv8_dcN1sv4GGXNR)s zf5J@Z+u2e8g8L!V7Uq;8%QqIf+y8kZ9m~LVp8!7(cQxAI`Q((FPnlssT6pplq&`6+lbo)5r~Q zeOJ?Z3-F5uWnpoo#d`r^pK)4*chq^$#)g0@o(3=#-5xLAD@T0z@Zmoh{f zh~E1G%`LwldLu<*u>*GsYDiGiEb6{1Y)LUh|M4St(F&)ZuTx9T=f2;t(@mSb-=Dm; z%8%^tu=i(yp6M|SgW(_zbxO5O6CBxK%(q#eLs!ZrY&8oiwe){i?;5xW0)jnEE57i0;ko7E}eqx&C|M3=XbfkEdYSp#>UUMXJ< z`8@Bu0Rfgq1fJ)QY|T%il3ln%kKr$a9W^b^AC=#h)`)4esMTswJEmVQQng}J!R8j* zDFa{PSvLN;-tWwff*$JN(lGkm4SI;a40uu*KzMte5!pm8S(L7~xUFc6A4$=@g-^I7 zHY2rz?6hYN-wDA^-i-~@b@$eymoOB3UYBU|!@Pf9e|~uIH;ORH0OoS>gW$vI=Hmyy zI}LW3j22u%xCwT9CIyP7tdRNnO#gMs+F{}*6GE@ntj@g&bY%YMRBB)@E(eP#{p>}ytQq8K}ad3PYG;#t7PCttegN>c}3XV z!h89AZZvq_d5vH&`p?QRkT>8Zt`_j;eUvh5jFKuu4fool7>}?a<;(rOCCwf{^L3uN z`{r-tWgEL6#;PC+zF6168b}`@`SAEUhoKe(v`Ve0}S; zyUl2_`b>94okqA%BSjnFcJ|nkqKq*B_Dv%a!l#~eR@oXbgyk8^8Y~ZcQaxh5{9_jh zi|l!(CtnP=(d{_@c1%l-B|h&aRY-^kc_+DJe1QDv2j4XJ6&EP9vLDc|7Byi3n#V;v z-)SmO@_7a86u18T3zfNCwoA(zUsJ*bY=m<~hH3-^0NeNTryHLgUP__K+G?>>$baLR z!N5UIFl!E$r2P!JJ=!bH`}*Z8uvK|gJAIJOABwOGr>#B6VZ*%tP&cmj^7{Yz0nD#_ z6lWt2YC&l5u0Wj>7JR)vftXKi^g-Dbv<*E@QT)p2d z`7QiCn&oSemA}dE*te)kKLn>NCIYryqn_KI-saO>GLY8%v>hp!l`LKbP|dfW_82B| zI*N`z3Qf+A#1^jv8z3ZyP6!c)*U)Qk(84d>*&d~8StsoH;`+fZW;)<8 zNgB7Tm=UE+(10j&L_Apz{udNWqe0lA72piC@)Zhb@w9glTM@IP$?>pz=kYq#*^1uF zN?vPF;AQM92m>;kp~6NB&5PcW_FRj= z_IptDVqWx>LxcOFD^IhN;vI!Pv=Ze|>w8<4+Xi^NKAL2bDoKiKtVgW021{(?ZCpa~ z&dM_zSwdfT7XwMz1D6dljO5JNk|bCHKuK~S8qvR4i>_^r_V}gKgGxVxwf(R-Ih}zz z;I)-6q4s6h^P(Qs9q&{0in^8ZK{2;qcq|liZt{NBS_R~xzxZY{k~#+d&#ArN0bL;W zqC3nI<5wxxz%S!fEPaSC6`N52;i1z0k7Eba(yG}*u6NP{;BwSoL?-x>nQC?m+{(5U zyMP|IOYynj^x*9fAZG$Lmo%n;A6;_;GF+r3MaA;`VW59Dc?Qmnsdy{SK;(>ZPNb>$ z5T_6=Vgqm-u~}w%b#@35H4<93<@3$;jjjlJt>*!Lua{5?NUpv}yiox3I8k4_|KC5n zz4#I^XNp)x0xkL7%yz(mO7y3wF)^G%oG?_t-m6Uruwy+}JzeNVk1J+g7gfhom{r#j zZ+-~0A&N&mxLb6;!|bXp=Vl6X71rvo;4$W^n$kqOJ!05+iBBjfb+e=~yiZ~86K3xT zdfc_4$5V_NXQLM21l&x3Qs^skx*=bV-G!4WPLGE)iLu2;7!*p?2E!sZ%INdY^CoWd zE7=u7T-LB5EjWK#<9yjle_mreVDXqF+YB?YZuNWosu*{46zF1>0@bBNh z-n?LHnv;EQOG`_cD;?@=3>Q|RNvf}7R=xyAZ0Uf1{O;RM8D;~EWHNo_M_N{k;&Hk$hx#eLt1hLAw!N)*bQLZ!fh^?$bU z+nF^w<%{3d{+Dg!jgUM_fCo{}P$q|rjeV3F#`N>zNYt`xLp(t8+Tq#PV# z6oieb6ytjx_xyW5#$KE#M-DkzgCEQ^!=e4?R2;7Y>1lV8#A;3Sj4Mz@1tG8tPTLtX z5DwH2vV3A=gyB71H$V;Bb1-IKu0xl$k~TjaYEutbobh>*bw8fQ`pX+sRB;{GcXh>? zUE7dntHiBEq?T{%q){9lCqHhILjc46G)r(HlPc_H{+x){l|V&vzwhzPJb(16Aw7u( zL2qQZY|%%LiQwR1u7Z24AK2yGfc6B1Lg`LZfBfnLMeo?H7QVkMEzSSD8o{FIHEFcA z=zjTH@ntjImA#W9+6?khFndsmB{+&$HX|YAZ~vCH8&=ldos1KFP-x;`+2sPTwy6Ef z-`Z-)S)Y5KJb~29!Udf36eijI_;dfFYD<2=0?9@COZoKbFZAKM=WwkR47$jBdA3bb zV5Lpc?mf}R+ZiJdlLHl~4pMFZp0>SEUl0D%V@5|nh=Y!?C9z>S47T&T7VNS;yoT&V zLCg%zGN*_QG?_hK&HsY{Zq4qoS_BSSudVZY`&*rx2VwpwwLuir;aPk;JMN1R%q zB$5ZYx^lsA#;3aS62elR1zhHC29V#se+PqH$5vK0N<4PbT+tSgomIm-RsKb-%3=2fr8`(L zUGR9NaAY@5^jTqSVw{dpG=hny)d{fx=bR)7r+`#);!lu;4qrS`6JV)=I2-E_f@XpB zgYIS8)q3FlaFJAd(=@MMaL(68QAA?zoUVWmX+W57Jj4{FO88YiqFYm z7J0niJn&5g7RDA5rAcm?|MJfsnS;}v3eJE7+Yqqw}|2%CR zUqurj_Cck>LbB7J>)vZ!`U>C0Hwo@7aAXJB(sc1f#?5?M96%EJ_FwRJcKJ*1Wq8AD zZSKnR^c_|Q0y-WL(olhZlUw|KzWCDQck=y!5w3#RjybWAK5s_(^TAfm5R$m_~gg) z9__ib%Hv4C#(ZO6dyT6R-YLL|TzsB`3g3FzVF4M_M3m#);z9y-!dXsHA78mTUZyBQ zS8I6lxwh6+vGTTS?ax0JFNr;UR2Il|lzVM?>Pp8G14mj#-_&vLXiP)gz5fN&8ovnv z&OwkrA${E+WiS(Q@Zg8+UO<-cl8j7L{F_U^%d`0gP`kYPcjihhl0eurd!O?YYy-bq zjBm`h1jFNA$p5@idCPj0L8%dKK(&AuAcX{YYU~Re=AV2qBl%iuVwEi4yk2hhAc;O^ zeW4TJL@|u=(S=hVh!mCa59<^;akJ+l4X2lPYZQ|SZvM~|ecsL#!qiiKp2%F$%l~w#r%{+s_#>L7s&`YAMH&=1U2f7BzGmYlt^AA3zW4nF%nH2 z2WZfN2*NUdIX=er*c@5&kg1ZPf4#!$ekgHt7e1LF5~X6~uo)X0lOQnLqEic#fVZcz zWprKHJo`{>quaAxa?1{s3r7EDJnuW#b}`UMs~b*g0%03!9}4_TFOTLY+^Zu1UZ-sh zfR4W5HL~58x1O}L6aO7!lhg!+eRaW~+dQlUk{3Kfy8ams1J%|p#(f|{_=jxYjSskk z&gRz=gMq$6RD((psN|#NdQEDQMQYMrhC_KTkD|S(Zn*UORu{33K1gTYk4Qg%_)zZQ z#bzjyM-t~qW+a?h8X%MUH3okBt@#mez8?OZ6o5O?agoPU4_|M`E)m?gJCZm1U`!mr!f*ZFw986E|Amb012F%sx4E zEA_q;HH0q~OeM)gjs!ttJ$hcSo>#07{Z25p=g=aiC2_cdEb{1?Q`q5g;fH#7bD5UL zy~4VcQz}@N>>DoWzlym|R;lsDBY)20A{s{7Kbx)#X?oeK?V|MTxe>ytL2TiT;t zUt_EfKZ1pEQ}h=T1Ov^0QyzYN;(%>l?d$Yy zMzxfPFTUu#mBd|zW+k2OJO7oiU*qJ5Abf42OuG~qApw?9n;L_;vhOz6JP%lx<%tJ;>V9a*{BOflK1J~kQz z*SYn`2uKdXjRfMw)!H40`_uqN;wAp*Gu@`1N-dx5^@`HddafuE@Q;`;9s%kMQ)o)5 zaE@10e^$;Apm9aJT_N1KWXwC$nS3e0s6xHw>90zwmoAY;YUX!Ofh8E0Mq= zsKr6-njAfbvwlD8PBtzS%?*g~7;XAkK>AJNNA3eWfB&@ugrALv6@B-mB90J``@#?| z-%*W;VaA<-mNA-9ie<2vUx_L7ubQg&S9=RLzy>f&eTnVw`R}}ZeUn8l^ z`?@Jp&9E&=^$hP|cZ$BNM5U@BI4 zGr#QKS(9KSd)pEgV>O*whyyIg%h7Y5_{;J!E952C=)u{%v4w`GBPi1gFN6;W^pDx; zPPWI}OuqAA68HOnx~3-S^%=QrvN}be=`)jb{)cEFWl&kZk+ybFWhEFCYI%!#ND}cz zC#^%~akm%n2N4nyVhJmxxgjX6B0~Rz2r!_z6zF*Z9PqPF#;U-m&6oI^%$b+lkOGZk z9GPQs9>v9rjfS-eey#*u6wY=SX*N>}mFGq$xgp3wL_cf9aHPTzINNc{&()KQLOK?r znx+#A=9(`D@sA%OVN^EWrzwoIBSzCx7)eoLqd$m$x|NKGv1XzUfVzT9b;EVj^XHgb z-45|K9?vE{t8);yEFsYQFQk>PD$k zTVX|UCYMCXb(8e53C1#Ceml^Vvxu@Adtpr&Vks`fk?!fR1;zHq&x7r>=*8>#1|T~= z9a72K@kAd0*oL-o%iE}L(&ydx^~bAS&hPxrJA)&W?l?FNfG?{w;|;qOmF577Xzl#h zw*b|L#{(ze81fxOeiBB1JhAQrl{fkqAT!$RiLj;wMrX(ET<6ioBWqqNBU?!f&Z z-*lYCh*h=NOmn{0>$?G4PTQu2D$?%l_m33u7GU5~vOs6p1q@h;+wel(eJ)G;0(Gd& zCDT`~F|KmK?0NR3Iu|5=*Z3W70L_@ck2eAB@%gsnlRcY$R-Ds_l6#;;j&8bIm3-^X z*gLjytDZdO{XXysx_J(Pn%>ty9cbMzxum_pZMoDYov zF>P^;gYNu*?dXfY<0?P6a~(B7-wP`hE2c=eTS%xlHr1tb3kgL;13Z^SbTZL@?RZxY zY&3iBU0TSvV)8x%Hn2}mTqto)jms=9ZEI7r8$dG%&|DWrFAwww`fJqzmS*`9bvnm! zVnr2U{DUtZdw9MI?xaOvH$a?YtG16sEK#h zSL_LW#ukM_v#bT)tf^aM&88S#Wr=F$ZQ;Pjdsg(9sNNlOhMDv!&P)P{?S;EeLJWg^ zi(S)I20Oj7r?B=0OhD22ZHX3mQG+e1rN_(W=r;g$db-JSTs*E?9-wW-+2m+*&^O2W zHmquyOnq!r%hasTrZV1@Jg(XEcngqsvoU%S1hOCktWZ0iScw9sa=A?6p8$jR$A!PV z5?vgpoVJNb=9GX}AzV;=%GmO|6GEjO;KOkQpz_aVA##YgDF0i&K?OT!0e^DlUYPu(bhyAE<1)3|~LvDe7-oouF;7c2G(Y?B(09VT`sPHp3R&|sqM)#1LABN%D7&@;{m-fZ zAhvYX&hBkeSgY>m;DOAkR^POli{)RyyV~IFY=aa-i7_5*3sckg50r*P+F{=V^_{>$uktGQWrVgK6={p)SIxx~E$V4@eu z84ky|KV4|~e=h)0U30U{svXcL%4XQf*Kkb1kjshNUTVXt;fflS)Ndjm>&JAToy8C$ zuv1OG)`YBa54%Lkjat%|J1WqT-d2cKef#L&dzxIj;>a#%nY1Nu?Mrkngi;r&w zJN>>;AzIQx{kj{tj_ei%Ru|2uSRuc(+!pNFv#&uBa9HazWS^0V+vmIv+jv7wzV~$V z17^41ZdiPhQdPPzrP{2P;%Kbb9?vfPpz=`F^ZdJeBX1Y7-v_2qnWy}jV|H&CN=8(O zTMnzdf~MyU0Roya)OKRXyYo*xlF*&kIY`MxB)(3xAg*(=&!gVJR%hl*PnGrNyK7~? z2eZ6$)p^-4@XNL13lJ1Eq9%P1EFVTd%1xnBm=IM?>=35vvUjEwj12F0n(VXh7E;9C`0bNv_W#ks`Oi=U~N&Zb^smHzVzR(vSHzo(Z^1}tFq z^MGkPk}wMBKhMm}ylk&-Dp0Qw!$H(eo2M;YW{TmV+{&9446zJiHw+ zUxXkgA00f2KYb(Q0h7G$p%}l)=fC3p$zk=|=|;Jj<0NCPeJpHLqFgBZbaS}rqIxHsV@j|)c&7*1QXmGpn6@ly8orW-t`3+Zht-{G@B5PC3+$>LMUsI z_H#;$>iTkj$Ll_00k>YG=6$yx(xo;iqHX=UbK1IiNC@S0x`8T3FdhlAQoX#GYOnd1 zY-xF8@EO~Wf(oWt7Cc`2Qnk1X!(pg7E-Mnp_SYSa~q@_U` zM7kTLOS&bbLAtvU1O$YY76j?erBgzYSUM%7VWkn?d4BIX`|s}Aotf{dyk_#4}pV~z`+y!t916HRcI&G_eBh`P2|I=QF7kboD zG0H;u?s-yPdLCA)G7*C?p(&#c2j}acZO7|`SQySZXSXG$Lt%$=W(&(rbffU8Fe~}FCtqrvgVw(6EV68Hb}5W& zNJ*Xk)&U)uN~Xv79#_|Ser#5!!Yw8E(SQCufAL?S%2(Z~Kjr=G9^Ati_?xEdO?oc$ zDE9X?)-NA+H@UpO2GA47T^+rx?9(qj${#RlJZdiWyYydOm5P0q=b+YTr%&8+TeS$9 z4}T?RN=sRNWrZhH8k?=9rN=@$Dnf0JRvc%3$Oc}f9B+nnUe-V5dRN`Cqu_g}anJgn zdG!a&zdyb&a>_2AEA4b!GY$nHJgwSTF zBzr@{HVy6xNigv8#)>QXxFyp1LIQTM3Z{)`kZ3<-g+9~Rp+mx4-Ib8T6L_)M5*Tor z3e!=cn)~UgtCMFm4t`uoHm4bR0c;z!hHvSgHcc6)GRCiz#MuWV!;zw%n^swrUSW*Z zxdGc09Y_ty1`+Xq2^#0)JcQzq_!=VPYwiyFq}JR5nw%lHOA$^#;*p# z?)i?S*c-z}v<+}P^{+79{bft|=GW+-BUE?|@#I#u2CD>-Hiiv~E9y(|SUYEDJP=IR zWd}3~%3{)l0SQJYJ~E%BvSLfhF<^my%fC>E%J6Ll80iGWWNvguPGef5wJxRuP;ZW6 zHHOX^&M)}g35hH(jfQ zVj)Hi=?sZ1nWm~y?PKI04R!WI?1|#5s>D>y6kG{-ylP7_IkNBgcX^K~)bx$3x~~rR zsO=5us_z${aY9Tw+bG6yVl zKY1TFbg|;JQ$e-$PFCLxMy+DDsBG8qT(k#@B(Gja5ajDQjvvVXZ|CfwC>y}tCLSV6 z_`ygV$2gWSJ^SRbY9sAnnbT)rYT?B#+PAy6jo=&wAuTS)7i>f-7SS@>3yM{*^syS~iJ89`ClkgQn5MSzplMgk$a zMC}G%QES5z`?3ftC(IYPtXd*T=m;;%bGKOZj?QyaG@sG}>`gwi?<*Qo0V`X^bMs|u zJu#heJQ9E5Nr)SLSHCAowC0iI?|W;VKiM9?XYRR3!Zk%$@V_P>#}v*$AC0nDB>f8% zLOI3PE4@h#aVAF;U@le(?Az-jPqJwx!rnqq{2#Zy5&J7~YFjE6tk+#`{uoJ4On>a8 zfAa8eD~Q$1(K*KW<>2Wf*FX&0osJRHjPc&R&1f>BtI(F8w^Q!UHTV`{f|Upax>c9# zI^W8D`*Gj7;6L;}Uf)II2a$$*h(c&FF4H|Cv?*K6;e#2uL^MylxwTK%#KEZho~=HL8+% zu^ECEH>YZdY{^<}1}e8ehk?x6aeRcFI-9!(x|R z?a);P=6g_^;Cp;4xq3=j?KhL-dp&y8e^7xq`fAVKYuPBLLMX4M1qW(NsJ);iWj4

Al2O@ZK~VxL$x4$WC6o@4h7xwNINX?*z1%i$n*Yx3_xip!g~ufZgqDUNB`i9oWYj zr*(j@PY!SJy=7Y^TRfWDl#zGoK;c)5ql?bPCW(*laep9xdIdE|oO74%CK!~Rt@CC} zSkEnr3GfR%$u?2~rsq#P>vJsBLy9_%(ppWmj6lrx!~5^v)O3}JZgzMh)p7X#!=$hY@;o4rA`7-=a+n*D73|-id zo##RbN*RSBEl?^NWfI6vHKd3&pZC__+Bz))h|$q-Did*BZk2yH-QB~XX}||#{h<3J zk;_VsKg#;Qs%8xX4jYB$eBW=rPs1emaKidZhooE6ld7EP0Pcuq370B; zh-L}zl>I30Pqt#-J9O;GCUIHJmuWwl%<8LRKc81^yth#)KXySLjEM%^7$LOc0ppikP=!YkG=wdg^JvD=@ z+;dmW4_DagOMZ`Vq6}H<5<#(;_iw{b{N`%PE9Zb(XxWWR@^sRNfrO6^+P!3gy6)Dw z9w3q{l|ESMI#R?NfE{0$zgM!PVnda=a|T4FC#pHH{?)*Bs+Nz&q7?b8#77VPw2U;z zO2dgVQ)s1n95si0rL1x(Fdw9yS!Zl(FQ+XslWvsnyA4&O=G+AXPL%lBHRs^av;SO? z^_C&sKPMnG9S<%Br%a5<4_jqDajA9ky-h_0A`a1<%fwp(ax7`{Kc|&>dU#%sI_})> zT>bp{p&4~k^c>E_+Bca}BD@kOEFvhS2;rTf^95?tW_%XRYc)E7K>ha7&0euNj1BlwTTLc`4`e& zJ>toM+233rKb#=u1jv=jtowMmWk?i0sxbdP^SeVLXa}nEBy}#caw6RCu7iAf;?D!l zO%xu<65D*_V15~or!Z6S2lZePm?D3ol9nZFR8)us-8m1Pggtgu;-^$%wU$k_`KX*w zstb{?B=0Sdo@%{SE{=B%*?A`H{xvZws_?7y+r@-W+5QyfH+z@70;VCk&8z;5_a_&| z7Hx)52|`R}62fhIWt>u0dTN{o@nfZszZ?*}Cj%QD2-Z(|Tx*M~|FDDafBVXrpWk;v zX(X@dagUc{VrP!WVWZ03Frnj&HW4Kr==ZnTdY4P^?4HJ5FVo|_u0`eDUFw_RVQ6l^ zkqEfqB_<{L%a15w=_RBqE~-w+1NFw-JTKGRP$Q`PaZd6m$exjsW{VkBLRRi3cNHhL z-c^b3Y`YkMWa!_&o{Jc^05Z3kJW;l*n1thvcd?n-<>F#?_C3ll@H{U#baCa~)94s1 zx&(&cfNko|%YWwd0kx8Qcrj>KqgY3ZA!n4;x#bS@tjgU2GzA}Q6nEQP)&`5J2Q~7p z#-kBF8xzfINj~r=dKCogH5d}z{NzsU&_!-J1d{xv5m%IFuGl$o=f(RWH{?G4M)p(e zk196e=VKJ&H=A~~Ee78L9wr$XuZAUn1bIU_ISm+<>FgXDFH?b=`q$ZA-n|;7JfYiL zPv}SOFTt05x&ACs^Rk<%z0$vW`<_Wf!UHaQ;+cu?+hHsNp-hf+)*@LxsIc~344Euv zKD)K}Ea^(7rSe_Yg3-Ff+S=#h4|hn=@i6;(1AIW)dt@9VaoWny`S`+3xSI?7wS=a1 zRi~CdbSFwRHgwc(++8DEE*2bN!BtNMJo8Cgoua#OpLxmT=j(dFO!x`qfr=Z2AwjFwc&ttofnc8 zMg06A!FO+-Oh0gSEs2~)^xE=Z{sk^ahJ0*VD+i5SEJRiTMOHt>uNwN@sR(n$dX~$@ zok~W3?kl*Pfl8)&7ET&l*z%18+w~pn^JgdHy%wFdBH#Te`)n@+UAl6k(+B&n2Nj&7 zx!%&o>t4oEZmBf3rxx{} zlRpCkS^nY4(`ce-irSN0pDsVs(YEy){q>X|%P~S7>*U1$B4P(qp)hPnBCDV{dhsdVd>=sDgJ zvUBmI;Iiuxx|lb^9u?wOt3v6nEd-LU%~oX1Bl`tE*Y5(uWO$+~pt9ZPe0}{#Af(-= z9y;IUZpr8{cG0*Oe>|6sS*n9COpRV?mg@W$ru;eufP-F-B^P&{JuwQQl2N%nQ4Rm?qo=#Y9uGI4;RbrOy_uLE@huEfuK9_qSfQ4gz9( zZ{HZmaT#dLTjlHCugD?@MKu}EfhM^T@FPbo#)236Diy39rn2kdvGmwL$u3Ji>q3U} z62V{~T@cE4#7MVyzu+^GsL3gv&#QxG5t&kiYesz|yxS|&alGk_xQ#iP*9alU!l$;d zrg=q2UY9TUDPntr-K0|8LQ0wrjkOq1&JeUBp;Utx5!$HP?0vla9XGG#guSQeJNBOn zZLSd96D67WKu z@p_@bPH_v_2{Uc@?#<%dfm35Txo=*?ewMKyYLk|Zg|f403ZN_UqAi+rA2u(CPajXL z-zH16ZU|{9yWJgD_n98IKGos~d&wWBId}G3k@*#Jn3{W1*yZUesx$;AmX9eWs|!j< z7f-DFT8Wjqr$7$NGLuxRQkM>T;8Ry2{o1RPvOKQb0VSR?w4x?<33<&j%`BLY)6(el zQ(Wx?<#`f1Ymk?>L<-<_I z@BSD}Gw?x{DhlfUAt`?>$%kPCO!@Gp`glM2X|JizJ*xNNQq)WSq#6oj9br5%N;-+A zxlllJs>n~Va6Wx1U$R?eN=ALOwxpkkaE^b;Q@F6orY6c07c)tZ(Wi5>4BE96XfHxx z+ujgpWZN4@(ZAB<>F=;-lrb)Y?p*qa z4Y}Ptb?skUqw6h+(wqw?N|Z(z=9q1a2fOIElI4K&`;~UVH_Y%J=yzr+*P#7zR(R^Vn0?6IkC+MZbV(uj$$+f4ptnad7R#SvpMiSvFS&*|ZQqG)EPTq|h z%IZY%Av`*aPPNy?1x(o%S=*CbI@UiB?oIqqp(}(a&r8Y5D=wg&CJh}MHMv_9V{Efc zRG1|o{Sa@r(9W(Cg#RtR@V%1?i7Wdc0=9+y7vCQGg zrmGg@;7BF1Mr6`XA^Cl%aNFG{I*3?USO9yHS5$OiD(BbYuIXRT$Y6m8F^Dtf0#Q&k zCX9`@k6Z(Vh?SaMM$fbP`TH7o!PiQ>)>d!d3XvXS2+y!XWDS%}CO`GUY^A3nGzIje zNSS9G<-wCx`CHL2jRuNAjan$J$;?n%{f2W8TVE_7I_==erCI?G-!3U`$s%Zmy{ zX_|DSj!ngR{bs1R5UMa~L2ikAv=pTf(8Ix@sTIypuGxsfzZ_aZp{a|G^X#1#W&v@m zwBd;CZj}gfCZB4!Bdhf_hh>@bU&$tHxRRwIDHsYt)#%E?<8gHz=aOz*2x>UGu!|8n z3ZytAT3`2RlVxucnF0Gs86P7VyX;2;38M{rSHq~6riBHaiVd%eL;c=R-{KZPLZPxu zzC_}mjTrOFJ%_qr(Ej>RXGN!#eYCK(lI}R^rN%n`j;EZ3CQVx0>1*AVj!&3N&bF&` z^!RyhyG7^iN1^lUut%~o^yqw!4NM<%B50sot(|U~?VU%@nGK`*?G~1uAV1{07k^h= zO7+b4G#zsNu{XqylI>wcf|B(M7E8La9}KC=GId^mc8G$gpd}}7VfU{DKXa&7k8kPQ zZh*kaqcNxN5g(M&BExaQRfzjvf6yr?6=Z}tV7O?_r6m^Yq7@LA!fr?-jru#bOD8Ku z9!2I5B!4jUXxj{+y6rSFTKq>H0v}oT%tOKqXa;f7y??%Zu#cHp`qH4hhUTw79)N&V=HEVX22fwrJ>HbUv$FwZ{B(s|D+F} zfTA3OSHmit>S!>F{c$bx%U>{q#CCe?`=QveT%trSZ;4QJOAMI3ECJ1fJPatgK-v8``oAv4fkoN~(?o9NCAlk)19B}AI(Gb76FgYH z3yT5Io;hvMrkoL}i4_i}4?CQTcOE!8!XQ`&cWlgVbm0{>dLd-j*{{4_vB-o<8@8=J zzO;8!t#0_ac5^|ViC(I(J^GKRi5Rf-fcAQ+Y&c?Fm(+1BvFae+qFrVY9Nf9N72#cA zJR+W>UhS_M&^X8PmuApmxTd6s?$ zl3b-4mvKbi1*Wf^_ya0U);Y^$%Z~b0wpQkbd8ghz(jQ^OLDtP^-|bGdSJkj@OduHn zvOUe8r=1sp%OJYMo<;_=c~sTa{fQA^>6XKcGok>O+U)>1K2=p!L8B4a8BL#fU8vIm zO$)Sdv_3YOZ92;yyH~{E`uTJ`L`(Xf(1G<~X*ip4^j1j2qJ(C2zZ>mTrQs$djM;0` zjES;G>66>%47T9R4cL9~dn_}5eA(qu{r+?3XmvshL0Bc#LxnE;r>rbPVpMRmsg5a` z_d82mP5+S8>`axGmIiz>rkTzFT?Xo@w*h($980rJwUQP37A&xFFcdRzmuwdG90%?M zqcUBf=K@0b;!$VQOjBCp{ORC>zrCu1LW5CxjfkU-b#S_g`84NeF`J%NaWB}oZKiJk z@;)mig(xvGahm9}^WqBJ*)YS7ZDAD56hO7^|F!2Iu>C09j17;WA3bXu)|_gH7Am(S zSIPDVsc@EO&z?Vj9_A#tFVV2z9I)WrzT@olrgDvPJ?Ed)IY2?~dIe5j_G*828IQ0M1`)04bhUX(UTfKsk`<*)assB79m& z(6?I5)m!2W%K{%<-YwLggHlWamNRH2eAEVS_fkNBWkpUy)5-AbkXnBcX)Ok(2J|## z3u?BXdU0pUv8Mw*5g0=71#Xjoka&IVcRX0~(Ld!@Stx)zv+wusFG7R$lvfzGO||dM z0G);E2m|12?%JfNa4~@o9|*Uz>EGemit}wm9XpmqS0PU$MX1A$wi>}7TcEsBP?xWg HwFv(|S)&oa diff --git a/doc/_static/lstsq_fit.png b/doc/_static/lstsq_fit.png deleted file mode 100644 index bb7f439376d04b2dc3960fa670b58a11d21cb0c1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27183 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 diff --git a/doc/_templates/layout.html b/doc/_templates/layout.html deleted file mode 100644 index 4756526..0000000 --- a/doc/_templates/layout.html +++ /dev/null @@ -1,89 +0,0 @@ -{% extends "!layout.html" %} - -{% block rootrellink %} - {{ toctree() }} -{% endblock %} - - -{% block relbar1 %} - -

-ad -
-{{ super() }} -{% endblock %} - - -{#############################################################################} -{# Sidebar customization #) - -{# put the sidebar before the body #} -{% block sidebar1 %} - -{%- macro sidebar() %} - {%- if not embedded %}{% if not theme_nosidebar|tobool %} -
-
- {%- block sidebarlogo %} - {%- if logo %} - - {%- endif %} - {%- endblock %} - {%- block sidebartoc %} - {%- block sidebarglobaltoc %} -

{{ _('Table of contents') }}

- {{ toctree() }} - {%- endblock %} - {%- endblock %} - {%- block sidebarrel %} - {%- endblock %} - {%- block sidebarsourcelink %} - {%- if show_source and has_source and sourcename %} -

{{ _('This Page') }}

- - {%- endif %} - {%- endblock %} - {%- if customsidebar %} - {% include customsidebar %} - {%- endif %} - {%- if display_toc %} -

{{ _('Section contents') }}

- {{ toc }} - {%- endif %} - {%- block sidebarsearch %} - {%- if pagename != "search" %} - - - {%- endif %} - {%- endblock %} - {%- block copyright %} -

Documentation license

-Creative Commons License - {%- endblock %} -
-
- {%- endif %}{% endif %} -{%- endmacro %} - -{{ sidebar() }}{% endblock %} - - -{% block sidebar2 %}{% endblock %} - diff --git a/doc/index.rst b/doc/index.rst deleted file mode 100644 index f00b67d..0000000 --- a/doc/index.rst +++ /dev/null @@ -1,233 +0,0 @@ -.. meta:: - :description: The ad Python package - :keywords: automatic differentiation, derivative, algorithmic - differentiation, computational differentiation, second-order, - optimization, Python, calculator, library, package - - -========================= -Welcome to the ad package -========================= - -The `ad package`_ is a free, cross-platform python library that -**transparently** handles calculations of first- and second-order -derivatives of nearly any mathematical expression, **regardless of the -base numeric type** (int, float, complex, etc.). - -Calculations of derivatives, can be performed either in an -**interactive session** (as with a calculator), or in **programs** -written in the Python_ programming language. Existing calculation code -can **run with little or no change**. - -.. index:: calculator - -An easy-to-use calculator -========================= - -Calculations involving **differentiation** can be performed -even without knowing anything about the Python_ programming language. -After `installing this package`_ and `invoking the Python interpreter`_, -calculations with **automatic differentation** can be performed -**transparently** (i.e., through the usual syntax for mathematical -formulas): - ->>> from ad import adnumber ->>> from ad.admath import * # sin(), etc. ->>> x = adnumber(1) ->>> print 2*x -ad(2) ->>> sin(2*x) # In a Python shell, "print" is optional -ad(0.9092974268256817) - -So far, there shouldn't be anything unexpected, but first and -second derivatives can now be accessed through **intuitive methods**: - ->>> y = sin(2*x) ->>> y.d(x) # dy/dx at x=1 --0.8322936730942848 ->>> y.d2(x) # d2y/dx2 at x=1 --3.637189707302727 - -Thus, existing calculation code designed for regular numbers can run -with numbers that track derivatives with :ref:`no or little modification -`. - -**Arrays** of numbers that track derivatives are :ref:`transparently -handled ` too. - -Available documentation -======================= - -The :doc:`user_guide` details many of the features of this package. - -Additional information is available through the pydoc_ command, which -gives access to many of the documentation strings included in the code. - -.. index:: installation - -.. _installing this package: - -Installation and download -========================= - -Important note --------------- - -The installation commands below should be **run in a DOS or Unix -command shell** (*not* in a Python shell). - -Under Windows (version 7 and earlier), a command shell can be obtained -by running ``cmd.exe`` (through the Run… menu item from the Start -menu). Under Unix (Linux, Mac OS X,…), a Unix shell is available when -opening a terminal (in Mac OS X, the Terminal program is found in the -Utilities folder, which can be accessed through the Go menu in the -Finder). - -Automatic install or upgrade ----------------------------- - -One of the automatic installation or upgrade procedures below might work -on your system, if you have a Python package installer or use certain -Linux distributions. - -Under Unix, it may be necessary to prefix the commands below with -``sudo``, so that the installation program has **sufficient access -rights to the system**. - -If you have `pip `_, you can try to install -the latest version with - -.. code-block:: sh - - pip install --upgrade ad - -If you have setuptools_, you can try to automatically install or -upgrade this package with - -.. code-block:: sh - - easy_install --upgrade ad - -Manual download and install ---------------------------- - -Alternatively, you can simply download_ the package archive from the -Python Package Index (PyPI) and unpack it. The package can then be -installed by **going into the unpacked directory** -(:file:`ad-...`), and running the provided :file:`setup.py` -program with - -.. code-block:: sh - - python setup.py install - -or, for an installation in the user Python library (no additional access -rights needed): - -.. code-block:: sh - - python setup.py install --user - -or, for an installation in a custom directory :file:`my_directory`: - -.. code-block:: sh - - python setup.py install --install-lib my_directory - -or, if additional access rights are needed (Unix): - -.. code-block:: sh - - sudo python setup.py install - -You can also simply **move** the :file:`ad-py*` directory -that corresponds best to your version of Python to a location that -Python can import from (directory in which scripts using -:mod:`ad` are run, etc.); the chosen -:file:`ad-py*` directory should then be renamed -:file:`ad`. Python 3 users should then run ``2to3 -w .`` -from inside this directory so as to automatically adapt the code to -Python 3. - -Source code ------------ - -The latest, bleeding-edge but working `code -`_ -and `documentation source -`_ are -available `on GitHub `_. -The :mod:`ad` package is written in pure Python and has no -external dependency (the `NumPy`_ package is optional). This makes -:mod:`ad` a **lightweight, portable package**. - - -Future developments -=================== - -Possible future developments include: - -- increased support for `NumPy`_: new linear algebra methods - (eigenvalue and QR decompositions, determinant, etc.), - more convenient matrix creation, etc.; - -- addition of new functions from the :mod:`math` module; - -- arbitrary order differentiation. - -.. index:: support - -Contact -======= - -**Feature requests, bug reports, or feedback are much welcome.** They -can be sent_ to the creator of :mod:`ad`, `Abraham Lee`_. - -How to cite this package -======================== - -If you use this package for a publication (in a journal, on the web, -etc.), please cite it by including as much information as possible -from the following: *ad: a Python package for first- and -second-order automatic differentation*, Abraham D. Lee, -``_. Adding the version number is optional. - -Acknowledgments -=============== - -- `Eric O. LEBIGOT (EOL)`_, author of the `uncertainties`_ package, for providing - code insight and inspiration -- Stephen Marks, professor at Pomona College, for useful feedback concerning - the interface with optimization routines in ``scipy.optimize``. -- Wendell Smith, for updating testing functionality and numerous other useful - function updates -- Jonathan Terhorst, for catching a bug that made derivatives of logarithmic - functions (base != e) give the wrong answers. -- GitHub user ``fhgd`` for catching a mis-calculation in ``admath.atan2`` - -.. index:: license - -License -======= - -This software is released under a **dual license**; one of the -following options can be chosen: - -1. The `Revised BSD License`_ (© 2013, Abraham Lee). -2. Any other license, as long as it is obtained from the creator of - this package. - -.. _Python: http://python.org/ -.. _invoking the Python interpreter: http://docs.python.org/tutorial/interpreter.html -.. _setuptools: http://pypi.python.org/pypi/setuptools -.. _download: http://pypi.python.org/pypi/ad/#downloads -.. _Eric O. LEBIGOT (EOL): http://linkedin.com/pub/eric-lebigot/22/293/277 -.. _Abraham Lee: mailto:tisimst@gmail.com -.. _sent: mailto:tisimst@gmail.com -.. _Revised BSD License: http://opensource.org/licenses/BSD-3-Clause -.. _ad package: http://pypi.python.org/pypi/ad/ -.. _uncertainties: http://pypi.python.org/pypi/uncertainties -.. _pydoc: http://docs.python.org/library/pydoc.html -.. _NumPy: http://numpy.scipy.org/ -.. _scipy.optimize: http://docs.scipy.org/doc/scipy/reference/tutorial/optimize.html -.. _Stephen Marks: http://economics-files.pomona.edu/marks/ diff --git a/doc/index_TOC.rst b/doc/index_TOC.rst deleted file mode 100644 index 1ead697..0000000 --- a/doc/index_TOC.rst +++ /dev/null @@ -1,10 +0,0 @@ -Table of Contents -================= - -.. toctree:: - :maxdepth: 1 - - Overview - user_guide - linalg - diff --git a/doc/linalg.rst b/doc/linalg.rst deleted file mode 100644 index 40b4248..0000000 --- a/doc/linalg.rst +++ /dev/null @@ -1,285 +0,0 @@ -.. index:: linear algebra -.. _linear algebra: - -============== -Linear Algebra -============== - -The :mod:`ad.linalg` submodule was created to overcome the limitations -of performing AD with compiled numerical routines (e.g., LAPACK). The -following algorithms have a translation that are AD-compatible: - -* Decompositions - - - ``chol``: :ref:`Cholesky decomposition ` - - ``lu``: :ref:`LU decomposition ` - - ``qr``: :ref:`QR decomposition ` - -* Solving linear equations and matrix inverse - - - ``solve``: :ref:`General linear system solver ` - - ``lstsq``: :ref:`Least-squares system solver ` - - ``inv``: :ref:`Solve for (multiplicative) matrix inverse ` - -Each item listed above is a NumPy-equivalent function, though not -completely interchangeable. The descriptions that follow are not -meant to introduce theory for the methods, nor to show an exhaustive -set of examples as to their usage. They simply describe the respective -algorithm's usage with some relevant examples. Several algorithms -have been borrowed from the tasks described at -`RosettaCode `_. - -Decompositions -============== - -.. index:: Decomposition; Cholesky - -.. _chol: - -Cholesky Decomposition ----------------------- - -`Cholesky decomposition`_ involves taking a symmetric, positive-definite -matrix A and decomposing it into L such that A=LL'=U'U, -where L is a lower triangular matrix and U is an upper triangular matrix. - -Example 1:: - - >>> A = [[25, 15, -5], - ... [15, 18, 0], - ... [-5, 0, 11]] - ... - >>> L = chol(A) - >>> L - array([[ 5., 0., 0.], - [ 3., 3., 0.], - [-1., 1., 3.]]) - >>> U = chol(A, 'upper') - >>> U - array([[ 5., 3., -1.], - [ 0., 3., 1.], - [ 0., 0., 3.]]) - -Example 2:: - - >>> A = [[18, 22, 54, 42], - ... [22, 70, 86, 62], - ... [54, 86, 174, 134], - ... [42, 62, 134, 106]] - ... - >>> L = chol(A) - >>> L - array([[ 4.24264069, 0. , 0. , 0. ], - [ 5.18544973, 6.5659052 , 0. , 0. ], - [ 12.72792206, 3.0460385 , 1.64974225, 0. ], - [ 9.89949494, 1.62455386, 1.84971101, 1.39262125]]) - -.. index:: Decomposition; LU - -.. _lu: - -LU Decomposition ----------------- - -`LU Decomposition`_ factors a matrix as the product of a lower triangular -matrix and an upper triangular matrix, and in this case, a pivot or -permutation matrix as well. The decomposition can be viewed as the matrix -form of `gaussian elimination`_. Computers usually solve square systems of -linear equations using the LU decomposition, and it is also a key step -when inverting a matrix, or computing the determinant of a matrix. - -Example 1:: - - >>> A = [[1, 3, 5], - ... [2, 4, 7], - ... [1, 1, 0]] - ... - >>> L, U, P = lu(A) - >>> L - array([[ 1. , 0. , 0. ], - [ 0.5, 1. , 0. ], - [ 0.5, -1. , 1. ]]) - >>> U - array([[ 2. , 4. , 7. ], - [ 0. , 1. , 1.5], - [ 0. , 0. , -2. ]]) - >>> P - array([[ 0., 1., 0.], - [ 1., 0., 0.], - [ 0., 0., 1.]]) - -Example 2:: - - >>> A = [[11, 9, 24, 2], - ... [ 1, 5, 2, 6], - ... [ 3, 17, 18, 1], - ... [ 2, 5, 7, 1]] - ... - >>> L, U, P = lu(A) - >>> L - array([[ 1. , 0. , 0. , 0. ], - [ 0.27272727, 1. , 0. , 0. ], - [ 0.09090909, 0.2875 , 1. , 0. ], - [ 0.18181818, 0.23125 , 0.00359712, 1. ]]) - >>> U - array([[ 11. , 9. , 24. , 2. ], - [ 0. , 14.54545455, 11.45454545, 0.45454545], - [ 0. , 0. , -3.475 , 5.6875 ], - [ 0. , 0. , 0. , 0.51079137]]) - >>> P - array([[ 1., 0., 0., 0.], - [ 0., 0., 1., 0.], - [ 0., 1., 0., 0.], - [ 0., 0., 0., 1.]]) - -.. index:: Decomposition; QR - -.. _qr: - -QR Decomposition ----------------- - -`QR decomposition `_ is -applicable to any m-by-n matrix *A* and decomposes -into A=QR where *Q* is an orthogonal matrix of size m-by-m and -*R* is an upper triangular matrix of size m-by-n. QR decomposition provides -an alternative way of `solving the systems of equations `_ -Ax=b without inverting the matrix *A*. The fact that *Q* is -orthogonal means that Q'Q=I, so that Ax=b is equivalent to Rx=Q'b, -which is easier to solve since *R* is triangular. - -Example of a square input matrix:: - - >>> A = [[12, -51, 4], - ... [ 6, 167, -68], - ... [-4, 24, -41]] - ... - >>> q, r = qr(A) - >>> q - array([[-0.85714286, 0.39428571, 0.33142857], - [-0.42857143, -0.90285714, -0.03428571], - [ 0.28571429, -0.17142857, 0.94285714]]) - >>> r - array([[ -1.40000000e+01, -2.10000000e+01, 1.40000000e+01], - [ 5.97812398e-18, -1.75000000e+02, 7.00000000e+01], - [ 4.47505281e-16, 0.00000000e+00, -3.50000000e+01]]) - -Example of a non-square input matrix:: - - >>> A = [[12, -51, 4], - ... [ 6, 167, -68], - ... [-4, 24, -41], - ... [-1, 1, 0], - ... [ 2, 0, 3]] - ... - >>> q, r = qr(A) - >>> q - array([[-0.84641474, 0.39129081, -0.34312406, 0.06613742, -0.09146206], - [-0.42320737, -0.90408727, 0.02927016, 0.01737854, -0.04861045], - [ 0.28213825, -0.17042055, -0.93285599, -0.02194202, 0.14371187], - [ 0.07053456, -0.01404065, 0.00109937, 0.99740066, 0.00429488], - [-0.14106912, 0.01665551, 0.10577161, 0.00585613, 0.98417487]]) - >>> r - array([[ -1.41774469e+01, -2.06666265e+01, 1.34015667e+01], - [ 3.31666807e-16, -1.75042539e+02, 7.00803066e+01], - [ -3.36067949e-16, 2.87087579e-15, 3.52015430e+01], - [ 9.46898347e-17, 5.05117109e-17, -9.49761103e-17], - [ -1.74918720e-16, -3.80190411e-16, 8.88178420e-16]]) - >>> import numpy as np - >>> np.all(np.dot(q, r) - A<1e-12) - True - -Solving Systems of Equations and Matrix Inverse -=============================================== - -.. index:: Solving linear systems; general solver - -.. _solve: - -General linear system solver ----------------------------- - -The general solver for linear systems of equations uses -`gaussian elimination`_. One or multiple columns in the RHS can be input, -like when solving for the `matrix inverse `_. - -Example:: - - >>> A = [[1, 2, 1], [4, 6, 3], [9, 8, 2]] - >>> b = [3, 2, 1] - >>> solve(A, b) - array([ -7., 11., -12.]) - -.. index:: Solving linear systems; least-squares - -.. _lstsq: - -Least-squares linear system solver ----------------------------------- - -Solving a system of linear equations using the `least squares`_ method -involves the usage of `QR decomposition `_. - -Example: Fit a quadratic line to some experimental data:: - - >>> x = np.array([0, 1, 2, 3, 4, 5]) - >>> y = np.array([3, 6, 11, 18, 27, 38]) - >>> y = y + np.random.randn(len(y)) # give the output a random offset - >>> A = np.vstack([np.ones(len(x)), x, x**2]).T - >>> A - array([[ 1., 0., 0.], - [ 1., 1., 1.], - [ 1., 2., 4.], - [ 1., 3., 9.], - [ 1., 4., 16.], - [ 1., 5., 25.]]) - >>> b = lstsq(A, y) # the quadratic fit coefficients (b0 + b1*x + b2*x**2) - -Now, we can see what the fit looks like compared to the original data using -Matplotlib:: - - >>> fit = lambda x: b[0] + b[1]*x + b[2]*x**2 - >>> import matplotlib.pyplot as plt - >>> plt.plot(x, y, 'ro', x, fit(x), 'b-') - >>> plt.legend(['data', 'quadratic fit']) - >>> plt.show() - -.. image:: _static/lstsq_fit.png - -.. index:: Matrix inverse - -.. _inv: - -Matrix Inverse --------------- - -Solving for a `matrix inverse`_ is performed using :func:`inv`. -Internally, this is done using the general solver and inputting the -an appropriately sized identity matrix as the RHS of the system. - -Example:: - - >>> A = [[25, 15, -5], - ... [15, 18, 0], - ... [-5, 0, 11]] - ... - >>> Ainv = inv(A) - >>> Ainv - array([[ 0.09777778, -0.08148148, 0.04444444], - [-0.08148148, 0.12345679, -0.03703704], - [ 0.04444444, -0.03703704, 0.11111111]]) - >>> np.dot(Ainv, A) - array([[ 1.00000000e+00, 0.00000000e+00, 0.00000000e+00], - [ 2.77555756e-16, 1.00000000e+00, 0.00000000e+00], - [ 0.00000000e+00, 1.11022302e-16, 1.00000000e+00]]) - -You'll notice that the off-diagonal elements aren't all perfectly zero. This -is due to floating-point error, but otherwise the final matrix is the -identity matrix. - -.. _Cholesky decomposition: http://en.wikipedia.org/wiki/Cholesky_decomposition -.. _LU decomposition: http://en.wikipedia.org/wiki/LU_decomposition -.. _QR decomposition: http://en.wikipedia.org/wiki/QR_decomposition -.. _gaussian elimination: http://en.wikipedia.org/wiki/Gaussian_elimination -.. _least squares: http://en.wikipedia.org/wiki/Linear_least_squares_(mathematics)#Orthogonal_decomposition_methods -.. _matrix inverse: http://en.wikipedia.org/wiki/Gaussian_elimination#Finding_the_inverse_of_a_matrix diff --git a/doc/make.bat b/doc/make.bat deleted file mode 100644 index d1cd1ae..0000000 --- a/doc/make.bat +++ /dev/null @@ -1,112 +0,0 @@ -@ECHO OFF - -REM Command file for Sphinx documentation - -set SPHINXBUILD=sphinx-build -set ALLSPHINXOPTS=-d _build/doctrees %SPHINXOPTS% . -if NOT "%PAPER%" == "" ( - set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% -) - -if "%1" == "" goto help - -if "%1" == "help" ( - :help - echo.Please use `make ^` where ^ is one of - echo. html to make standalone HTML files - echo. dirhtml to make HTML files named index.html in directories - echo. pickle to make pickle files - echo. json to make JSON files - echo. htmlhelp to make HTML files and a HTML help project - echo. qthelp to make HTML files and a qthelp project - echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter - echo. changes to make an overview over all changed/added/deprecated items - echo. linkcheck to check all external links for integrity - echo. doctest to run all doctests embedded in the documentation if enabled - goto end -) - -if "%1" == "clean" ( - for /d %%i in (_build\*) do rmdir /q /s %%i - del /q /s _build\* - goto end -) - -if "%1" == "html" ( - %SPHINXBUILD% -b html %ALLSPHINXOPTS% _build/html - echo. - echo.Build finished. The HTML pages are in _build/html. - goto end -) - -if "%1" == "dirhtml" ( - %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% _build/dirhtml - echo. - echo.Build finished. The HTML pages are in _build/dirhtml. - goto end -) - -if "%1" == "pickle" ( - %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% _build/pickle - echo. - echo.Build finished; now you can process the pickle files. - goto end -) - -if "%1" == "json" ( - %SPHINXBUILD% -b json %ALLSPHINXOPTS% _build/json - echo. - echo.Build finished; now you can process the JSON files. - goto end -) - -if "%1" == "htmlhelp" ( - %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% _build/htmlhelp - echo. - echo.Build finished; now you can run HTML Help Workshop with the ^ -.hhp project file in _build/htmlhelp. - goto end -) - -if "%1" == "qthelp" ( - %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% _build/qthelp - echo. - echo.Build finished; now you can run "qcollectiongenerator" with the ^ -.qhcp project file in _build/qthelp, like this: - echo.^> qcollectiongenerator _build\qthelp\uncertaintiesPythonpackage.qhcp - echo.To view the help file: - echo.^> assistant -collectionFile _build\qthelp\uncertaintiesPythonpackage.ghc - goto end -) - -if "%1" == "latex" ( - %SPHINXBUILD% -b latex %ALLSPHINXOPTS% _build/latex - echo. - echo.Build finished; the LaTeX files are in _build/latex. - goto end -) - -if "%1" == "changes" ( - %SPHINXBUILD% -b changes %ALLSPHINXOPTS% _build/changes - echo. - echo.The overview file is in _build/changes. - goto end -) - -if "%1" == "linkcheck" ( - %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% _build/linkcheck - echo. - echo.Link check complete; look for any errors in the above output ^ -or in _build/linkcheck/output.txt. - goto end -) - -if "%1" == "doctest" ( - %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% _build/doctest - echo. - echo.Testing of doctests in the sources finished, look at the ^ -results in _build/doctest/output.txt. - goto end -) - -:end diff --git a/doc/user_guide.rst b/doc/user_guide.rst deleted file mode 100644 index bd7b942..0000000 --- a/doc/user_guide.rst +++ /dev/null @@ -1,359 +0,0 @@ -.. index:: user guide -.. _user guide: - -========== -User Guide -========== - - -Basic setup -=========== - -Basic mathematical operations involving numbers that track derivatives -only require a simple import: - ->>> from ad import adnumber - -The :func:`adnumber` function creates numbers with derivative tracing -capabilities. Existing calculation code can usually run with no or -little modification and automatically produce derivatives. - -.. The "import ad" is put here because some examples requires - ad to have been imported (and not only adnumber). - -The :mod:`ad` module contains other features, which can be -made accessible through - ->>> import ad - -The :mod:`ad` package also contains sub-modules for -:ref:`advanced mathematical functions ` - -.. index:: - pair: number that tracks derivatives; creation - -Creating automatical differentiation numbers -============================================ - -Numbers that track their derivatives are input just as you would for -any normal numeric type. In that sense, they are basically *wrapped* -without really changing their fundamental type. For example, x = 2 -can be expressed in any of the basic numeric ways, including: - ->>> x = adnumber(2) # acts like an "int" object ->>> x = adnumber(2.0) # acts like a "float" object ->>> x = adnumber(2+0j) # acts like a "complex" object - -Mathematical calculations that follow, like: - ->>> x/3 # if x = adnumber(2), the result is ad(0) because of integer math - -are interpreted based upon the base numeric types involved. - -Basic math -========== - -Calculations can be performed directly, as with regular real or complex -numbers: - ->>> square = x**2 ->>> print square -ad(4) ->>> a = adnumber(3 + 4j) ->>> print a -ad((3+4j)) ->>> abs(a) -ad(5.0) ->>> b = adnumber(1 - 1j) ->>> a*b -ad((7+1j)) ->>> a.real, a.imag -(3.0, 4.0) - -AD objects that represent real values can also be used to create complex ones: - ->>> y = adnumber(3.14) ->>> z = x + y*1j ->>> print z -ad((2+3.14j)) - -If an AD object is used as input to :func:`adnumber`, then a deepcopy is made, -but no tracking relation is created between the input and output objects: - ->>> z = adnumber(x) ->>> z -ad(2) ->>> z is x # are they the same object? -False ->>> z == x # are the nominal values the same? -True - -More of this is explained below, but we can see that derivatives show the -disconnect between the objects: - ->>> z.d(x) # derivative of z wrt x -0.0 ->>> z.d(z) # derivative of z wrt itself -1.0 ->>> x.d(z) # derivative of x wrt z -0.0 - - -.. index:: mathematical operation; on a scalar, admath - -.. _advanced math operations: - -Mathematical operations -======================= - -Besides being able to apply basic mathematical operations, this package -provides generalizations of **most of the functions from the standard** -:mod:`math` **and** :mod:`cmath` **modules**. -These mathematical functions are found in the :mod:`ad.admath` module: - ->>> from ad.admath import * # Imports sin(), etc. ->>> sin(x**2) -ad(-0.7568024953079282) - -These functions are designed to support whichever numeric types are normally -compatible with them. For example, the :func:`sin` function has a real and -complex counterpart, as do many others. Some functions, like :func:`erf` are -only available in the :mod:`math` module, so an exception is raised if a -complex number is passed to it. - -There are also many other functions not normally found in the :mod:`math` -and :mod:`cmath` modules that are conveniently available, like :func:`csc` -and others. - -The list of available mathematical functions can be obtained with the -``pydoc ad.admath`` command. - - -.. index:: arrays; simple use, matrices; simple use - -.. _simple_array_use: - -Arrays of numbers -================= - -It is possible to put automatic differentiation numbers with in NumPy_ -arrays and matrices, lists, or tuples, and the returned object is of that -respective type (even nested objects work): - ->>> adnumber([1, [2, 3]]) # nested list input -[ad(1), [ad(2), ad(3)]] ->>> adnumber((1, 2)) # tuple input -(ad(1), ad(2)) ->>> arr = adnumber(np.array([[1, 2], [3, 4]])) # NumPy array input ->>> 2*arr -array([[ad(2), ad(4)], - [ad(6), ad(8)]], dtype=object) ->>> print arr.sum() -ad(10) - -Thus, usual operations on NumPy arrays can be performed transparently -even when these arrays contain numbers that track derivatives. - - -.. index:: - pair: nominal value; of scalar - pair: derivative; of scalar - -Access to the derivatives and to the nominal value -================================================== - -The nominal value and the derivatives can be accessed independently: - ->>> print square -ad(4) ->>> print square.x # the underlying numeric object -4 ->>> print square.d(x) # first derivative wrt x -4.0 ->>> print square.d2(x) # second derivative wrt x -2.0 ->>> print square.d() # left empty returns a dictionary of related derivatives -{ad(4): 4.0} ->>> y = adnumber(1.5) ->>> print square.d(y) # if a derivative doesn't exist, zero is returned -0.0 ->>> z = square/y ->>> z.d2c(x,y) # second cross-derivative wrt x and y, either order is ok --1.7777777777777777 ->>> z.d(square) # since "square" is a dependent variable, derivative is zero -0.0 - -Access to more than one derivative -================================== - -Arrays of derivatives can be obtained through the :func:`gradient` and -:func:`hessian` methods. The individual variables can be more easily -identified when the variables are **tagged**, though tags *do not have -to be distinct*: - ->>> u = adnumber(0.1, 'u') # Tag ->>> v = adnumber(3.14, 'v') - ->>> sum_value = u+2*v/u ->>> sum_value -ad(62.9) ->>> sum_value.d() -{ad(0.1, u): -626.9999999999999, ad(3.14, v): 20.0} - ->>> sum_value.gradient([u, v]) -[-626.9999999999999, 20.0] - ->>> sum_value.hessian([u, v]) -[[12559.999999999998, -199.99999999999997], [-199.99999999999997, 0.0]] - -The **jacobian matrix** can be easily created for multiple dependent objects, -where each row is the gradient of the dependent variables with respect to -each of the independent variables, *in the order specified*: - ->>> from ad import jacobian ->>> jacobian([square, sum_value], [x, u, v]) -[[4.0, 0.0, 0.0], [0.0, -626.9999999999999, 20.0]] - - -.. index:: comparison operators - -Comparison operators -==================== - -Comparison operators behave naturally as they would with numbers outside of -this package, even with other scalar values: - ->>> x = adnumber(0.2) ->>> x -ad(0.2) ->>> y = adnumber(1) ->>> y -ad(1) ->>> y > x -True ->>> y > 0 -True ->>> y == 1.0 -True - - -.. index:: - single: C code; wrapping - single: Fortran code; wrapping - single: wrapping (C, Fortran,…) functions - -Making custom functions accept numbers that track derivatives -============================================================= - -Due to the nature of automatic differentiation, unless a function can be -represented with a mathematical equation, automatic differentiation is -meaningless. For custom functions that cannot be represented mathematically -(i.e., those that do not have an analytical form), derivatives may be -calculated using other means like finite difference derivatives. - - -Miscellaneous utilities -======================= - -.. index:: optimization - -It is sometimes useful to use the gradients and hessians provided by this -package for the purpose of supplementing an optimization routine, like -those in the `scipy.optimize`_ submodule. With this package, a function -can be conveniently wrapped with functions that return both the gradient -and hessian: - ->>> from ad import gh # the gradient and hessian functions generator ->>> def my_cool_function(x): -... return (x[0] - 10.0)**2 + (x[1] + 5.0)**2 ->>> my_cool_gradient, my_cool_hessian = gh(my_cool_function) - -These objects (:func:`my_cool_gradient` and :func:`my_cool_hessian`) -*are functions* that accept an array ``x`` and other optional args. -Depending on the optimization routine, you may be able to use only -the gradient function (typically with the keyword ``jac=...``): - ->>> from scipy.optimize import minimize ->>> x0 = [24, 17] ->>> bnds = ((0, None), (0, None)) ->>> res = minimize(my_cool_function, x0, bounds=bnds, method='L-BFGS-B', -... jac=my_cool_gradient, options={'ftol': 1e-8, 'disp':False}) ->>> res.x -array([ 10., 0.]) ->>> res.fun -25.0 ->>> res.jac -array([ 7.10542736e-15, 1.00000000e+01]) - -You might wonder why the final gradient (``res.jac``) isn't precisely [0, 10]. -It's *not* because of numerical error in the AD methods, because although it -appears that the final ``res.x`` value is precisely [10, 0], if we print out -all the available digits, we see that this is not the case (i.e., NumPy_ -was not being completely truthful about it's values with pretty printing): - ->>> list(res.x) -[10.000000000000004, 0.0] - -The real reason for the inaccuracy is because of the ``None`` upper bounds -given to the `L-BFGS-B` algorithm. If we had used finite upper bounds, -we get the exact answer: - ->>> bnds = ((0, 100), (0, 100)) ->>> res = minimize(my_cool_function, x0, bounds=bnds, method='L-BFGS-B', -... jac=my_cool_gradient, options={'ftol': 1e-8, 'disp':True}) ->>> list(res.x) -[10.0, 0.0] ->>> list(res.jac) -[0.0, 10.0] - -Notice that the use of :func:`gh` doesn't require you to explicitly -initialize any variable with :func:`adnumber` since it all happens -internally with the wrapped functions. - - -Testing if a variable can track derivatives -=========================================== - -The recommended way of testing whether :data:`value` tracks -derivatives handled by this module is by checking whether -:data:`value` is an instance of :class:`ADF`, through -``isinstance(value, ad.ADF)``. - - -Python classes for variables and functions with derivatives -=========================================================== - -Numbers with derivatives are represented through two different -classes: - -1. a class for independent variables (:class:`ADV`, which - inherits from :class:`ADF`), - -2. a class for functions that depend on independent variables - (:class:`ADF`). - -Documentation for these classes is available in their Python -docstring, which can for instance displayed through pydoc_. - -The factory function :func:`adnumber` creates variables and thus returns -a :class:`ADV` object: - ->>> x = adnumber(0.1) ->>> type(x) - - -:class:`ADV` objects can be used as if they were regular Python -numbers (the summation, etc. of these objects is defined). - -Mathematical expressions involving numbers with derivatives -generally return :class:`ADF` objects, because they -represent mathematical functions and not simple variables; these -objects store all the variables they depend on: - ->>> type(admath.sin(x)) - - -.. _NumPy: http://numpy.scipy.org/ -.. _scipy.optimize: http://docs.scipy.org/doc/scipy/reference/tutorial/optimize.html -.. _pydoc: http://docs.python.org/library/pydoc.html - diff --git a/docs/api.md b/docs/api.md index 6004d61..6241902 100644 --- a/docs/api.md +++ b/docs/api.md @@ -31,6 +31,7 @@ The **jacobian matrix** can be created for multiple dependent objects, where eac ```python from ad import jacobian + jacobian([square, sum_value], [x, u, v]) ``` @@ -56,20 +57,16 @@ pydoc ad.admath ### `chol` ```python -A = [[25, 15, -5], - [15, 18, 0], - [-5, 0, 11]] +A = [[25, 15, -5], [15, 18, 0], [-5, 0, 11]] L = chol(A) -U = chol(A, 'upper') +U = chol(A, "upper") ``` ### `lu` ```python -A = [[1, 3, 5], - [2, 4, 7], - [1, 1, 0]] +A = [[1, 3, 5], [2, 4, 7], [1, 1, 0]] L, U, P = lu(A) ``` @@ -77,9 +74,7 @@ L, U, P = lu(A) ### `qr` ```python -A = [[12, -51, 4], - [ 6, 167, -68], - [-4, 24, -41]] +A = [[12, -51, 4], [6, 167, -68], [-4, 24, -41]] q, r = qr(A) ``` @@ -105,9 +100,7 @@ b = lstsq(A, y) ### `inv` ```python -A = [[25, 15, -5], - [15, 18, 0], - [-5, 0, 11]] +A = [[25, 15, -5], [15, 18, 0], [-5, 0, 11]] Ainv = inv(A) ``` @@ -120,8 +113,10 @@ With this package, a function can be wrapped with functions that return both gra ```python from ad import gh + def my_cool_function(x): - return (x[0] - 10.0)**2 + (x[1] + 5.0)**2 + return (x[0] - 10.0) ** 2 + (x[1] + 5.0) ** 2 + my_cool_gradient, my_cool_hessian = gh(my_cool_function) ``` diff --git a/docs/index.md b/docs/index.md index fb6d484..3572ba9 100644 --- a/docs/index.md +++ b/docs/index.md @@ -27,9 +27,9 @@ from ad.admath import sin x = adnumber(1) y = sin(2 * x) -print(y) # ad(0.9092974268256817) -print(y.d(x)) # -0.8322936730942848 -print(y.d2(x))# -3.637189707302727 +print(y) # ad(0.9092974268256817) +print(y.d(x)) # -0.8322936730942848 +print(y.d2(x)) # -3.637189707302727 ``` ## Main Features diff --git a/docs/quickstart.md b/docs/quickstart.md index 22de7d1..5457806 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -7,18 +7,19 @@ Calculations involving **differentiation** can be performed even without knowing ```python from ad import adnumber from ad.admath import * # sin(), etc. + x = adnumber(1) -print(2*x) +print(2 * x) # ad(2) -sin(2*x) +sin(2 * x) # ad(0.9092974268256817) ``` So far, there should not be anything unexpected, but first and second derivatives can now be accessed through **intuitive methods**: ```python -y = sin(2*x) -y.d(x) # dy/dx at x=1 +y = sin(2 * x) +y.d(x) # dy/dx at x=1 # -0.8322936730942848 y.d2(x) # d2y/dx2 at x=1 # -3.637189707302727 @@ -47,9 +48,9 @@ import ad Numbers that track their derivatives are input just as you would for any normal numeric type. In that sense, they are basically wrapped without really changing their fundamental type. ```python -x = adnumber(2) # acts like an int object -x = adnumber(2.0) # acts like a float object -x = adnumber(2+0j) # acts like a complex object +x = adnumber(2) # acts like an int object +x = adnumber(2.0) # acts like a float object +x = adnumber(2 + 0j) # acts like a complex object ``` Mathematical calculations that follow are interpreted based upon the base numeric types involved. @@ -68,7 +69,7 @@ print(a) abs(a) # ad(5.0) b = adnumber(1 - 1j) -a*b +a * b # ad((7+1j)) a.real, a.imag # (3.0, 4.0) @@ -78,7 +79,7 @@ AD objects that represent real values can also be used to create complex ones: ```python y = adnumber(3.14) -z = x + y*1j +z = x + y * 1j print(z) # ad((2+3.14j)) ``` @@ -107,6 +108,7 @@ These mathematical functions are found in the `ad.admath` module: ```python from ad.admath import * # Imports sin(), etc. + sin(x**2) # ad(-0.7568024953079282) ``` @@ -129,7 +131,7 @@ adnumber([1, [2, 3]]) adnumber((1, 2)) # (ad(1), ad(2)) arr = adnumber(np.array([[1, 2], [3, 4]])) -2*arr +2 * arr # array([[ad(2), ad(4)], # [ad(6), ad(8)]], dtype=object) arr.sum() @@ -168,10 +170,10 @@ z.d(square) Arrays of derivatives can be obtained through the `gradient` and `hessian` methods. ```python -u = adnumber(0.1, 'u') -v = adnumber(3.14, 'v') +u = adnumber(0.1, "u") +v = adnumber(3.14, "v") -sum_value = u + 2*v/u +sum_value = u + 2 * v / u sum_value.d() # {ad(0.1, u): -626.9999999999999, ad(3.14, v): 20.0} @@ -182,6 +184,7 @@ sum_value.hessian([u, v]) # [[12559.999999999998, -199.99999999999997], [-199.99999999999997, 0.0]] from ad import jacobian + jacobian([square, sum_value], [x, u, v]) # [[4.0, 0.0, 0.0], [0.0, -626.9999999999999, 20.0]] ``` @@ -214,8 +217,10 @@ With this package, a function can be conveniently wrapped with functions that re ```python from ad import gh + def my_cool_function(x): - return (x[0] - 10.0)**2 + (x[1] + 5.0)**2 + return (x[0] - 10.0) ** 2 + (x[1] + 5.0) ** 2 + my_cool_gradient, my_cool_hessian = gh(my_cool_function) ``` @@ -231,9 +236,9 @@ res = minimize( my_cool_function, x0, bounds=bnds, - method='L-BFGS-B', + method="L-BFGS-B", jac=my_cool_gradient, - options={'ftol': 1e-8, 'disp': False}, + options={"ftol": 1e-8, "disp": False}, ) res.x @@ -259,9 +264,9 @@ res = minimize( my_cool_function, x0, bounds=bnds, - method='L-BFGS-B', + method="L-BFGS-B", jac=my_cool_gradient, - options={'ftol': 1e-8, 'disp': True}, + options={"ftol": 1e-8, "disp": True}, ) list(res.x) diff --git a/revision_history.txt b/revision_history.txt deleted file mode 100644 index c636827..0000000 --- a/revision_history.txt +++ /dev/null @@ -1,86 +0,0 @@ -ad-1.1.1 -======== - -- Added ``gh`` utility function for generating gradient and hessian functions - of mathematical functions. The intent is to make it easy for users wanting to - use the ``ad`` package with``scipy.optimize`` functions. - -ad-1.1 -====== - -- Changed the core usage to be compatible with all base numeric types (int, - float, long, and complex). - -- Changed the main constructor name from ``adfloat`` to ``adnumber`` because of - the full numeric support (not just for floats). The reasoning is because this - package should simply provide a "wrapper"-ish functionality for derivative - tracking (i.e., it shouldn't force the user to choose float objects if they - don't want to. - -- Added ``real`` and ``imag`` properties to ``ADF`` class. - -- Updated all admath functions to work with their respective numeric types using - the math and cmath module functions. - -- Updated all admath function documentation to reflect basically the same as the - math module. - -- Added ``pi`` and ``e`` module members to admath. - -- Added ``atan2``, ``isinf`` and ``isnan`` methods to admath. - -- Updated ``log10``, ``log1p``, ``expm1``, and ``fabs`` in admath to use the - actual math or cmath module functions, mostly for their higher precision at - certain input values (see the math/cmath module documentation for more - details). - -- Bug fix: ``log`` didn't default to base ``e`` before. It's fixed now. - -ad-1.0.3 -======== - -- Fixed an issue with using Numpy arrays as input to ``adfloat`` in Python 3.3. - -- Renamed ``_calculate_derivatives`` method to more appropriately be called - ``_apply_chain_rule``. - -ad-1.0.2 -======== - -- Default constructor ``AD`` renamed to ``adfloat`` to follow general coding - guidelines better. - -- Changed ``ADF(...)`` and ``ADV(...)`` to just ``ad(...)`` when printing out - the variables in either str or repr form (made a general printer--credits to - EOL!). - -- Updated the ``_get_variables`` method to not depend on the ``d(...)`` method, - but to access the hidden member ``_lc`` directly for getting first derivative - variables. - -- Renamed hidden member ``_hash`` to ``_trace``. - -- Made the constructor for arrays more robust and now the tag is applied to all - objects that get created. - -- Constructor is updated to return a copy of another AD object if supplied as an - input (i.e., ``x = adfloat(2); y = adfloat(x)``). This makes the two objects - equivalent, copying the nominal value and the derivatives, but naturally they - two objects are not identical (i.e., ``x==y`` returns ``True``, but ``x is y`` - returns ``False``). - -- Added ``sqrt`` method to ``ADF`` class because some ``numpy`` functions look - for this method of the objects it operates on (i.e., ``numpy.sqrt``, - ``numpy.std``, etc.). Also updated the ``sqrt`` function in the ``admath`` - module to actually use the ``math.sqrt`` method to perform the calculations. - -ad-1.0.1 -======== -- Fixed some vectorization bugs - -ad-1.0 -====== -- 1.0: Initial release. Nearly full differentiation support for all - math module functions. - -