From 830ce1ab3fb3b72b19ef70bfc4f752033c20faf9 Mon Sep 17 00:00:00 2001 From: CalMacCQ <93673602+CalMacCQ@users.noreply.github.com> Date: Tue, 13 Dec 2022 14:12:00 +0000 Subject: [PATCH 01/20] add new logo --- .github/workflows/docs/Quantinuum_logo2.png | Bin 0 -> 18245 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 .github/workflows/docs/Quantinuum_logo2.png diff --git a/.github/workflows/docs/Quantinuum_logo2.png b/.github/workflows/docs/Quantinuum_logo2.png new file mode 100644 index 0000000000000000000000000000000000000000..5569581b8e420f14eee561cbf1bf78ca0c96882f GIT binary patch literal 18245 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 Date: Tue, 13 Dec 2022 14:16:48 +0000 Subject: [PATCH 02/20] remove html workaround --- docs/intro.txt | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/docs/intro.txt b/docs/intro.txt index e1461620..70aea340 100644 --- a/docs/intro.txt +++ b/docs/intro.txt @@ -1,19 +1,6 @@ pytket-qiskit ================================== -.. raw:: html - - -
- -
- - -.. image:: Quantinuum_logo.png - :width: 0px - :height: 0px - :align: right - IBM's `Qiskit `_ is an open-source framework for quantum computation, ranging from high-level algorithms to low-level circuit representations, simulation and access to the `IBMQ `_ Experience devices. From d96847fef92e146cb87bad8ccebe68756cccd577 Mon Sep 17 00:00:00 2001 From: CalMacCQ <93673602+CalMacCQ@users.noreply.github.com> Date: Tue, 13 Dec 2022 14:17:16 +0000 Subject: [PATCH 03/20] update requirements --- .github/workflows/docs/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs/requirements.txt b/.github/workflows/docs/requirements.txt index 62096a9d..382fc378 100644 --- a/.github/workflows/docs/requirements.txt +++ b/.github/workflows/docs/requirements.txt @@ -1,2 +1,2 @@ sphinx ~= 4.3.2 -sphinx_rtd_theme +sphinx_book_theme From 8aa2c6132c6cf2242c481a010601bc1573adb5f2 Mon Sep 17 00:00:00 2001 From: CalMacCQ <93673602+CalMacCQ@users.noreply.github.com> Date: Tue, 13 Dec 2022 14:17:42 +0000 Subject: [PATCH 04/20] update build-docs --- .github/workflows/docs/build-docs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/.github/workflows/docs/build-docs b/.github/workflows/docs/build-docs index 89cd7274..76657f5f 100755 --- a/.github/workflows/docs/build-docs +++ b/.github/workflows/docs/build-docs @@ -2,11 +2,11 @@ import argparse import datetime -from importlib import import_module -from pathlib import Path import shutil import subprocess import sys +from importlib import import_module +from pathlib import Path DOCS_DIR = Path(sys.argv[0]).absolute().parent MODULES_DIR = DOCS_DIR.parent.parent.parent @@ -16,6 +16,7 @@ PYTKET_QISKIT_PYPI_LINK = "https://pypi.org/project/pytket-qiskit/" PYTKET_QISKIT_GITHUB = "https://github.com/CQCL/pytket-qiskit" MODULE = "qiskit" + def get_module_version(): m = import_module(f"pytket.extensions.{MODULE}") return m._metadata.__extension_version__.split(".") @@ -39,9 +40,9 @@ def build_module_docs(): mod_docs = MODULES_DIR / "docs" mod_build = mod_docs / "build" conf_copy = mod_docs / "conf.py" - logo_copy = mod_docs / "Quantinuum_logo.png" + logo_copy = mod_docs / "Quantinuum_logo2.png" shutil.copy(DOCS_DIR / "conf.py", conf_copy) - shutil.copy(DOCS_DIR / "Quantinuum_logo.png", logo_copy) + shutil.copy(DOCS_DIR / "Quantinuum_logo2.png", logo_copy) remove_dir(mod_build) index_rst = mod_docs / "index.rst" with open(mod_docs / "intro.txt", "r") as f: @@ -51,12 +52,10 @@ def build_module_docs(): ) content.append(f"\tpytket <{PYTKET_DOCS_LINK}>\n") content.append(f"\tpytket extensions <{PYTKET_EX_DOCS_LINK}>\n") - content.append( - "\n.. toctree::\n\t:caption: Links:\n\t:maxdepth: 1\n\n" - ) + content.append("\n.. toctree::\n\t:caption: Links:\n\t:maxdepth: 1\n\n") content.append(f"\tbug tracker <{PYTKET_QISKIT_GITHUB}/issues>\n") content.append(f"\tGitHub <{PYTKET_QISKIT_GITHUB}>\n") - content.append(f"\tPyPi <{PYTKET_QISKIT_PYPI_LINK}>\n") + content.append(f"\tPyPi <{PYTKET_QISKIT_PYPI_LINK}>\n") with open(index_rst, "w") as f: f.writelines(content) @@ -102,4 +101,4 @@ if __name__ == "__main__": MODULES_DIR / "docs" / "build", dest, dirs_exist_ok=True, - ) + ) From 15ba5d10d1fff393f1270b1e2c9d3887bb0292be Mon Sep 17 00:00:00 2001 From: CalMacCQ <93673602+CalMacCQ@users.noreply.github.com> Date: Tue, 13 Dec 2022 14:18:09 +0000 Subject: [PATCH 05/20] update conf.py --- .github/workflows/docs/conf.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/.github/workflows/docs/conf.py b/.github/workflows/docs/conf.py index fe9a193e..eaf69e6e 100644 --- a/.github/workflows/docs/conf.py +++ b/.github/workflows/docs/conf.py @@ -12,7 +12,21 @@ "sphinx.ext.mathjax", ] -html_theme = "sphinx_rtd_theme" +pygments_style = "pastie" + +html_theme = "sphinx_book_theme" + +html_theme_options = { + "repository_url": "https://github.com/CQCL/pytket-quantinuum", + "use_repository_button": True, + "use_issues_button": True, +} + +html_static_path = ["_static"] + +html_css_files = ["custom.css"] + +html_logo = "Quantinuum_logo2.png" # -- Extension configuration ------------------------------------------------- From 7fc46b957d23ca827b8c5d89ea1f831521406b97 Mon Sep 17 00:00:00 2001 From: CalMacCQ <93673602+CalMacCQ@users.noreply.github.com> Date: Tue, 13 Dec 2022 14:18:50 +0000 Subject: [PATCH 06/20] fix URL --- .github/workflows/docs/conf.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/docs/conf.py b/.github/workflows/docs/conf.py index eaf69e6e..1195c2eb 100644 --- a/.github/workflows/docs/conf.py +++ b/.github/workflows/docs/conf.py @@ -17,7 +17,7 @@ html_theme = "sphinx_book_theme" html_theme_options = { - "repository_url": "https://github.com/CQCL/pytket-quantinuum", + "repository_url": "https://github.com/CQCL/pytket-qiskit", "use_repository_button": True, "use_issues_button": True, } @@ -43,13 +43,14 @@ # The following code is for resolving broken hyperlinks in the doc. -from sphinx.application import Sphinx +import re +from typing import Any, Dict, List, Optional +from urllib.parse import urljoin + from docutils import nodes from docutils.nodes import Element, TextElement +from sphinx.application import Sphinx from sphinx.environment import BuildEnvironment -from urllib.parse import urljoin -import re -from typing import Any, Dict, List, Optional # Mappings for broken hyperlinks that intersphinx cannot resolve external_url_mapping = { From da446ac108276ea2c55eb7b47ec327c3835bab34 Mon Sep 17 00:00:00 2001 From: CalMacCQ <93673602+CalMacCQ@users.noreply.github.com> Date: Tue, 13 Dec 2022 14:23:04 +0000 Subject: [PATCH 07/20] add custom.css --- docs/_static/custom.css | 44 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 docs/_static/custom.css diff --git a/docs/_static/custom.css b/docs/_static/custom.css new file mode 100644 index 00000000..6552cb58 --- /dev/null +++ b/docs/_static/custom.css @@ -0,0 +1,44 @@ +.wy-side-nav-search, +.wy-nav-top { + background: #5A46BE; +} + +.wy-grid-for-nav, +.wy-body-for-nav, +.wy-nav-side, +.wy-side-scroll, +.wy-menu, +.wy-menu-vertical { + background-color: #FFFFFF; +} + +.wy-menu-vertical a:hover { + background-color: #d9d9d9; +} + +.caption-text { + color: #000000; +} + +.btn-link:visited, +.btn-link, +a:visited, +.a.reference.external, +.a.reference.internal, +.wy-menu-vertical a, +.wy-menu-vertical li, +.wy-menu-vertical ul, +.span.pre, +.sig-param, +.std.std-ref, +a { + color: #2563EB; +} + +:root { + --pst-color-inline-code: 199, 37, 78 !important; +} + +.sig-name { + font-size: 1.25rem; +} \ No newline at end of file From 5496561deed0827e6c41176adc103640d3972681 Mon Sep 17 00:00:00 2001 From: CalMacCQ <93673602+CalMacCQ@users.noreply.github.com> Date: Tue, 13 Dec 2022 14:24:30 +0000 Subject: [PATCH 08/20] remove refernce to old logo --- .github/workflows/docs/intro.txt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/docs/intro.txt b/.github/workflows/docs/intro.txt index 89a3ed67..85d4a2cc 100644 --- a/.github/workflows/docs/intro.txt +++ b/.github/workflows/docs/intro.txt @@ -1,11 +1,6 @@ pytket-extensions ================= -.. image:: Quantinuum_logo.png - :width: 160px - :align: right - - These extensions enable ``pytket` to be used in conjunction with other platforms. Each extension adds either new methods to the ``pytket`` package to convert between circuit representations, or new backends to which ``pytket`` From d6c9341999b3d1dbbf3129adfb379ad4afe360b9 Mon Sep 17 00:00:00 2001 From: CalMacCQ <93673602+CalMacCQ@users.noreply.github.com> Date: Tue, 13 Dec 2022 14:24:59 +0000 Subject: [PATCH 09/20] delete old logo --- .github/workflows/docs/Quantinuum_logo.png | Bin 58430 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .github/workflows/docs/Quantinuum_logo.png diff --git a/.github/workflows/docs/Quantinuum_logo.png b/.github/workflows/docs/Quantinuum_logo.png deleted file mode 100644 index e15bc56f61301d93775a7d8543f01e69d43a7cf9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 58430 zcmeFYcT^Kv*EdKA#Yj^SkSZmB^j<<0q$EHJ#+~;}b{bs#iS@Z9V%Pb?Dvd^x+z4tlyE?Akd9p^tzM@Pqo zLK@M9H`*# z8GO}CAu2EgjHaX0HHZpv_we@$6S?Z;gALLXTW)F-6Ty1wiCt1hE1^Tqd--CKF*q-q z7%N+k7=I6hrG2gJT5N$=p$jC^ANL7VkoR6Y10)bFeQc+YL!*Pj z+@s`!LdE~Rg0WYq2M!w&h7Ar9p{?kCH8?y>PYjUy&lv(k{`IHnlo9-^qM zphP><(Lhg+|BMR>#|0d1?&+cE72p-<6%-Z<#w!13Y>01gSa7Is@c(4#|NQ!Y*Z}Yr zjsDLb|1B+nf&bYeG|VId9OGXM`EN&u+D3^%)>cybXDB+@6YCxQ-wjn&(N_5%hXS4PbPsd?-wyWl(Dn|-1-gR+V*}lNyc9!% ze8fcl!$$4%!2!WIurZ)c^@s{IS{oG<8s;A4;e|5R69Z>fz+yeMz0|!m-PPSy8pd%kh7M>tKgwE6#Nxo5BkSmXcRRqd*`GD1m3 zLmr{xt|qUdrRE`jRZ~MvUKQb?q=E4CQdL$_{`YFuI4m$U_kjPpDvc^nu%fq$x{|uG zikiH)s*1O~x3`+Q{8d#iFL`%&WeqiNPbFp5tDZD%K2i{EBsLU?F8W{gVdHh}U*7_- zB1bx*?e0O-bv-c;nvlIb#s2kU?0>_L|D&D%H9ykV3oQD-5dJ^AhX#9xMY`j>41ECa z{3cDvHq#qeycx{|H6# z|0%Dd-~AVN^zY%o$I-t2$Gd|6{Kr3g1%ah;!25D(Tm_DMLI7oKXd6|qxbG7w=#x`= z=<;XQ#7KG(c*M#6l3f=gIS@#kGD zyqL*D1~KtpI~Cb1w||Nr^EUm`8^0MOub?1?BEZ4lx!u}wmqgk(6v396348QI6jkLk z@t@zL-n-!?|M@DPY?$}YKr-w9Kk)xM>`As$Jh!2urtPr72}e1k8@froV0m~}UzpB2 z^~@wxP-dboiO)^=A@p5Ra=S9dM5(%HTwGRq~zbk}rH!xXdhW9`# zzFp)OaZPTbG=965+cV^K>@r;t zG3cf!R)y#XcI!}z5-ffczK7*K!_g1RU`iBf_gElImary9K$uhNEt1L6ZmKUhhFzOo z<6GB5@EY_1il1Nfy-PJn;3}M2xMny?7n1QjlpNKz7sp2&mrTfA2y2zBX&=*RpRMZu z9V5qM5S-J~*8avrU(+!zzH&S2Nvtaqia<H-;e|zgCDg1xrnOK(-vBkcplmHO(0#n_>$fF!Op8X% zOsHl`@3@S94jffh`1#wntAqX*(xS*V1hUmA96n~Ael@)hq0m^^li3Bs!9x>PLrYWY znNhc{WGC4h@rVAZ2N3?w+;$({xp$fr8_E(B78odded8-gugEN?tekrPnV-)bl+Hkm>KN%llNo(o z%aQc$sODOI!HqJNl6}Y37oR9RU$n!3P&z+=_na&AO&c|qcO3l*DkH76PnV%~? z|0rv6Z*?5sJo`P2Dm~@Bs%62%?*z9C`2O-!DDmkM)8-{WkpIjJNX6Z^OmNb*Q6jys zEQwz>!#Rg-@4X?!i+gm-j)+jUv3n%de=gUaIQ~p^eTu12l-bK`%$c(;o6C5ar#KfL zsC0+zPpjwPc%-&K32v`DD3cM0_Wnoq%&7p`!UG?R3@?SHOmD`#vH|+KOrFRFj z_BL*HdMmY95k=U!`Id<+#x8&-7O7at_|*~2s{`SJW9DVO-R5MV;?LExa%LqbE09et zaR(|S%O=Ac^-Vz8PX#~IjH)2mI5rxS^Lu5QX&OkJmsc*D&|$QW^Zu6X(7E z-2UyAp@y=qL*AGZ#k@wCfrVSK^{BfM={Ey&6RS||qeGNiX|B~kje}h*EeHc+rkx-6 zLRKSg+7>J^v;X=b@^L5s{-qC?=T?F|B) zWZL{G2TrOFWK7STuknB@jh#=wmSd(R^+RxJz1DeDOCHx8bKkaNN!(1Qsvj{Qed}hx zY)VEj&$8>pk9Kncv9`u6&;BoAEP?EP8#Ooro07l;ZqkPkzC7o+R1c2u0%=r-;>^1a zjWc~y^S*s|@|1x__<%7&##Yvez%wBa%&hqy z42)H-jHi%sGQNoBDSpz`ri*d9O<&6&5L1qP#epaav(Y`BuSi$LvwTLfLp^uXRG{25 zobdT-=H8hzl3#}f=W;cmU&LDmte~!Ryh)0w8C3y$7zq?L>vCo(_e(J};j?Gr&8r@s zDSzjDoA#JFHp@csZ|}&Lx$=aVrePt4Y%&I)b26Vxf3V6ulrS^&SvmVBkqJx;ziI-U zh=5O`<)|)`ps1NfBwcLuitjVgya9vTohN^u#KrA00OiYNz~&|fqi&66f7>s&ld~nj z`2buZU#!cT&a0wVr0>lyDLmsN7*ZdM9C)e8{{hFi%pZ& zRX)rU4Kx$CCHJzTZH*;rC!Psg#+4CaP9ST5{Ch2W3QLvSI}01w%ql5#EORIznvR(o z?ZP+<^sLikT^K+RDt5)YEnQW&0CZnrr2@rn{vmxFCN3_A_3Xp3m27juzzG_o{{>zDI89NC7Wp}@TmUDRxK z-{r>rgu_0v_rs{{ndY_cJw;xhnyc4f{17}9BY`Sod=}wnQZOn_%2*ULQ+I`bZ05+E zPj8_Z;yld>^WNzq=VX%I7 zcg8&8jsRSMJ~lOD7P&EUg|q0oWm!l^=U=_j+E9BqYCe|6neUR)-;N|rl*FjC%Dqso#@9}8 z_k6hepcss5nz&DahumTCEv9Q@o{+NhBfvN0fwEu>WbPch58)z0wrVIGbL+-g#CWP? zmcCin>L%t&wvM4p1V`raTHM*!*QbOxZL;7Su%lU{jLpY&(LpCNc#CE4z>tKiH+8Mq z@v|T5lNLOYuYHI{OQAHixc&w>?t$QRyeNI!*@+?%J01ejOm?@l#hAXv(NpPlai`>8 zZmX+k)&V$*%?G#^zgHTC)5u-qVT}*cWE4i_LK4Wj$rLM`aXg*@YnBvB@lwH0X@?{U zLbBnci?lt^^|u&&f`MWBpsI>tIPtSU8AYc~zsO(DX-1{T#v7%_wOZ`_IbQA^4Gfcm zMt(mlekFkAk#6K&){{{zQEalG;3NU2u1`4?GmShdb2W=PjZIO9YOs-?Szj5lJdOT@ zqiSj4&@ZoAbhDgj{*8{5r-cmKhNBid?%(vuPtv1sbY}J{cAdMCkr*uNSO`Zs)3PhS z6dr`%y5I`?iUp3V9-0wiPBoQg=F&yW^j1R8&?ks;ox78yN(r-Lc>u@C(+(3}4;!{9 z6Je)Q#CPGU2p)w1o(?HY{A6;G>>cEqLF};dnTFi6eU5l=j$kVQ^n~~d#DI{4(^0o9 zzsbb{9VpYZy4|`c-a=J?oPjPw+Z6RRuZ+wC3x&{5KF&&obr(r$`gq|tRpvlUn->yq z_lR9x4W+nqK1ZKgPDniugQL`G)R*Opau&51#XJ_0u)~@u0o8alY*Ew^iJ$$orbXKy zdbIyp**;n{a-|D~>YxUV%B!J!K%exKtCap&8m}H z>~U8TwXy!^6Na(Q%zaggCQ*CI(XH~v28yswN29Z9%rqT$zz~(jfNi?=FcGefMm%sc zP-1jqI5@V)-vD(Y1pynm1)w2`H;}%LkW!PIl>38~YuJ9g8c5~G*C!0Ur*9Gxumy%8fTVaGR;&UJ^jn$ut9udCfr5 z)-k+&yxCNSTEuu;#t~@gC00UO4!V7}De)~Omx5KfKgAhR{}dc`=O&GQKj=(nkHE}! zPbkG^=Jf2jTMNK8i$trxR_6!Q6)@@3$1^uur^f;397NL)JKxN?0LP>(&xaI_q%)ai zY8lte3Bq3Z=7<1^><=AX-XHAU&V=ACcblDcOA~*a+smN*;53$U^Pr$}mrzlgtca&I z9Ou2joptv5i(<4DPMiPt4Vm-Cp^le&Hw_6%ml~DV% z#FRc_zOlG@B0%i=KxwDx$Ezm(58&#wgJ4VU6J*HKo;#x%z;suS55ZA>Ip`VnQj?fK zeU3QR0&z3_-mD7%$l1|!BJe>W(P2txig`wBmIos=bc7nfY_}4#hPQ z%UK43uMABP8{~U8z08myn;w{Zn<~Q74?u_&b#q)zv^{@@E`qywm#}Wt#PUV_D+u%N zX&A-9IyR9P$v9d=37xt9?gW|^#0iEB`N+qc@_fcC$}2G1vfQ+wP?39{;t$wqjZ`E% zXICN#0~w>99zGn1U(sw@rY>2xJ74xTo&FO=$azikW`Vn17kh?MI%J9bffm`R1UPKi zN!P*iSWi5rVv}u!JLI0_!2|eQCQVr5YNjzy_8GRNNk(IaK{Vgat&=p=<^Oq&(nP81 zqATbhlm~clfi~7({ao3{h)n1GVuHvLn)MSL)q=HI9Y#BxTzuMpen}PhJ*(A+<-TbI zqA<-FIh1RJoQ{GcQ|U%t(dq@fhClD)ty+aag`K3B+T%hqrK}_j(jUp(5pEure1K6FO zfmrgfR(b_qkRuL01S&xyb8PEOwLyEc;uYDs@o=oyyUv9lK~vbN-kDba+pOaFf5vUp z^E`SJO}8zL==mK=odv9|_;Lc9^&)Hi^thp9+)w5S=1RKy7YTXrK>}EIquvA;w>Aqm zmd%&20NKWvd8tbVeJ}U&A!J(|oXFOKcD7=sln%(0{M4BwSGpw`UXUfeWyPD5_bIv~ z&HPfLqppd&o@bNbBuT(4(%}Qh=(Q;?l}Bq5tbHJgSwkr`a9sfidzL7JD=_G_Bgs0^ z)=j9xmq-|h_alm>%&g%k>JC4H6~HcBGY@?P9x?>k*UO=(IG`_>1mCO!xjUV=b|*8x z(i_0hnIOg35fFLH9D&D8-P1 zqt=-sOIuoZ&kJnJKvtxtENBBTG&agvFth9lt%M57 ziJ&k-Lh{1anM0dABXYY0RyZDRM*%)C&x2L#O>#10`jIyw+gn3w+IM%8IFb|-gOj?- zcqCB!-Lzrucb5Ta=XNTPz>_$@<@vi0o>@Z<0j%#60b~oOkD*~foKYXDKX|ULlM&idq++_=GABIndePrc+$bc<|8-1>A%MOIs+mXvNg7I>R={lu)LGGZ)bm>sHV6lP z-d|?~KW16he^3%NtcfPr)Ao!RqFbR~;qYvrKo(O0arWK}TI_<1R+;CP*dP6kaHTOX zhsHe3B}fr{{PAWhg?I@ttfb)J`UBgBNkx5qwgSjcyE+wA86QxCd2~l&ah7x;bLT*h z{jCKcw~rw=ZJUCb;?Lhc5ob4-0_r5RgGH~6r@?DF^!$r=+6Wfp#wZ=}NKXDfca8l+bej#m~qP0>*49VRgE@I<@h2rf@hh7H@JHZEb(j`E_WcWcGyUEr&Zk0U5eQ&c98t#`nB@rbWCQ3k zWy`FAS#TOVcLptFy0VMp$ADdVq|ULuQ`?H3pU#z!en%4EdXLfR(dmQ~vb4&`nh`)w z#4@06qsVDu=E21&hQ_n`&{jroS*IaWe&#xwX9j5p*r&xiQE<6H#15MZx7{spY8sc6 zVu6#Yz(GclyNQ>QvSxgz)u&iTRu_490k#T(WB^}D)Yd{)I@dvp=@S?Zju(^%fhHIm z&>aCUSyJl`V+dUX#OY~*Odsf2@OEA6(M%d2R4@bfb)}9wBiZwO7z@HKB%k~PPizI+ zfo-YnRO|LZ-Q9#zJ*GXTxTxZRm1XULcnFTT1}AmK7OtBJRD_@bv9fmTsd-G^ounIW zncd`4*WM#;WA_6^?JgTY}no+*XezLWT5QdUF#c>*XWXn`asfHJvl;QcVy?ao-Cr`DBl!E`?P~s`B)S)Qhj2< zbBcx>QDsdZDeky5DAsHBlHfTJ(pMnLiaXOF$|OJyBzn~&L1;=~JTQ)s%MVDjEfEs2 z^EH59{{{>`?=j;dor_q7E>p^lM+NAnBTggT-zzEd=1F5&v^lftXH;0 zS3IUj=9hq4lJz49(?#qe_yJz9TX;W2#dfMK3j%da>78WKXSC`!Fw^cxobBrSJk+(y z3^ZPn|1E^!C}$$p$}qDmGQ`97c&DT&$kplk&XA-8iGJ;>zC}N>p&J*hZ$i?{$=a5N zb%`6_>F80{--@8A4)TP@KRQ6ZQ4?mQhRnFXl{883+P}wncya33%JGmCOPOro?3igZ zMFE@pJg-G+-bv^*=^s9C5TD1&yUj9}^?ChXc5KomP-8*4HPg@=JW!DN1kz6zC|7xH z*b9nc^b0BenHzI5h|j+fu)fD59olA{3X2Qv(;}n`z|+r5(bm5V*0=Ycb4#+(y&SF1 z;snu`6W&*Hd(0Rho~2zZ(V=tXt=e#asirE(EHbA!aXvsGLs;%Yo}`&}0y;h1<;x3h zdk=z$|j3{gqU|-&M$DT8{)YOKspS{) z1w;1{D?ErE01)9c(oX}@-z!@x+;9==KqOebA)_;X|ISTROzKU1FYuzZY)MM5FWx++ z9SoPIX$P(9qK8Ud-;K$%O5Ef`O#FUMU+eXkiI~)MJX?U1u?P16!O4H&>Zxv`)Ct3X%l)xq~9jwte@XS ztPF6)e>72Xni`^9^6Yp?x{Zw5)CeIFgux=&93lyBj<&eE8b_ zW?F$EK1XMH+Y@UOO*r#}#JIGr2_=70@OIo}0i*z_=WVQPCLYZZqL8QU7=mycfmZy=~LECfK9^<~D0qZLg z=he!nImg5r2Z=jY;JVCcACL~JQrsEhM}CD=m%}d7V14_<186z$aJg{393Z1RLUi#= zdyy)hZVO!T2ZGXX4^KVgzj08#&!r_sXJDmKRk;Ua(UD z34ezOnv>WZe`E3Z0l{*152jRo-!+zF`vL3e?Yn9zflm$H9@v(&K$=mv*?^8>H*P0h zpNX11OES)O`-Aj}V;&h-1J52+5FtwvBDiz%zzA&BUVHeMQA{$`M1DwAJZ!OKKB0 zoZi|<0}4;=X6+v#H=D<-&@!S|Z^BVjC@YnCpkXLOGgEC>&)<+fy=sqb;T4IGdekeU zs8)RgF*9vVyCy+kzNXs78WFrn*Qj^49H{_O$N*5jQ4gi`CMCd=8Q)!6@ed{x`7RR* z-{1nGxoVSIW*T0@XsH6>^ZR3k3l$Km2Js6eobZg;4FtB2Wg)%T;hVcx_vJOcg)=>< zCKU-T2V6Y_mAb!U?h2|#u@Acd1OYr7s9xLa@}!!j7TnN6hiV2%41y}hKruUH89!Yh zbtU>PQ%LH%=`K?P^h0D|c#D@Jtj|T{YYCXD@y-zUQ5zkzS_GtoX{Q~whAk=$q?~uM z?Jj5Q+^9z;M({UK$G>kpxTf-CEs%O9(D9FQpkDKeV<{bieCI+k17;>V&Y@|zop_*( zjM#8t02zppqj>KEyt?UmZ4y>1crnzC{&+;A5u+**oh9m6r9e#Y1fVVw zLsx5NjKMjH=213h)h8u6>03-C!w%@9@&@fLjWg;q#-k-8CVuvC#`b81+`R9SaL@MF z?>LZk*rtgB&@8Uo%OMLZV+s{VWNRRmB8-ZkzGT zZXEpLEqyNHu2m67*qgJ_G&Zw9@HE2#t->tuK?LnrCr_y%9$)gAx%(|$eJ`H33!kJ) z)UF`0<4-Kvxt*C~^LYruo^6W<!4i6SI1i_2Ce~rF*>`#fMoI%nGFAy)fUaNE@<^>(#)aaS)4sjY>@ zl(Zlt5CAI=jBU~d6IKFFYzxr>S0+$Y!SfWWYSk@`N7Ub#-1y}+ICA&K-hq8@8hzncsOrJ-WT zB=yVR72*^H+-hyc`a{5LObcsf+DtK_q_7QA+5aKU4aE(7@O&`KT=Hhkw^gPWjVx`! zjagfdgHJ~;(Ply;~!IQnm zKyB{OG;by&d~QpKP62u*tBgG6ymLMFBRi&R%LDhk|Hx7{)GRBPiX`6Fr}x1=!%4EB zWj&jSGk|7XQs*p!i7?h(ckI^@hyL%)BpMjf@+2>&6UB!`*?6^nifpH zkT0S`4Fs|z(6Q@7?n_?D%%MOK}Li;h}Q`iFS|tR!J0pa!7% zZil0Oqb0Qi$H2@MR=RwoVpU{fg219Z@l7nc;4{L!RD1vCgZ>p(%(GQw?!4LMN~c((pKYs|)SKF2mxuW7%MANuMIHBe zNz-Kc63?|Tt`Mje%U&au8&#&BtOkk=i7=ISyYkfKuS$(dKk5W1yp&56`8>N!4P>kL zZsI=C8URs3-tw^(aa_e1eXHC=E|D8Vnt6BC=+%TwwN8V-c5eEDjw@B?n+&#Rl$b)k z$XO)BRClSF2k1KgrxiHKTChz_{KSx7Lo3~ znLcdZ8gD?Ko>deIsP$_#bmM4DZ#6R_FAytGTzC9Y4pK{Hydrb=-X-~TJ?P;@o*oEX zo4NY5OO&6e`L2c{K$NK%OXdgE4vf7+R(&~x_kS~E&C%iwtH@3 zR6{G7b45e8W#{+;?DB{mz<^_VAyeT~9YoH+0HMR@2;A3@+Yf3dT{;ZPWm3Zw2rhJW zcCYvW0UIei*y3O8e0AZs0^}^H9w02Yc*(+I4Bvk~8?{-yanNk|MZnnHZPJ37u3*Bbe z7MO$e5r1ub1R={yB@^4iqydl@>EL#k`nGjqxo6F9DD`|)9l$^H%D{X#9DqlLV8deY zX|O(#rU2Kh_!E)7F8Iw;D}p3*fqyKwED1*S`_9Sdupt~$)6ED>3(O2>N-?{VwkeL$ ztGy`7@A-+MIpgcozX(qjaPgd$*#l>_4L(m%g#)Np37R=r5Kl?kYcri+GZKpl2fhL) zH|6O1iBhA{xaOLBby@MDQpgN7St^*f4nI!`!a2taZ{M&oaLKl#TMiRKO7)B=4 z^zL~eOQESbw!O7k6m-x!v8wa#a_MDl(i;3Xe}+9RLxT^ZQ=M$|8JpR@h!3q4Q=3s+ z1bcAfXEdtB^U}f{V!}`n+rb(ys`$}MX?F1ZuxS+MnN=7yUeZD;biou@69>FKKr~4K0rwfecxe|kC<%<)u({e7eS?^_nf62a=+!pMP}3+5yhkB(SJ)qKDVLAR znHU>Z`X=NqKGoB0D4gmaMFZ4j=bGjjk=LK1OOXeHQ7pq(Uh{kV24xMnyXhc$8Z#Jj z!JZh+w9NQs#Z3R$vAf9YohfQqk435LAhDASxBsdS>(iGq)5$+Y3>F*oRitM|-lBP9 z(CeC8w{V0H4Ws!dB<5g%&<%B?Zi=g<&ZQ1nr}uDRp4^DfBg6^c68JfAS%7-`s60yG z_v6L(tDJvBwx9{*4-~gFMsbv0_xz5u;2)!jK7{5^xgRfr-O?bjsJr0q%ox~=tPd<@ zRu+Ci2dUBP2$CG?J8*Ny!QebxH#U{^bX1<7z|q0D`|esr6lqWEO>`3?H$C*!8IkY2qhxksZ2n4E1xPSBVYf7?%~ z4&4gS{zFk?K*#ppxPmaStuw$4zY4~ywHa8&l;~O0*Oobpi#pi2OgR!?FEGG9u@n4g zKmgk!PY`a&@7&nXq~xmk*EmqcFV~8OPtt*Al`4P^mv8xBfu~)l%0d;^%Q{)q*P=LH z?azpL|AX=|2GX%l1EE%#Mc8MZC>V+j6jH+{PlM(GVntiY<*NfvqBQ1SM4|T*p6wHY z+Q=G0y+7czzlQOK|+?&JyQNWrM+bv$$3k~MU0Kw-hl(7;NPbNP-@B0EJaxQsQ z@7C8IRozI|OAr?cfnl2&c&8ms+Zglq;RB0tRr9hE7f~~vdVoym{_Z08tWhLXJReIt zP!xXE>YE0~wa`#y!aHPBW^Nb$Wg)0drg@p<4d}&oSq+QlXFWmQD1A|7Z$Ql1ZFPY zEQAKp)nr$eHr3%(h(+&Rp75d14XMu7H&#)@D|C^58X zF~%A0J{nj1ey&WOVgnp9t^7lX`Dlgn`>x%{(`H!1lyKxS912C<3M~JQPPa^7{Nwgk z|4jQUR_fnn&Q_PwvP6~`RVw;tm4VW2C9WnsS_auwnVmnfajbJ6KX8ir&DsJ5)@`gj?ZWC_Rr)74;V?v zd=O|RukmWJ#j!g*MVRS0&fJ)h=5z~saz*qBpf=AvF`)GfvkPfkS z5F2M{WH63V7P)%fjJu~+BvHkr;aslwVGGxi2!?eS|fnCF+B1eL*EZoL9IPVx1)%PV=qK+Fqk(5+!M(Z_{jm8N4Cvk-2Wvgsw4C>uh_ifm?l9EVu?V zmoV?Cif~^QL(F}XW+B}MK2}OVV(>z5R?45^GbS&F%wO_$_I$qet&b=Yc=tiu8Hqz4 zkE5az%HgFbHS{;13V9I;;vktH9JVN+V3D6z51d#^t2@V^<06ukC|M3PiH(q&?m>z8 z(n8C>t}jV!@jmNvdr?Cfm*ItDf73P{v%1aFY*M-;_bGp{V2#-E#tTOdeRX8oFr~<> z!sgHa;75{AZPGMl%=6r^9+*bMt-=*1=|SmqQi+Poh>?uPESB5;l*gA8 z@*?q{ZRf)DJcA-|0LN_iaoAyS8ye4_2n}~qVQ~=)m$GF$Z;KKF3(Q*<<`i_ zgIk&R82r!=M?vxw{*$@ReH&aICVC@S_Z~X6Dbk;z`88{xiF%`_AD#GpoX>jveM_Ht zDySyQW70m~oUb_P#tiF!N4werdWHdvE>cit1-di+_ZOl_FPo*ag>5%yV)6v%;xcWG z*z6igzh8zA`f8?h#H}{I5|GMHlIl8X{WbxdQoZXKR(kFHlwI{BgWG1he-wFvO?^*k z(G`e6dO%C3CLoo9<}6izqUnIWDY&4U!lgs=)lQC`%Dp~`g+!kka6csc&idme;>avV zSJ0=kHI3K;hJ0q!pCdPAbii(N?r$mArpzeU-Pj*K2X`lgy8u@| zF@T1hiU`De6$_cZN=PK?#b<`VYSsEwD=)VyYb#JGC)j)3XTYve?5K)MR{=Iz zM*?S^TnDkvB+R1+#2X%oX8YFrey$um0i(VvbGb{i(H@5x$J^;*XjFW}(8{O}ia+yw zz#e}Yh2La7J&f8<=je*!k)aQzc$`Bx|7Uj#0kgk}gt)szD1q>M!X&a0kDieXTL#^iZ5D z9o+KHUDIvMadkXsHvHwFdO5C{kn%O@+YsBY@w8r^!q;-)2|c;+>qB&i>}#jMUDUL7 zqt^2-S#Uc5wD$uF9$2iwc`;huCC#`cq`nOYyL;18Eo1NXFA^Q&TOO~s%%c276vEbx3CQ4@XAcXvN zU24S1m$$fBsy8*i>tgZJ3?kH%udN>R<$1v6I~~vSv-|+$eV;$gj~uV&ih2^YSXy*= zrZh^)*#Cwo4%(R8^Ra~Z_hk{bEMDY_fl1L@$=tXg&W7IPL9eZ@%$z@ZBU9m*Us)Hi z1h37ckiXk!hnI^jIoe;!tRroQXOtlYM3QkD;70uVlW;cPw)h7a`@4m) zpI}8IukA->S#!3&{AzI3X}Ry}sBhMLYC$OG$J+bfwb1q|+42Pki}*Nf2Km=Q&ANJk z>WJK^l~GO7x6phf_n5afcc4f67`lBng1fC}))iIelB#>hnvNNny%zCn)HX=}=q}~F zW+1LV1aJFPNJ^7Eyyjfcr^-_q-@goRy!!PnBzAT9h9(YEB~zTt^W)~_wV5}qac!)% z-IRc&o94hx+aGLGMJo1chr0T*$KaMS$>arrmB@usK8*aOTkhJ14*6Dijn`YuSe-7@ zeg=}Se;>(SHla%8FaIq6u3sHzxaWZfs`_$@Ut&wX3gUyTB3FM;Bmyj58s9IOCE`k7 zRMJ{PB-l+PHWTxbLm3{g%~XX8VVN z_Wr18PIIBiYe&A;k#cZNyMtjx7t0sI)?mAYBOZ7Gid2~jMA&p(9~TY!;srkH%$Th6 zd_0}3XZcKXlt<1kH)arx`|ForA^!QIXhfz}_?40ELmt>*cdPHH)_6?du&GQV2Vr*h zr9^NfbT_plNSiyzD?5J>OBfK!Px9&X{|TxZy2C%uQJIvHHf?<1c?h=9tV=k<0G!y;ZWi|eaoxOcpw&;O+&ZW%HMB()PdCA|A zE#1F>pUE5=`Z&{gJ*=zad*V&-P)$pJ(t?V6Fx365bN_?YF9*j>mTa;iD|H~a4)45H z;#uEZdC1HIy6Mt+p(WZz>Fi6QhgK7pQ3A6HFjP=hS@rw&X))M^%1@-kLdjl(ny{E+ zy-Kq@-p!9Mkq7(BRBZfyNCvsOc$^N_{SMh+uhBJOqubp*-9j9HQ0L#t-lH3M@qQ(hqBqExx1PLvjMb^3kGGwiMV!t# z9|8%!QLaIvi|5&fM6(^%Maj}``I21kL#2`~CB7XnAYKtse8}6y7Q%Id?2hwLH#Dk! zbtr&pd2EvY-C6Yd$4cHat`cU-!CA*kere54r$>zba4olEFFh+e+LM)5aZ~bXN_PU1L`t4Pl&^Ycwn3BUA5->$JV7`M9i;$^;%hsjVQ z`uKt_u&bYyeN;~+1!NIR`9*r~nRVUE-=B#NCfGi0QkJZ!d36Uy#jz4(p1t*a7JGB& zj+(_CHcOks<2s$!3gwC4+#Wa`L&h{O5UUquIUfL?VifujuNuS7c2PwkE}rF=YLRDk zEsVYyVk$I{LBg7Sb5(UsQLzsh{O^EgSC!vpQ5df5q0anHrmzv$sGKic+x&_Zs>y2V zSMqPF?j}9!szlqQ-;g6XKg(D1G4DN5IH3gvHJW)?4SX+8>~QjZ62yk+Hyg0JO}OcM zX^sI~!~Oiy{B1_}>WRcJ~JZ_73>${#bXFl}b&=UkGA|tpIn`M1M7J$wcoT zCOSdY+>@Q>u}oOMY7LloI-xMHkCrV#XH0(w(Q--?OpePewhRNhn;ws56Z_$3n=F0K zQRKDFbe6L|edW3BJI}H8BS6M^`gKWRKJrCfp)I(of98yc=okc4<<;M6Oht1NoyEHe(3T&R6(3+fqlQGsL{+aOkf`r1e?>c%he07l&Y;`vj| zZoX-b%r$IoR9`_n9JOjT&9UVunfbkVD&)Ry!nouX>!x|u=X<;`zv_#)xam_L5u;bw z`5H`vPRvi>+t4!1k(u5k;RV~ahZ3SAyfdfY<-+Bf&e7NW@zxl`y>O16KV&R3VYT&1 zsWai;Ss|Qn~aT(ipgYIJ2{Ns3mj$% z4(k`zFi(#yD&-;;mWIN~f>syUWlqb3{)J1Qq+M+KPhYQ1dk6Ci zp(Nr&^_i$_R>>WLQz+7bd4gPa?_H$u*Tl_xXpUs z_0$-A@r!j#&wbFjnA=5XoeRjbLPmi1M$f?YQUvK-lg&p?iSQAp)rPIRX9Pqw%O|NY zsudxBScoVVfB(yHI$p$z@VWm)BXdl)uI6>5##bL1r>p@j;0jVS8ZVDq@CW{U8ZF8{ zv#jQ%o40ZpnaF@;?o7L5m=`k=$eHKN&??!X(F=MJnyA6u@(3BYhxR z=uyOsY##+LVn>ufH-mh#4$=#1BTS@%+yN7G!^vEc$@d^NddJefizXwxYw|Hq$0hd# zH}Mmy==>LD-Va5;j?7Zbz%8#t!RhA2re=(RY`IOFw7xJr-{?-_G^J+7baU?8^iq58 z%j_iLhKdyv(MiI6^chj_K2ZT^oDI1%XjztGp{9w<7gJ2(?ON@5#UYT`6Q&j{Hz4~n z)8oYV!;d6cMGd{#Yv4^AP|H2 zB;;+1M0@puY%QDtk}LJi;!W}CN?-mPj;uw`+5MgT!b3*+)2gM5EgY>@>Y=uAONoqE`uDanP z>cFF&vMNSxuGnC?-+Pmtwn zAF5P`Uw<}fkW9zSA}0Sx0~tSO0<4*153(&!GOk&EMBIpY7In^r`A%mk)uw&=I4MVd zR{-SILQE6zeg0r@(J>r6sG1K_9eI7dNHFtsc?4o1sEAdt!R$ujE9;*H;z?5>gDe-P zv+caUPqQO18|sBAb%NJqC~rpM#&AAe#o71!_H3}8n7S(on}0B$cPB+nqG z8F2-B=clqjB29ZMG#?}zLSVqg%DTKaeJHNE8;Q(Fe#MMs0cPO1VKm^YIz#_!|J&-x z#w#sWK~C=vdkFYRSMj=NIhr%XdPl8d^St{vdr;+@$}_^Pr4_R3Oy&<(A3x(GB!6UgR1!HLpTbpAi zTACB_Qahe%O=dPwG4C02pzwK{_OSH}gM31DnhRHw{Yu2xeZv~+ua_coIPoDNM5LtP zd~&Agb}pJ!h^2HaPXG9M1B2UBAhtH>7PAE=PbmRH?HKEbqe$PyN=VdMwh0>tbc>68 z2|P2gyRDb$ntGMX>3)8>^_dH!>_qMDN5E80pLz_`-5=K%p8yp@T|w!ZP?apzRRtbs-k7k3ofm^-C!Y@?|_?ZP<#+LMC6B=L>E4PBQUW#l}OwAHx}BCb1jZuTNa z_wbgqDO5PO6*eQWt9`G~zWtsg-*N}#6=ix2AG`8;U~FT2KKd+vbmkD}!6ZUzwQ2r} zJ+n!2d}~^orb^e@K66ZiXEI{<$bu^7yBzi|JFv?$TboCgA$gY%p7_~#Tnl~MJ}w); z(H3?xX6w*bww@k0B_C`bN!C7FNwNj%0@Y~oov{k?lVI}2*h4d7yWO8W7B7cKJkD@O zJQ21a7NABZ=`zZ#<%%?53d!Pr`Fm=Uvz?}?M%Na)Q{t#hn5(L~4(~D#aC&%O$K`0x zC%?#Y#PijbBCjMP0}Rw3Jq_R1W~JnasP;*;u0AG=OU|EA!7YT}cA;OsGAk#O33KVf z=ZjbRGGy$3KJS+Yh0Qk8h=WhO#%XuWhscu6qRn`VWk*BZ!}l4KuQ8=E0*3M?TOIZ6 zwI(WZo19tZm@M4( zW*UeGdS}dVB6VHb48_Uu3DN|QYivZM9LpgTsicUY`ooxl`RRWs|6(XT?Gq~5Q+ah` z^u;5mk`DZkV(rR@(nH@V?UhUZZS;<~VK*V%ReHCmF12_wd}xorq5L5hZShp;7PMTs z8x87nJ*Lbi?YG!lLi4VHar}#~YM3y2N^y0^GQ1MZFW+L= zc??WCt@MxTclXxt-JiKp3`@(+E!)u(lU`GGD5^J#RPgM_jVC*f!zL+6l%}+ zP4{+L@`_tzg5DvuFLhtEU0 z$f5GM+WCY-{74?`?#uGA&LeC3o(W6}s8K)~4>JK~b^pc@zCJ^YnGsK7;n=r7)|lw< zM0TVa+Q!dI+(LHP6IJIE72{r#On1r5W!a44yzwL7K~-P2b&Y2p91DK{S(Me0Ti(d? zww{9Ks2r#+7>s?KvIW#Ek$fE&&8X<|W8?-VZ%uQ7AKD6#N16PoMcvcwzo#2Y?>N{! zy_S^2r?I$Qju;KVaINmYV8sxun$-jlj#w)lX+dd>o$AW)P%xh#2SO02vjCM!J^l9d6q%m5UKVGduI3_9rJdV6TtN|o6UoY3 zRD^o=&qqYVss7x0J=V|pX68!M zra=0q&4M4xc%%$o{8td%I=@XQW1a=(tT+K|j!xw#(vO(Nj;M()K%bbjYK(XrEk%Rl ztddS+;sbA|9N(^^p1P(-y|nnoKqG9#p0YPy(wGYwG#_6Qh*d0pYD<$G)ur5-yoSjO zBmvMPw9J@r|GV1eURVWf3dz3b>pX6+bOk?5;i+-%KgBS1Kej`s&gZfD;qd)C(hD7p zLUA1z@hcJIz*pG(@pC=Oe@vOc!4J|A_|OloetWC*zNzMqO`yt3WC=N3=+G^yL#0#D z`8eM-E?E#rf}2+pog;u?JIJToxlRL7t*E`yMbR~3@Tt&=0A|>91%3j23ixP;`4t$A?B57)f$A z=Ufs=`TQ1Pw#DP}tKHII?7toUg7dPR@q%(7_Q<~s)Em) z3p`&NHRUcBq9kc#=2LY(VQ}Zc%9~B@cQHVK!A1=Ums{*N*9@_?0CsMKPX6o6bXY@i& zC}}jQm%VDZN}rV1kY|><$9?>Qa`fz3!m7%-{rr%u;5iGF0gMk^5ao`G@fc{xU$FJS z*_|6k>QKG%3NH^0F~h;jLOiE&@wzz;s9)!TW3Sz0=-=672mYO|-$q^2e(HV&vu$=TD2s(pXl|TQ!RF@F*?ZyO`2adVM7FY!m#x@T;0qEEV z*ju0IE(=+psvg~9-q7klQhkm@F-fYg7F_V2{6Kq;7bylTtNzB~9= z9rc#qnU7uUG@+L%Cfio`<%!nAE9U?xqVBy!Z>jQ)#;_wrTl?{kE2!6RYK-nB3AZ@_ z8^5~RUb8)^uM)cyy3Tyu{Fg92al3*}BCaJu!M;z}I0C}^I;SJwE+z!d2{+*cmG-eG zA80E{%yD@*)4TV;$T~EUe_9E4v2wHC(wU%CcG2L&EC*53S04=)3J4eJ$XZtO5?LU_ z&GRVP@4Fb`#;c>)kset=2DMJ}k$LT^XB#pLkv-emT0jD6mKgVxW_)jDr?AoG0uYOM- z>iyT3kTTfKad0Qfqlqr6f2@!fYHWdk3S7dtn?V0ZmPDJm9B48dv+?Jjk0A6MJ1MwL z-pkWMzRqcxQd*UCG%`=61L?0^r4oK9j#HgvG@nyB{2L39=eA`QjxNYl-2iH`5JWrp zzE;o1LTJlBcwVfidEe`}vau?3v8o$TYR!-S*N$lTA+<+3HVxMQijh2(xx(ppcsKTN zIY-yY95Eo2ID=Vyhp-bbNtZd4Pm@f*WOLx@@0*S7^)SJl0BjKY;`i~7@asgQJD2xP zhSg&O+93xx5`C6VC`l{_024pivvrL7S})ypBi}G(P{v*ZEsOR7RL_KrUzW|32Hb}X z<5o!D&{AD9iM@{8ul+pAU85T4_8doZTW`MApow7+hP&yDleC|Y-~;zXno{HVOQ0hH zwPYsO}VS`bnP<{hexP5@qn{j9jS;i|50bmup7bw|@0aa|5Qo0hp6mno!d{%&5e&!(%T0#)8ixK~|RZ7A4i0kn|vX4K*#- zMZixgk3} zi_|Xw+vai#UsQj?QQLU5KWrqF_8JRvkgjL*z5nS-b?ma(Gj zcjlj$!28xJG2XJ77rlER6YxRi0$@YW^xh}WHrs0Ti?(IltU4#_>V|C}!D`t_Sh&-u zNZS9>_}=ALkbS~J$qQchV0Yb9x~$5dBv_=Wr2w?Lw;iiSi_Q*Rg+9j!*cauk>qDG= z&;B_|S(4FSsQ^HG$9rMH$?z;m1@9SCI5OvdT%tqctFPs(gjAoW8taHlKHl=Hi^F#xZ6|Q%hzO zhUO0?*8XkD#H>hUi`rQ_?G{5oK=yVW9qn-0*K}>vc+`TzVn_*!rw@y|<5F75{yeYV zDJeg`;(_LOLGfrCGg4u%SsY_hCi;%)-iS(HA7N`I5TOpx`jB1PgV2%CtFjw&bdh42PXKy!#z3pmqVg1R!iz2eU|L;=xeZ|>)uWN+?#2IdRqs)L>wE$cN((kt|#a0uW212j-2l~?uP>` zwemtF?7BFD6+lF&!ClQid3~d69pvzR;|yb=uOu@wC?4@i#(#bi(w^=~bX#Tk>K2C{ z7j7bRF75Wsr=mWWqr|@}<(&ADB8_VF0)w~7{F6;f z(xbUi9e}JcqXlOahJ3Q{(*eS>E%yG6ZINLEbkhDdRwrp+;*W9^-$x#VcMNwwnYJDr zotDL~P@aYsRC@V~vZ%~MoU(mbh2t~ed~n*QOwNG0skVJp|DjGlDA7cfq#)y}EMCoHZK39B2*xlytP_hv&ZjK9->GpIJX!P*mN))i3PC?Z`h0#$o`L}_TZMJzfofDVu zAvIkoia3xx%b>PacJPz1w<^(a`MmQro3ZoW{NFAp-d2KY9~)$I83vhe8PJ!Vb>dE%UOOwORh~ENuU9rf~s&Ay>O# zlW6s5jY^KH9e;gd_0C(TA17Z6g)x&%X|0u!-~4MIT;?wW`XV&&oFc*Po3h{c{(m2q z<=tVrr6<+NFC`3Gpk+}d(HfxCmFDtcg9ySc-cMDk&i3ntGO1ks;20`;M+vMW#81m) z3&iM(OfpvtJ>S2H78jbmNmKUNy^5z?_yQM8?Ku ze{7-$Y-&x&TVlmsyOCN}P2GfAv~flHV8M*|Zc@PwU26`wy00ps0)MV03+&HD^<7U{ z5&CBAkd;reZzr|k5Ji$^8UmoIf;UtpD|OV2Ww=4oM0w;u|ICO%f?CIq-CSN^&`o2X z@K0(QNm0Bisslfa{o|FjvsX0Tck@~BAVM56<~Bz7xL;g1Xmk2da+JPGA99x;l=|%g z5z!eQhkfs}KdI4|FiPeH?&&nq>r7RuIVPm@bs*bK@$)@(57{tl9ILb2fp^%sH{56v zFL*&Ew90@h`rVp8|GB5*ydonbVXeE4kYz?q|7{{%VMtHvWw^p@!qPjZ!?(#HXS9w? zxzcSM+h|a`0!UviDt45;>iRLUqgYPiONUeIveuIiD-Cbc1X0RzKDH+OOXv4*mqb@N zA5spJ*?Kwpj8I&RdGC;Ds@>1AdGpw~Pnl!yH-Z`+{|+fsljXomp%fje;8NXijBzAQ zN2@GHP#+bJ9-0;Ni@7rViSkWB`3PUq(i6*xP|D|K} zs1Wf>#8j-}c!2~vjeQg&7W-PX$o3vNt}76eYPnuANniD}7MxRLfrB#Fpvbe45;Cxs zlRVDQ9O_C0%tgNRw)4E$x)hK$3~bJVx~A!!G4f3ofF28Ot=y(tDjzg*$jb2REWe@| z8WQzhbKxkcB=Lcen#CE0!vO8ep>>1AU9|_L3A#4k?kl(aJ+~ z871dKQ=;m_^2V~_VO7?9eU0K5z8Jj6P!I&5ZJ4QvV~h(07cQIg3=S-N7Kd;f>1;V zXlxGb5Gj>cqnQtYL;rB&4BuCbeQN6Cfw;=`MXEIiT(7Qs;$FKQ`=%$mpPf=&z^@{& zqj>%k6QyxaifA~U_X1x^;NP_$%_ZNR(+l0+AcE{fq93A3z)3Fs=H7nd*o~=YQzSrR z>Jl0jPK5fD+S!2SPk?P^?ZUiByto0t;eWE@OXiQIKkABkSauvFg3vy9&65eSrC#jQ=as0Ppihml5} z=aW=822WfYsiOqV@PdfgzFL-W-N1MN)b@TTxcUB`OrzY(Ju<^;feI1iOlBl3(l9S* z4N;N5`*j0_VW6H#jHxxPdX__Sues6Z0@7w0Ed>Z|xMwUvv``$aoKfRW?T9Ka%?tabKSG$(9RU}?3YE#B@>E7`-5%M38=tN+XtefKNgl3$6rnbVGLhhDS-bwI_B-tuu#1|X^?v)^QE;~G_4)X}%K!jGIbz1! z2Hl|Y*1Z95rJv6|q8Z(-qNUBl!k1J)*+^=k#KmAk|F3q=?loLl+B?2M**e5IP>E8`Y9S!zuQ{|BdM&Db1tIEQRr7+`P^Y&?$+1Q3aG-Rc}4VA@(#%a~DmwCuyAZ1dZBJ zU8LtWxM(sZw6a3dS$ba?s2tn6dhFrCC3ufHmmB6xx@#g(Q*o&xA~z`z`y}w3iYn( zlWC&y*4J4H$9b&ZGYhvaP+qWj>#zJ}iz#LqS+>o+!2_)SLZDWHm$39qD9bv@q7aYw zY={^eGZ>P1SJ~3y`{6|fSpAdQ7ZZrXNUhJk z%X)!0{?rYL(UIuo=?ynPE*CYQN*~)ijWt+gt#ZJJ+V>~8@>RK=-mnl;`aW)3cda(q zixeut(f3^OP(+sNj$;np^(0bR#Mpd=Lp%PK`(E;jKvhFRBq-5SY>e@r%7W1Hm)Asw zt@e`*V7*>EXLf(zRvD_RJ|3*W8aNYQQU913YdnclF?Mh&!E0luFXL3$ zvcyEFLgeL`s?dWf~Q+8U>#`@U)&ZCd6C zGDDUxz;w@~O9@7bi!`4+j`DqIcjscAOUhtj%KCi(YS0?|EFa=GXcEZBPU!{luGteB zIOBa3SF|$K+b{ZC+ru&qq}ul31uKQ3We1)}0Pz#zZ^oMU`-n)K=e(MfKdgAc?OUU3 zt%12N_zv4o56c9`(3GKjtIFqYm)$`c@j<2C{xlRNK9Bu)Z3|l-u5I&CBS~@Xh4x!C zA{I&hVzG}60k=&@DF|ktU+mVnhrU0q^_;g^!aCsdfsn=FhcDt)&u7}5oR#=Rf%B?B zn%24Fhh7Fu-(6!~I0y$5o$s5A4JB}<^n5~({hEwPBbPtxX8UAzaafFW88*2LgNxMX zldL`Acst09D~}k`e-Q`ckT5tShkICdogdDJo3|Kit#*bJ2EjIr-yp*E^K*SfMF5u& z+Ki|=%P;mUWBtBIjQC)9p=yeOMiAbCWhhE8sDYd|)CU9HZ< ze0c`XP$5)I&oVSf{QS}9dyv~(h-G@JPk(?-KsYk_$=xXD2L zcIp|Qt&4kP*hruEVMVL>_|VtOE}x+rH(t7JG4b`K@gKnvJgfPD^)1vp)So}9dhXznm zB{%}10@L7*i*MzMa!g+14uU&N%JlYIE2{9YG-(`&1eNS~L97_e6IVQ*CocjSTx|tK zZ?A+MEtBL2nFfzHJ;kFH$50;{aIBWVc-VEpneT+7iWBdlquv}Z5GS3HS<-qJ7k+k_ z!4)X#Wy}F3c9-X$6j-;-O}pGrF*Hr;qy+3m)*%K(Bebt4MKhQx=qB9!L$|T--P`Mh zK!cfzsBHar3DnM_2ZB>fdayX*phrjOf=6E36mD}=hPLdpRI|J``7~ChdyiI$V0m{= z+{Z-rXP+JN0~4&^u|#+>Ti?qJ#e1%d=On=BK{U)SxfE}rs%ulMgy~As>Tn1tOHk( zUgnI{3{u1-nLg_bFN-*8Bs$-mWmqhtqdjSVnF*>6lN0% zZ}(j9dSdoY76kGVX!=lP+*~Z!$FWw0Sx>7=gBw_{Qjxy6m}~2C9YbPt)COF(1@r@W zC`NjFVw0JHIM;Hf%RW-l08u|I4scxq8@^;G=!)iXlcaH+i6gOBp0$&cp#bgpW>Si$ zn+eKZjRlRRE)vuJqi3T==+elSnV>;Pf8Qy39KcKzv}#s39|5KJ4&xycOBb28rGzP-b|@ulHBD(I#Ee&wEvyIM?t%B%{|V zld)$>wI@+k0;=RC;(Xy}x;1DX9)pq*Gpx8L@6r4M}nJrHz%{4OH53 zwtu-%<}G?t+xK=EOTS6+bRNXgGgtZ4+gyCSd%(f=zQ4*)cP+{eA%IxJ18Yh3;`>G) zh{0r#!nK#aLtY7=F)9u!@8p18+p#kk8`Bq8=!hAR`>}zW6eqvRS2ilrovQc8IAdY{ zv_XQ81H&AC;+3^R42`Mjxh&IPHfXpt!%M){^&di&L*l;tWGsi5m|T5MK#3(B!D_xq zI|JQAqO4ux@|v`rT`|!7Q?=0y5;}$np@!2}V~#kp<2=J(&%g2bsC32Cf|K{yzw-s8 za1nHSNoY133z80=O2 zms(GHkl83S$$oIaRH}<`oli6(yAt0k!$w|NhqiWfYqwiNJovRwwnzbd zLl7XyX=}0zlEh1y&0;}Q^>ls@0S7#?eWWL$DYo~yo|{L3>Fv5}F(zcC4IeQ$satH3 zP5pWbo4ZQBu_j#7MBB#|%u6v@9%LW8qMm)Mp6u7cKC5B5YlNQA=fCl?f%!_b0N0b9;{$ECGVgmU&Oph$jSeq4XfyJ>G4zG9P}3AYNKQBTdg&*z}5n5040 z%3GHt2_y!3C^P@oq`UrJqQODQPzpe;_ul;BgO6ZO6yv5_b^L}RW6C&>H~tK^snhY} zs!I3zvt37^E{@w2zCi^N#!+IJSdNvPt28qFVsGa!+Q%NKkE$Hk_RUx^$!zkBEHYLX z3FI#1w=jdNbrE;Sp_RL3s;MnLTuJ0?TFxD&&BGNJBfx`hC|i&E%T&$NKPeGp6Q6Ih z`To1q z=nu@H_L=5{Y~%+P+I8)}o`ED0L|1Nq*EqOk$H$*mB9Q73$t5Y9?F8ns8aq) zxPLWtaVmIY34fIWiN)Mx)>u%?@rKU$0XyCQ$)HuJ9Fe+68;&4$^)!Iq?lj&~xB-I! zAgO0#Y@>r;c2)Y|Vbo{ZmTCm-V+#1DqF#I~sH%c^2_65(oIu(i*G-SPPn1Nlx0FL%{RrZ?itqgyeqI7?mdf*^*~WO6E#UjMcc(A!p2CNrpx?Hz z4Dq07>Ce~@3&Y*fm=(K9PQy6LP>_drYfMiJW^`*3C_Ms zJFQT)%$SX%St7*{sN71v4`{EwNO}pE{91Itl>bsKvUHBpoa`5V>j2tdujP`PXb&7f zU*fF&{#_1&)C|arU_)xt%)R@?j0?-(jXewf#>kJfz#b09(OgM+4PEWU{15XIe3k!w z{jI1m?1uACn8KF|lMhn(W}OxT%l=bkpqr!5MMMhkQi`o=_! zr5fKZlL4;)Uyonp02>oKvr9n|Z-Cv{JpR$!cTAmHbvTy+#@#K@)!5gV3pWN}sfwYe z;c*|@Qe3;1rSvMugh;5moqAp7yw3-Dm6O?WY+e=NrT5k&93y^cQH* z)YWX_JR2ROWx#q(FcHX9s!P;RAiIr);yn?}9C5~C zj-e@?I4&(3$GyvA)1{AHBdUPR*ijVhVg*flsxsLjby>8o4h>gf15V8UkX@}B`byCQ3p`?Bgih~TTl6j0SJkXlG`}J2>UVMGyQ_h0?(+} zsO#Uq0P%_L5fu=tNQ1yRF`5jw4p@f#CvZ0wd>nbeHw%WW^-GQxX+`zt)1 zC>L&A%Jj`NA!JUtu8a1m>s9;0QK5PE;yoUCbEpy9aOjqer$Zpdsu1k->Ob?nI+x6v z6Up3;pEgC41Y$Yd^YqboLK}iIt|8RuYncWSbED>PaYY7nctbrledV{-!vbMsPZBsU zqJ5)^)4Lx5FKd_ql@!<5)d-MMnx)-Kr!R)5114@@Y6%%{Nhs-Zwr>eKHt<-B4#S;B zH2)dM3lZir#13nABt2u`A-@J7%28=b87325ju-JNEqhpbn4sV-w^?~z2J`{I(-qAj zCR&elTqIzO@g7jLlU9xzQ8liFLqj7<1ejA`N?N)EiTN}rh*?c~AhCB}Nl^?r@bYcG zc~u}!n=KJ-J<6LP0Y-`m`jSk{jue)0u5h+Jh*tjR8qU(=%@mXSkT*RiLkr4+7KC-n z_%|LMWq=ZOx7mLmEWdx%rpsGggvy4z#8-3^FgR!rd0=ZwLT0_xNXP zbxib87*lx2ZbfamQE>FcsQOzo5UU2WJmPy$&G;TC;L$N1fB#(T^QRW`C~Wwe@-YJ1T2L>_Gg`T{A%R@ z72+4XJwfllwD$dt?_WC;^<~;93$`nP*l~rX-uu{@1)j0seJyn5KPfGbBqjx?QBmJ} zj97n~D-;BKp!j()CxAj=9X!27o08HiwV*6R*B7m?2s+$e&DO%kvC(s@#Jd&qDW%wWdZav2Q(wF zCuqQ!(8a*oPtCNoxdG0fZk~Pwp-2n%K*T>k)#Ga9t6M6}njEzZwdX=<(F}UXk86W_ zT^8i(lO__+Q|jpp(>~r#LfEY>^@WN5w`)$+b;{x=v%CIlOE1IHBVk3-H`FB3 zBU!5KFzAv8FD?q-dj&1p)Px+$$!2NClgh9&sp7Opqp*47(RWEa&vITfsL{_b=`U{5 z4xJ%IV=0O(eI+_CBO_05PNX*RQqcxSVQMwYV2cA2Xu(U(>N%+j9;I!J^)EP&vP5)8 zSr~L++6i|Ad*$Ubo5hb-(g8=`MR)n9EX)MFH4Dy88HPkGdPrV3Kd_!{Mk4baXsY0< zy`!^&m%bHyK=!n#+hP9zoW{*lkI zsQZXy;hKBFy=c$|nvfht$lvae{yRwZx6ykci|+vT)$Pqjxb~I9uUe19;S*fWYvR_8 z`ER8nU;Y=8v2sHJ1NBY8`nyec1Y4uM-;YT{&>^w}0f)lVQCBn0=tsREI8sjoDh=A6 zy7yLL_KUsGQZ+iU_1>&C6y6_l56is-u^3R!<{aJkI?ZU6CMDDBaY)Vde3|XB zdK4+?S_-}zD?v2WfHxflpA=uGiMD%0P5!tc_|CG{$I$_uN;}u8*a!yw#`!_RVs)ov zX>b34g}(z;JB=}94ANUIG0<=-pSB`06h-gr1Pm-N~>J zpl|;favLpERxtjep@>obh2y>lp8%ZA=8j5^AIA7N0b8Dx@?u_*od!Z>iGsZB-yq`( zqL|(>Ij5Gkzk8kb9cz>~R(46fZ|R(nVsSCCi=LD2tnjb(dvm84yNauqt;3+jnMurxSYk%a7Bh5q6=SDJ^7a zJ`m^iE(}6MT8!}pp^CO%WuFuMT|;eD@he-VNr=G#BEuau&=@kh-z2u=g}NVdoxiF; z31v15+eZ15L_>{>0pMl0JaMG5*+yD)tnGAoO$Y9Kl&Mom@jDlh_p1`>GNh#6SJcwx}Tjd-}8V1RN+^M@scQ?R^sv1 zVm%OE;!F%A<!+7+HQ2n?OWp95Tk=Z!~j)itQkt=#|(O^TmP(l*|6?EZvNUSVglQSyOV zsm&n8|CzLF)PT!Gi#=mevpn&FCvKi7J*F2>@ktMcKvaQ(X#s5eFbi3IQ>BZ=+eIid z?~pRH!bM-bj4~TY{#Dlzt> zfMX}#{4CV8(VuU`t{B$nnrM|hj16t!mu!7^NAEaE5;lQ8+cDvhvzE#v+Y0)UWS(Bn z#y*!Ic*_G`w+_Li2gYZG9z(9nObINHh3*Loey}h;e%oDnoSZytf9U4BxTn{TF$dBF z^(GeY(~?P#eGaLyWSux_s`7ST>(}e(rID5}bPv=Y!7a@Q+kL<_Pu0r+3{raR-Gn=Y zE^rtc8zp0ttmIMC7R#Df;(@_ReM8YLy!`m51K`DmRN47ihQ)c#C68?zL8rE~lN(O} z*p2ZUsFSShD;*mlJGB122R3UhU2tbG4d^=Q8#QBMe}d<{+Z#t(gjqj=^rchd8vK`I z&p|0sB*UW}uHJDWhXQFuX_aLAf8C;;8&!6+X*+*ClezdOIo&}ewr`cB4uLYa|5!6T zy?yuPje8GU*xk@b;Pl`vg)Bo6>!;F%G40yf2TL~@wZc|@xy@h7P6 zVV5F;aCXPwGia_%(dae{r`v<;p}CkM@Z1V_>ZZ;8wbR{;T%)#|KTJwPKCzJ%lxKbZ z_v8sdP~}`gpo4H`$udL@V9teTKiWXKW!z9*m%KPk@Y z7a>9`d1B(ANa(4+dQ0fIOP)u{dVFPTdF==0|MIy|m0u^DB*G;|&KpFp_WABt(eo2jToM4@?^7Tkn5am|5> zKXOuMd2Ho<2*q|Cl+rpWPRq>9nIv^czR7TtlSl1maQX56$2JbK-k|#vBT@{@bY>jA z+GRa@h?7X7(r>DQd*+2B$a8U_(gJ|l7>R6)far& zN6A_rbKq=ZWj^toym+%5_em_rCrRL=bYsKM^{3GG^IB7N-Go3JoMq8l1FAO^kQm^+ zl6kBWU;DsVto+T#s5B@lvM)$O)B$geZl_rL<@)hSKMmEf#*L%Jdmt)@>5VyN;&}O} zO(Uz*;r{+=gk2$sib3GS6o-6O1uqiT?-h7v%TOk9fm~sph2yl@0eY+C+YhgyoYCz@ zZT`70{l}(y$PLg+MncR(&_LE&3-={ZgX3=I2ZolJl}{Xg(ChIm_!Ku6_Js`ncC-+_ z9=lDu761;il|9>1nDmj7Yy@vM&syX10ghY4s!C3NE@whI&!)Do7VVJod7do2Aqs2O zJ^y&^=CEAma2MEyb)OivRBSCFVk5lwVJfSrXym8t;~GEs zI_B5MrqMa5fOSTM(;NGX#uA!oqNa}L^leIYpo^bu-g%=Q_b*I3y!KUxB=ol`HOQ)F zJVt%^or_bf1c^ihA`WVW@oQJ5zV;7HIB|c8_d4oe_wbt4lf$=_s^5y4JTi)HNgmAJ z|5e*)Nq;Jy4-wT|imR5@%+1j8e=+j?RLV3_d5T$w_wOf;ztZwOQLfTc;d%#MQ`!H= zbIN!-96zF(>sii$czvZ8Uz<5rgzV5uQbF?(Jr|n%r0duJ>s!Vd^_+`K=Sb&`lk{^1 zjh8Bk!ro%!j%@)>1VZZ_zG&S2eHNLDvX6_*A{i~$xykOM{Qi{MtyH~^>6)^9E`4g3 znmu;ct1h}BZEV%SfDzG1D3VamBpGT5U2R9&qmSBzr({qk!#eB^5IR$(iHFDfk%`Fu zo_Sy4pc7ScWSEe&?z>&>-5JDWM$t$I)uEWDyA=L8m=%`+sEuonbKj1M`8Mp zpF(b4mAYhB@wx1s9N7wEmLON~et30!IsVT*CPX8nS3Z5V|7q!~6cx-!(E9x^M?J4} zrcN&sVkgU`d%{Pj(e;^Qo91q&2n6?s=I)4x|KQ100loOJ3*)zw_t{tRE{~*NU(dJ6 ziNqJFF6mt3MIe@EF;mq(TFTDRi?*f~FS6rZ8NM8(^~7kl8+RAG=I&8fR!Ge4|BN;{ zVI8-?gK)~RH&zx1K6{iP)68CUqXuu2xlz}>T0#4UaD1^Bfz+v;a9z!)M1Uwidye$) zju#2PRM*X?1>c$u#|PmxbM|*W-V$gZ96&AUObITA4vHyAFk)|ByM$Z2E_KNt@4`Ea z@-xNDxfS*|t|ChaQe8WP^oTD7ZRSaV;^o~fevH_kH)U3L|C|)OqUZ*{{ADBcWaDIS z);}tm>0=FqTdpIfOQ8)P=nzhiRLr_G`Z8v18a|}kW}++d>RWg)Tt!!lX_gTW_mafY zo`Wp;{S4@}eC~4*6Zx~Dwci;KUozXecR%I1`Zp*DW)eLoo3{GtFODa`@a(-*EU;g0 z&!X#d#`aKJ>f6?MD>I)R1ma7gPLj$ytAh)VTH?)>sRl&PsrXy53`2(ro#mdy!xPQ* zEcCk7XO)}%gYen?9vO6q#+`3pEc@2VpG3>cs$z~t3KjG|H`{C(JP5xiBntny)6Lgo z-)WgKSwZnym#{XiTXZy)xgdRj8S#Wm71PxIG>*Wu(DGBCL~g7h&ac9Nqvu#Dzp1WM ztQ}SG+d6dMs=DwoN^!SR2OBYWC`}B-fOx{A`nHFE*3L+sKdr5MeKXvgaJm4d&|C4S zc9yZsk9xo`yMBmAnijOj@nFt2%p3HdMKo$2Gg99OENsauzR3He`4((hxI zXm3i+VF?xBVD~X7jgTad5Tv9lB{rS$ePR4O2*fN$FA9tbJ@h+B&ENCDm0M4$C5{kI z2hqMKUv4HTSLzi>!uzR{_r%Cyoe#JXPQ63!6>Y9B!sb}g!@#u!idnqhwv-AF&L8>S zC@_#S*5o>n8u~C$om_&kcr43|K)80ePMw*vBVj&uw=aG(8se(&4_}FJorCqIu6B3D zuABX;H4I6=mWbSJAjnn+A~z@YQQ&8t@#Zg=b*7^C{#wQWCe?kOAgJ#+9i;YE3#`8e zXY+D5+x*Em$3yEtQ@l?>bqA+x?XAw~`v}CbW}0{HR?cSm^Am#g)gYDnmM@aBq&Ex7Md9GH`L{`<0~ zA9&~?i$=0$=Gb1w{@4(}Lp`|Lddy$yhgo6zntk#F)utbQ8azZeZ8A+% zJ*mUH>?BEMK-c58`iF62dqztGf2V`2KlN;{85x$@px9HIEltdeXwR=NQQZ>Ye3U30 zf5XPqc(FFc#dL}oqk7V{-w?lx4$R{{z~0Na6Orglj~H!-ZJ)1=E{d(unlqzTXJr(f zeu-LsnqGAR<(ySaxLvkPMEocYzVpx8tl?4~96rtF=W3;S55T^82wpH%x@}_aGS&9t zl7p1dVZ!M?M(m@m@@})7L<~Tl{ykzk{-FZNB_1MDUi`7b{Tu=zFU>qXVr9rR#HHbFGYhOdSA|5C2HDDN+GFNEGa~{~`XhA8;TJ{< zK~1mDalV84^`|;hYIb`cRe1B>q}h-I~!0JMuh$1 zvJaYU>*ni6**yc_wal^X~$`fRpnS^TeoNq zkJ+>L5xbl$;^!IY5mA#BAzdHciwiQ?Y9Eiab+5{Pfz6TZdt#OF;|?+mb2cbvM}A(r zkgjR6JH-uw*t(&$niToEI8EMLsjsv=r6YYG<;sEEO5#_;JR)8yLeNqq1_p6(u$Zo? zoMv}h;KrZ&%X{i4sbugGw`;k~`YNr!ofzF0jz@npvUpLKGd77#%sbEYB&gE!-0Pyv zZ5;;sp?CyB+*7Q4=ZgVRO3Gftpfr7dr%5v}_S6Ad@5ENiChl}+_UsY^UN~K5=RFXv zxVr6YijPDu71BN`KHK|HNxxKPRV!T80vA}`*V!1ekMbm@X>c`P9dj>TyY+575OSY zg#3s(lYnK-o{`sZ3V(8)68sfvH0|~CycDYD>#~~Db4IMud#8h+O3~U0dMCdRBS%b@ z+&yN?YVfr@(}oBH{9_xn>0@@yV;iB_f25LP?uwwC4>9XdGuzhC;Nyp94K4Du9=n`S zF83EJccoUnq%tCoRqEWYD4LJ{@>HkvUL{5`@zv(%^9Kp1SyeGQO$L_(7%D@R$dSg` ziSy{Cy*ObGgi{vtQEZUj6P1V3#IPDJ*k-*?oS*%j23|&=+*&31deNOaCt=Y9lhwT)aIg9A%+`cA>Q*DnK=2I`TK znbl8f&XNn!4spb<2!wr2&eXTf8&XFOF%G4FCJN7X5MBKQ5v7-4I>1vuPjSO!v&}yc z=D>#@+A<<-HY%e3j z3d*#*Q>fR)w*~z=#c%Bbrfe#BF)cxL_O%cKWcCs0>VVE?oK z;Jb)-B^!?W*e!(287@KOQJ-h-*5O!SI9alydI}L$ZcqBf|tU-|n!=V9((9l}?zcp-7Z7rC51@ zkLWjA-rcP{y7m~a`OQlM!xQ!y?O?nsm~G0`4bDfl4`X)5(YQ^%x_jRD>Dk*#TYhi) z84>ce68N1ybB5bzk(<^e)}|V*1Xe`UW@Y;R4s9dl#L_SO*x=B2?8QK4DWBVdrT*Kn zYnTFg89jGVOQ7~hTpc|^Uc1liDAuQ7?)#AouU|7_SFVYXS!r;qk*cy35+L)|$Cy=9<|%rfU(o1MGD${2%R>Sf1V5f0vv@pDT{EqJ+9ZhQ+3#AuxfX^ z)$Q%;X?M}i=Av9BX7>VWyWH(eeZ26bi8gZq?cQJ{(kXJ&g8ZlnJ^SAO7=#`zi{RpZ zp!04-`F;PmiQXz%S$}{o%sY5DOlL8K3x#R~581jh(Y2V9dj6EAo={j{b5Cbnpn12e zu1cm!zS=K$LWGI`Rco{SG>CB;tuMA54VLP5w=V*$`V(@Klop(S^H^6`>$17jkK8Vk zt@AQjPJU%p|4`D@7p-lQ;tH7u&x{XPpuzTiZN{X??ay8^Fq~W5)_JyMu_PC z=9CPIu7|Vq`TitEJMO{e6ong&LY4QGpeK?-iTUH+J%)~7cXtpu-6%@nRxMgW5hpfK zsY2t1K*wZpJ+DjsZnPo_#i@*a>YRe@R5$r?Ck+sbQvm+HrA4zOgjT`&tkb*Q`EtpZ zW{uxU(CTvGlLexFzX}r>^^Vb;8#xC^Lfa0CqBiT`ycjEUrW67VoFk| z3{4JuT|0>pNHGrw%x~+)J#LgsT0b4F`0GzSp-#qVm$mCG8UhjX^+)f}dwY%z82kSk z$dVq7kXQ`ajjI3lC6loM8Y4_O%k}I?jy>s`SxcQx2IDI_WYqaj$*~4>M8=-(S^^`2 z9IXU^SpTgeku(&ft<=r$vg-si!%Zs!@9+O7N6SKrR&{Ml;p(nbdgKQ$s#oR3&aOWed2M=Z8&wJYu>~bsB zt{d+B+8ZJy0Xa%&y0yS^Ag1+$zvuwOfUb*B68}#hnop_^5_01hQOuH3md;bs*V0$z?wSLhp^R zbEwFx3*pk|JFWI;$8J9Xf10IYK6Qr4^jEBBo;tQ-O~`1OFe8)M(~V5p!VAkD1Ij%T z#weR#^oPBf<=DQ>|JdSrMn)HH{RiZgq4%l?p(kiH6xYncV=F1RbJ48J8IU%#6y*Ia zXqqP$O={h3rWdP?1Ep4ir4_5>XplMMy>fQUD^R$tP?6g33eS8^x;5dO{=o^o z;Zod%p$ha?I$m(`GW8kTFOg_P@?a}kz}(Cr(@5*YA2|)vU!F25a29ka%%&EtEot3N z`nb+8XmI4tz+?U%ZzYs!Sk?!fF{z>y&5^TIAtn?0(f{FiAb$oC38L+_3zH|>3vhwD z_R7=7`DvwPE371nD?J1|^`a(qa-aWcrKckwbGUY)PQ7|b`Ma3UT*0ou`Au}OD5eK; zPSW1`M1Y|xH%gvF9man)v~>6@N``4V{}jEP6P`DWneXrF92rIuLgUuBuEuHz)PF&0^8$L!yQMVl(4Yf@T8tGp`C6{2qAgc;ML!cVrrA|XMgIm=G+wll~Lq7aG}ca{MzI_ z?XqM~YT2^#(PwUak}ID0j}s9_`4;m<=sIHya>kU$O}HG8;`GUaJZbFa69$gZWFE&A zu%IgWOgK=bzp>AndoF6c&5Yb*TJ_mI#gQ(BLVf1f6DnfdkTzU9C#@Tz8Ldb(fU&RO z2aCOqtz0McVyE&pP9RwSObX}-niS>Z6Dh(#S|!bP(*JzD>NFAoC+%se&D_(ulq211 zYvR8K$sG~W+ag91PU+)03U6i)CT6AVWJv(sh`T897p+GP^2G~-;y5-i8NaGuYnD7kJ>TU>`t{`G8qTL{t@lmIx zqRn!{T7#PKLU)5H&_DhZ^Ii^2H(Vy*o- z4gXZg9mruC&xcN?|HR|z6JFUT*kEu@7`(j%4O6!utYLMUKGnqUA{Kj47XJ{(Z-yQ_ zkhvjikxND{{j3Hvbdflav!P6@1&9iI4P;_i|5Nz%cX$ej9LfhRZ>O> zO|*`^m7jMSZowLj)W51CGKP~vPx!}FYlIg>wUx=x95FK{^Z7Wb5l9Tu8N=oiPb{%t zf$^x1*rzH#)tUz%70)~PM}#a5T-y%vAd~cmW)|ZU<-{{Pqj`6{Oi2QEBK0KY14jzB zK^S%)zNXt;x!9%nN(I}(rL41+#U4uL!XCgUAS}b?w>64V*N_Pi(=vz}T3I2pDCt^g z4NPNZqnDS}kJ?|6$x{!V@!DL+AZiS|DV`R=!n2k^qG&J&Ic-ymgmhDgd~5DAN&A=(FqfP=n9J$n$;))Cl;_uXAB(=Rb%n0XwBt8Pdd#d~uGZ6*mI zryC-1V4yCUVc9a_wWO#I+jJI0e|QpOYc?+jv?bMWX-QSgUfcbmMGg;%s7Vi9x0W^z zQMSkrQ1|CuJx^Kt)K!bmS{ zp=o!!aGzg>?S;iCN2r+graqGCqA~Tx`9x0RkLIuh$NhP&&F(tQ=2UWTy;=EX%3A3Q zzXy6f0K6OPdktVwzD;pDmA9{N>VD(}AIr&V$m6)YR@Y8aJ{E8E?de|1J-bzeQ6@zc zWm3(n{^-Vo-C4jwWOGyeJC=^E_`G_`X&if<5*gtPTM6Dkx;tlt+4ZDNf%4kpX9Z-; zC^C=|L4Il$U+4O}=;yai__K3=F4N1U*LS1cD4(a9UBwGJidkDHO2$XI_P+pr7YET& z0#X*((>Y`+GwzY0XfMQcFI_Y5)D<_)FI;lKuTF5aOiawD#O={G&X@%=-3^-420WU^ zf+wK~2rP|Y(f##IgeA=FT4;-N&wmX!aWqT5X=8VKJE|^XI|J1PAlu z_HZh{?M@$QqwFc^O=Grn1$oN|!9MD`!9Mma;z~YH(1qk4LF?HxB#il-2B@0Z3xA>QPHRUY0Q16YmDShFY=DkA_^C83MnFRk<45*5ih*J&JF=Q@o?OQ zTiUc)h%I9%Kg>`M88cny?mR{2MpJpKRKf}clb5%sS-Z?y85?g)G4IqL&RVF4dV@6( zUVjQCtskMCgX+f$It1B2M!sTyW7&$AFvXi$;}nwDC#x8towcXeR3#!Je8=ccR3zo7 zq2pzs8Duw(KozGEz5IT`G%_mJsXvKI4?CK5{qd5+B-{I^?)eR+;hjy3{p+GYoI>9C zkfA?0K5LAmeU=2#Fy1}(AKl61s2SsV-O?WYs-U>yhJYjfwpw7_8flDctd+Hv2%Y}* zw36MMI)GDFh_pZ}IS_`WR)VOFgSF!lsK0DVshu;2z75+oGh>R=wq~-&S=^KlJ9|Cp zo}M=o-IX5nxomoVb_m)x&W6(U;&44hn!*ej&VNFikq-_W%wc;pGlct6B2~gWW{;o9 z4Go^0csf2?sJz8AFYUQrMIl;xwBo_`RJ0UeKCOu2 z9|;5pfK0u>dX+Hc+4Nbe4>P7qZDrJ{>hT`>kjeZN)^MO=f8Y45_GIV+m@@p{{KN6! zNzNG@lw(x9-6*mFX?>)#9Jhva6l~Kvh}itKifShmpm10x_zcvB8J_U)~c7Im@Rd}ul93o1N$2nL?gS-ewodo z9!`GipR}|7mxtt4(|K>gTG4?!Jmf&$9>a^11EEvH$CR`dvb%!TjeH+9kleBqx0u;D zD`n!*U`v(~XWSp!m9E26E9=YA82~Y_XG_|C1;VZZpgnYXow%4rIgx3m60v1CDajo< z*PpzH98jv++Kp(gQSlVzV+mi{R%vGb$5NZd*J&}u!YXmh0MEfd?`dJmG89r&V`6P5 zuzX}7Dn$e{L7#zEnl;bR5I35)g36dZhenY_d%!5!Lqf@ap@)*8V%Aojo)3{gtV7m; z9G;~bf|;4HD6WGI)p+&d{1m#*a3?+j$~f|f)=l4-yt8qMI#=&YDey%#C(BCrLoHM- zi?NlN?|*rxYxCaDFIG3FD0g2XxidxfmT(`54u++>yp&TJRtObUmK74dTKPd1G*F#7 z$pD`_1Vvob=$quq<;p*n?V1I#8dq<|D0yfbf}5Hse~PyA(gx<_SxAiOKun2=gVU~# zXQm^CQddotL~ctXP8v0GFk11rv-#NjH3F2o-3zlJTtSiJl{%i010`t{NTg@psioq% z>IKK^qxo|h@~#`2utF7Rxx_*~IHqXKyki!kLTe*Tn^x%a z(wb?Lw~C>fXv+PB>>!uq-6Yj?}@%@HgAf@Po&~3 z&D?Tf4eNJ6?D|vNR7w1oh4iJWFSFh-OeE$^3IDxi3_wRkVc(`N0r5O=oG7R#wAagq zppw>>WjJq42;1O6rcXp;H5_iMn0KmyN(`Ix?9w*%$wk;a6e{V6VT?vuD#M*%nN*#O zFg0KXYH+!txa5in!2lbzFxUb#*tTsv8qWsWD;Ld&4*I?6L^pE4JC_2qS`xz&vq@yc zKynP%K1%yrQLv>1HyULL>%Sybp+b|uTv>&570^Ofx&t_2B#g{LlHJ_@-tzEoMHg5U zFDb~UmFWB!F-SJx@_MTmhA{yJQWc2|gw~q{*1|e#d(A7Q;DmBo0t8b=kf~L|4|W}a z*b*f#1&ZW(&BRAt={+m6Yqlqhf|PSm^&*!Za}KVcY2w)Hnr3?$g%xpipUKG;no3C=;6^9T8Qf``YxWXOsSPobDL%m7WnRwlw z_JlBu*v#)W76lc%dCjX-C23un#)2%ii7?IdvVvRcUn>en(n6%bD%WiYfk^{^Ldaox z9NaMoZ7o2RDv4SFLl}CTR*JAfC{!rh0ay8;DNJh)`F3qGy>n_2bhA#sGz? zfgM<=_~O1yjxIJpNCI|Dz>=ygoUsBHoM@XzSf2${>?ee(Z13{-I2frnm@u5%g9%Zj z`C?{%Z12wNdf2s^0y2qj-3I^n#5v5S4WZ_Ltm%{_&}4Nb=sF{dY^LFS+3#igcXx;V zs)uBd3~dZuMVQ7|yzrRyy#!Bw?E+(M6sYw70B5iHn9%^O2I@h`lJFlkjOp`{q_tt$ z=-?dSi2V(?Rzo?dI*Dr9{}_y55a_Oxr@Q&#+y|pX&Z6z|0uVQiknazhAgL3aL6UW% zOd5sEo@d_eauE|i4o|7;LaK2n`%Mr_`MT-+1iIh6Q#~*@x&GBaTQ|+9*%QN% z#KBQw7)WH6g$_DKGlvvVwZs;YNd71^Ugf!AWYH_jxWrN!+Ay@&(q?{Jio!*B1~U{` zRp~Be(9qr6>&^k=c%_h-?t~0Lu1^>-Lm#_@QP`x&)S{YMHWdGxOhz|)E6XXQYTGZ> zPhWn_`EWEJEs!)|_?Ez!>sm#2qJAHT>uc2>_-$f9@gsDVB+aKc4I&zmar$7h-?JPD zc9MPF>p^COnwmI7W1a3C<~i8bgb7b#_)!1wFd)q4koaCL{9bQ-w4#-93ZXic;fyIg zR*}iLi#A(QJC01;2|3jZiAzKVUe{a8U;9f2b$k0f!MVJL02gxAj%0IDtvWFt#7m9H z?dpguK}Q(vbQY$_o3JDLSAO>}PdSM(2-d}oDK*$W_KO>`q7fg0%0Fz#P60v8BUt{J zk&RUQ!Q_t_vU}$KK64Ll7X3XogdrmViihC>gp-bJ%ig{M>J9Z1?U8U4B?N;CBFzt| z*FWLt>+NgppYQI7bU?ZTQ1xf|bJzlnwk0@7fPt~UF9xo#{>6VUhJlrT|JC9D|5w>< z+3E*ii0hvtVYJ8!DMR+koNXbXZGqG8_jJc$;P0euztnt8Pe@*N`x)|<@Qm``LtFz> z9u27C?_{F-MO*I*FnSy)=q#gP6>jZMgsW9{3M&XadY& zq=4>CVK$X%toC-WhsYDK+^c@dN-eAyv?XCcc-!8vfCCFZlAJ>1Af!4;VRa1Q_@hN@ z;`V}Eu=(ud2Eentcg1l~*qq&l#ri*CUY*}s(BhI%Mi~zZq^9M`0|rD=4#VZ|yP+Nh zK|ulT*-|(GA~^HkiVuF!eiiBt0>HcY$kO7_2|3&T8^KJXvL(_$q!M9kWHK8n+kI!G zmN)}pj4mH6rlLj?V+^Md4J@?o&+ctp`yK`NI016l5Q+fNda)DvQiSQ>^FIaFD$fo1 z6briDj?l^=A}9$UO(HHp@@yh!bF>FAH$JCnO)aGgG#|p+cB2)F8+M>Mx&?P1!o3xs zBRn%F2%$0-sR4EbrdAxpwvjtwa!xH{=t8Bex-140_)vjh;r%cww;tR|YQd?rB@n8+ zLu*qRGdKe?I3dUllDve->M36LHB`n~g-M!OH|@6V*WMPC_3E-7G*#Ti194e*Ea()i zU|SpNMgGWPD{@zW)`T&T=Ljv{X-%J?MUmv_UllqG1Ko?gt~G2pZwJ+;ZI?I`d6>tFLtGhX2G>l>B=?K+gXrboc;s{+PN8SX z>OnJxCd;7`O5H3d8~ygLPRMPFh$4Y+s6xyAuG^tdSzv#sNGBn;n?1JT%bI{150r60 zVTRECYul^S37~)K?McjL;-2=Qi}P88P@qYX&b{sQ#=gC#+dVI-8Y)?@C20KrVDjG1 z1yVs$Hecy(l*!^*bWm;6EkuLB4@7DN*7micSI!X<%-Q;V@Jz&X#uH%?{3epF8Tro+ z80Kd$F+rX%%3>#?SNw2OfG0Xg;Q%$mcpg%MGNAK|Hh6&ciYx$!NUwN2IUaNb=mPET zJN6O~r9<2j1ty)L6$cg+$qUo1^jD_InMct#(QU_8rqFU=k04Gb1SEsj&<1#0ixvYq zN4->avU{*I2s#Gr^(&sU3ns+D+)h%AiW8F3O_h#(Nny;P`-6oM7as_LguE@dI|8E( z$vnN1s)>wRCq!NK;ej8fjG$an1T`gY%8x8)l1OE|aleb#SUq$UZf@L{!)DyN2oBCi zrsN*vGPO?`x&*In{FCnnsgf3Li#8;?AC2Hjp`2Q?;({zwBvgdizc-CJK_NsRi6<=x zu|UXlKeD&<%0@I0ye4XO5wUucm30q7q2x*%v;@p;hZ6NNFziNUm;0<_kb(`*?$*2> zvk+C_`DWsLl>rM22cEDQCzzR=?1G)sD2b;7=`Ue3l?U7QnP25ERHx(XEA%GNd&X1T zQ~Cd~sRHt;X9AudP~^77F26P%DE{sxhij)WegHlj;wzluB11 z$W_1qhIwH{wRa*h2tQ1TXq$$SRqn5X7Um!+nDZdgb7ci6k% zk4dX5dFVQm`7z*r>x@iRz`xlW!_11t8l5geRh@;YP1@62n%e`-D=7QD$eAf)!bvFS z@$9w*JxBB9kwdjJZ&sAG!_1lwfepD=5uxy`41uj4T?JxonmIvgTh;4B!4ox?#yM&9 zuCL$-Wsq4mQ7BnvWTE{7Nz_aI%0KkL4x8CwjL?ci7(-2Ik@W*TY^;R7Elb00@Br-D zmx6|le~LrTD)qZz#Ej-Az!c30*DgYR)y$3^#3x#Sey{ky=_|-PTU?g34oW-%{d#TC z=%x)K{@Q_@26K$1v}Qsh4*IqtbX;soE^5Cn{5=QYiJ>-ToSzat-nC(!;&9#3G_JF>R!E!vDz(cdsVuz`eS}Ih{^U-!D^X^^}uv)|$@TB((my0&k zf#vLjU6w-NPtBsDG>?pe24m|{ngEoy*Rdd3S`8+^0E<8#8?4r^ zQ{v>FOKXQ|a!Jz{=Wi0c&i{W-SrV#;+-X;^(F*NPKz$IXL)`=8w$>heGSY_*fu15* zWLP4BvqBS0nvlSEEkn+a?bqWwh1O@fs9b?q!ur4zrP(H$P~2qL-9JqY!X zI^G5z5e+YAh-%lRQg4Px_n5)DIuQ@^L_%kJX&hRdOb)FjS(`C0QWBYO#@kMABh*Md zNGTZW0k-Nx=){CSW@Lgbf!j7EFrg=hvR!r?fUbYk=P=wFbmf#xB}kt2>qFE1{I{&OP2^WK;-k0ca(*M90D%_ z)mccVPf}(wArt-!s?ISK*Q{Zvof7Jd=8dUFi0Xesu8DcsvP6@K*m5D15vnt(*Ft2w zf3Pyq8c73#?w?NY{1XBh1rV%rdK4XDJg*0N5gPKvNak}WTNPnyyLwS<@VW}vzdgwV z9aPm9zO7D_6Io_Z3G99b!T&}}gvufWph!Rj9mM*C5~r#}Mh!H4I1wztX0<3rC0uC< z2|46&*v?`}80w%0dPN>OLnnZfsY+v3;C!RK(0$3)SPx5`MzG0o$k`*W`sMe@=Itm+ z+c;5@Ne9CBc>)BgP%nd)hAP6V^Y!3D2H4=4tZ{d|(Dzu1{?28|zBJPK%5AD%gCk}s zR|p&lYA;X;_0_=AUMb=^m3y`rB0mkN!J3({g}qvtg$t0NqyFd@L!hG$ES!a+lN)s6 zT2PrLCL5v8R&Lu-9io;ofbKfwdMNm^xZzG0FZ7BDKCXBWO0&SoA3IQ>l^UE7`Z~)2 z=GSS6j8@U%US@4Nk0W6F_H>v+luU>gs24-`lbbX zo3Xk8^Re!LTM-0JpagW5j^e6SC`W^A$rHFI~o^#ro>A)c!&Ez0;#zMOX@A!*F7Q>etcNKp&FrRwG6x>RLg4k&QWcz@D zf$EWKgh1G@$bgDy3cDv%R*pkAW@IpnuwC4;0a8i05GF%XWQ zsG(e9*5aN8*ikE)wc~YzDbyRn>;0k>|9&yzz!vP;0@8=W@>1yDy|BJ-YpDP?2HPI# zUa@jJf;BhiuB0M}qi7{FXyagX_MWh$k!ja2`Y2n}1i%+c_>{N80KIHnB}tYP_ZoHIa@wR**6=^a_&U#RNubS6W!Q34Wnv^MR)n!fe6tbZn zdHxjByd4pn`t|HSa2`OW!e(&_(8L*Xc>%oSkRkOF-$2$ZXMl2qj?4Ym>6P(^IP7Ea z6@wJiOy>BnUe80lCAj0IDhEcG9-E<4b;5!iw_@gaW!Kpv+j)kj0&|Dz9GuGcaiBho z;fwqoEU9?rX4lnHf%LTy`R?NmX41bZ7pJ@wp%O;OBPH~+`nm(tT1rQg z3+FCLcd?^p23ER)U%6ol7Bml*OBfx8hz4c9t6y2g>$*C^O`yu3{tb2szz~fT@lmLI zkO;&7B9DM(!XNuxh}r({>Hl4p|1)(6T+~82b#}}{TlX5&)qF;LH-A*1rPA8WJYN-N z2=_ljl<9*@|MYW^fXFa&Q)Nf^{@r7x)s_<=jgz;gO{y09i z<7MvH)9$WWD*;})8^>#kt9?{yUk}C-tFm6&AkS@?u;h(MmJptDlhP1vmQlaG@#V~1 z*4VgSfBXIbtx}NTRcAx-i01rz>(GP`;bIjT2S+ogSuM)sm4S$pg}u!+wp?fE6)z$v ze#S*nJIjiz-v+t{{pIf(G=?KYG&9Z>+c1Hjs=H=wtJbdhJUXbDJ~wBJAM&g4l|vS2 zDr8^1v9B1L%fx%~>zFy*dixPQdbALS3&u3JVZjL$+Q8nI+hOym%(9=-Bt3IWcRQOOKlkOKE|If%@hpMAzyhWJw(`Y9o72JM5=ZCA!yaskovH~^ zD|yBff3|8Y24YN8&$T_W7G=#@2kkQjBH=GZzs7ZVXY^gfBy?`bKHvc z>DQ;`WjV%huBE zwmvVbO5XH-9QC3;jcuaGL_k^wWGpcP8<$N4%ndvy{1j+r!DG zcZy^aK4d;xp)EmUl7cRuf;dK6tIJVE@mI2iJjMsQmr>vK&5qFF)n+9da}%Ccr7Us7 zx69>`HtdPeghW-%2aUvKOq z##XLikR&o2wAZoy6|2TYfd(%_d+-{|pI>uj`J1}Kh3nA~A>RTb`f%d_2**eBKkp}> zKA`?We=S`4zHo`_fAEADnOg0v@!x{l-(CariiaCTnIVTAy^Ckr zeoR5EdSS#xKSXZTwrNzbyP}q>Ui6k2o8ZtSAkCW~b-ShV1#Z!OIW6U6jS1DWFS5{A z2LXJP?m0?fNc>;lpqohiG<>B_>iTUkG{(LIexECxYHF2rI$vTs?zp}@R3puF881fH z8hA!)e6DUvpA3R;b$~kgW=}g$D$1xPp!PbOQGeYi8FuiSbQxy1_apH%zlIAWeuSGY znh`XM0Ge*6AED>N`Xg&6YOK{4Q8C(R^ChMBRq2=I1)1(A9`Pk+{PAyId#ipha2I6XCkZ_n(P{=#`-y_F|jCKVO9D&{pDk ztE4&={O|8nq6W%ve#;c`lP<;*Tu2x?NtDtzEQm%}`I7befbDggx|&5L5eMy_4u`VEtRv z_G?mNuD9-YzA2?c8)6GlGHPp$mv_;K5L5J-=H(dXp)_c+sM*tSdgLJ@X%V%ZlebK@ zlv$i=CH?- z$kd2n%s%E#t|rob@*flS^jKH&?K4+Ksrtg-pP@H>6Y5;yBroSaq%=^okyK(rd|I8pI_B`hJy)N9~~4buWbS z9~M5BW*&T}_)Nw@sQxEuJisG)Hue2fUp5Tb(IEK!{$US&Klvvb4Y3B;YZtnIj?Nk8`~4=4cLYGmq*#99I&vJYMPI$?7TFsv2P=K!M-1uLb7~b& zj@28Njl*Y!-XGDI>GfnOExT6V3i+=`x)+f1zBc5{248Ff>}x1_Ys>4%?hdEM#|PIk zThlk^l>{iUHe%z3Q&GAbA|(`kjWZujMRB>V)pLjbD^BPe@wtm6s>#grnR^YmD;^ z|K;9NGsR~ka>K4jvQN>?NT?4~4>C25@$wK)puimDlaqcxftw;CMQ2iDzCuapN@y)?C zu}PP`r{X12qw&R2$L-HKKbj{pKp@a3IpUhKNu$}=aL>i zzg*=nHsy&f%C3;#_;J5VeA*M;Ty^5rwj{HP*KRj+z+&_Wwn@aQtBdK%kxCj&%T)h; zOqO>4M!Lr(SE~B2nLy6fk!JoJlR|cxC9R=$L8tb){mX8??;PhuXn$H{^Sm%h6F~+c zwn}WNUU1`Jdo*eIFl;%ej#}_vDG0ecdo51+ zHT{O2g=-+Pq)PW#hJ;wtcGAvP#s3Z@r7qIg?0WX! z%T*4d-#yV;Q(f>Y8#t1^y_&4SnP4UQ$|JQG@S{&x{|gKr$WFU(IhON-v5Kx~?HK$6 z=5skuDD%6|K84AD@2@duz4vDLIu6!3)!dZ;o%B0h0m_u-biU;fcJ{Vkje#8;hWhM+|IbiRd4X^1qwxYAi5#B_0%SP=o^tLcKz zL>A$V9q31gIU3*XC;Lwh++P#@?!7lm*!AzLX51NBBDd<;MdP1)NgTL*svcM0oxCPK zWxqG;Wz1i8rcLLjQzZ=3Ou6(23R^VigM9EHWT5K3Hea8AH+Vr>ZBfBnb-tqUU*nY; zI>25||By0y=^Cg|N^g-r7`u&NkB6AEA*kzC&te_8R>gD$4t`&(bTqm2s}V3wC5kot zxY+$HS;zwlrQ@Fxu9jdlFq*|2|Eqx-9%{u}y@;Rm26iUMLD zwPb4X{_@?NbRRL-!V4DNwQ51Lh@NK`C=3`q>~(94uCsk;e*Tssvo+SBsbtfO#afOz z7^_-?ZkQrV-aGc*x!3ej`EUbo)8~idChlFH%6XN-w2agSeDT(= z%F9ocZ~X>A_0#y2g_!HS|44Be48YIGIhJFyH(!ZQ`|Q(FgQw@gc68wjo+p61t5$Us zg0gsXIX>e;9#%KY)*O|TJ+1iM^KPF0fL9yr>vP_w_SkdTGhaGMqU@k08Ml?_x?BQc z)DC^dc8HKuk|Z$`_@eRj!r15gYZ=qtdy`h_vFak{?0DnKhbg>G^4$<4Tu}&C&BR%* zZVWymE5_}mYq~^KOsol8?}I*6QNd*a7xF;ds=oJ&s>ci8V3@@--G@_uATwLN{IrJ~ z!fKmViTrd>gu1lPG2L%m#46(}Z95;#=%0C0$Xv7*LG-uNXRF^eq*_AsQB)>0$cjtB z{6D|4J*61cH5^yI1{eD@U9p+&x7l`u;T79kbExkDAkK`--Y`|o$#^Zxrs5TPtcK7z zao)Jf(SIxyl-wSaTou^P2-vSb%BAQFQ#$dZQZhY@PEc=oCf;N);Fa#X-oykPF!NKq zr*Q^C6n2Ab>3o%zyB*Kt`Koq-^yi2H6Qo3kuG!wlAhMc_xb;${ci5*(-wh2Ki7%3S zQ+1f$$BSQdIzAvb%d9VG6%jS@5A;oviGJI7Qgz_hh8 zG6Ah|xr>DrdcVS(Vl$@F>_yAh@etuYebm$7bLnX*eT?|QT`9Y8 z%e%VDVQ*m!xERXkqNF)Ld#_I$mJ0n?so*k1Z&!kT-HMIffc)X3eI>j61QNt5t3*ki zSzVjVA79b*(ag4V5xow{pZ2k*V|FiM?zSZaDiE&3JKwS`WKZ4beJN*fX0;7|jp^o^ zLEoDbPO9{8Zp*dP+=KgaO!D|K;qvdoL#jkS7`rJrhndGaEeKDFD++K+RSCD=ZvJ_9 zuswOLj@b80O{C`{l0Y8x(26fWyvH5aMz_`q0|ojrG-a(k=8aV}HL#gp`}hR+9}%;S zh*R&T{9nDVl{2GFbw4B@{%U~P4FC7sG?Juhep{I_q-O+LIv<-JW2Ms7?06TnP&5CT zD^AP2^(xKbkr}IN+zLGEjH9))Z%oHHrnlM};EwgI!dsz*U$D=lQ?qIT$)g=b#eIcD zyxz=+GcCY@8=e=7^S3*`RI|~*o z|M(M})fIlSf0$U1D`$bsOc(ysMuHhj{W&~5_6*%PIf{k7^5Ayy*khYTD|%nV?-i~LcpWhRX~*Z4qlRg=g$VS?a-GiRjV~Xj z!PB3Nf18n#;bZZ228<5e3Go%R}hjj~`|yN;y{U-fT!88t5@1Q98_oz?gJMc5Rx z4lfvA#8)x??sa2RoPaFxq?}S=oAabSlaZn{MbZJ#_5ZJ%O6^SFWe}F6-ZyA?uNRlQ z@gnBjVx{3vu%n^zsj~d@7jfAp8WygizuAKMyYYVBj|2$m>;DMP-olHeXBw_u8uuet zRsQhiY9ik2ow}qRTtlKfTF*tiB@iKeWdm8z;gDu41wQMptF6874&H?F;UAg(hK1xo zk*%l{NVz4$8@xM{N@dR$TdtO0x)c}Cgis9Chk8xC*RM6c6C4d<7&bMfmyfH@#)^vI z?Wi3;AWajpX4TKT5XAGsjwhiF$Q6~8My{5yI@>Lxr)^=QsEDJi|D{{2seJd-Mk-tU zyUc=Xn{Gl^0hapL%Ea^dd#4{Ff;`}D@@^t=r%H&5&fG;KtkqS~K(#d!f!%e+Rmwvu z8UyXOKz+^Z0R@uTtDrr5;Aa?x+ zXwzJLyprk5)Rx{U`^pFaKfhN&{yAftP1>Wgkj}C~$48EEltDD@nccdqJur6I=>qFt z`!4Pp{=vALiY+@$`aiI%tm#qHH@thJtofhilY8c;CXXJ$gn#jKBOUK{k+4B*-4Fu0 zF-@P4mY7fHM8)RccQt-;93}2YI4y5L(eqTQtDQltR@R{kOXAnwsjQB{DSvf^`QSxL z%$^TnWd$mOxYMOUqWP{WO-M}s>;78J=Lu_+mioYN?9P`sRO2|soW5wnrdk4n7Bk!4 zgK9)MXKV7Upi-J7uW-$8CnB1^{n-G|>>gk1BKv-08m~<)ZfHB_xPm+|B3ex5u8l>$ff?9nPMo2VziEnSnfNs%QZZ4Aw2(S z*FO^mYhvfQW3fkikJi{Wt&08o%Jpn-z|Mba|Jd0aw^$-_yL*VS~B6_=cy+fTsO>Wn}GGO8v>52qg^#Pu=87a_Ln?qkLrVr zP}HNxtpC_qCwe=1o;_43(CE_YAKTg1AtTqeR-GqH4Y!DLKW%TBm!2dQLmVWgsR1;s%nZ1Q7 zx=36~@!aD~*Sthh_7(ov>`GKFE3_0>zpbnJcUJR{4Ysl)hG}djjgiVKrV+!ZY}+2; zO+RuetO@KbM5}!cTDnLm4NGJf`E8$=iPy`lSTIhs^CIpO%VMUCe>!wt^76-TH>BEj_Sw#1OU zb{|}$8l~;qPQjT=q(!r>5GP;BdT3(0nxk|vZMku_Y3jX<`f>dVew}neh=?S3cL{aX z{nHqq>L1>;NBGQI(U0!eM>0(3Yh14q?Ud*f*r&=G2%Ge-xZf=~OEs|%x{R`o^|~X( zNm--pbHQ^d@i*6(jVBzh&)kUVSEfpM9Ss= zSIWcNk;2*LM!yfHFpms8IXGNr@shW74PiX$ucCl2XDi1RN#n6CwuQU#wM_<1>wm=u z%LpVK_PD2L;c5V^%3UZ-KV#nhZi&qZP^AT)2{RiBCooc7s|+v2DT`RR7F__4?8e1u zBn*5o={D7A_S>nLhjnu^>1Y3Bt5n##dAsI|kK!nIBNFW7$N%_(FawWV!!P&Cs>&Is zZI^P=q`ZeOZV5ERpqM|O6!1ejJ$wN|^50a$ZhkTwP)ebt<6p<{r8`L4C%bGhJI}1; z=lh4)%6ax^cG-z`er@u(|}JUy4RIQ2hs*l&Gq|7vS`ri5)*wi}g~Pg3m(<2^6mh7VyB6W{i+&4g9+ zMPqW4`$}9g`YM#evVut()TGf&djE|_j^Z|UNU(TAZnMEa{RCMtnq>!UY8}|1rXHo9{VF?@n_J!J4F~gb%A}*V& zMLSAa7*pk}ENJ8M*9)Cr+7f{;@G7ZHae300$OTo}Ctt&x7ZqLpJ(Mn`-T|(}&UaHg zq0vLRk(9?KW$u>gKjufU_=}2^{jwwt({8okp72wY+A96jyT3AsQm2p;(Zv<=ALKno z^7^d#rUr<$$XgNhIR2cL2LPq;=FP1gcKFvnf6%&iJd~3Bsf3ifgTZ%8ASj)*UY;kX zV|ClNNAwL*8_sxZL>H?mM7d_NW69_>O7h90>ZbY6%U@=|Ag^ZpzeBHYRkrO36U^@Q!_c$7S_JJHBRUwDeV+ESnA-ajxf z9kSP$0;{uu;XS7I#XV$IxaHqa;JBIRhhyL(6d68Y`CO@i9_7?O>>iR-{kiS_2c-Sx z_xl{k75D7p{1l|H___^)0q%F(cP&4&E?8WW-!BJzsFvKKlOwhri|7 From 8f3d5f10866eae452d7585a7c22073c502a6d216 Mon Sep 17 00:00:00 2001 From: Alec Edgington <54802828+cqc-alec@users.noreply.github.com> Date: Tue, 3 Jan 2023 16:56:37 +0000 Subject: [PATCH 10/20] Support Python {3.9, 3.10, 3.11} (#51) --- .github/workflows/build_and_test.yml | 24 ++++++++++++------------ .github/workflows/docs.yml | 7 +++---- README.md | 2 +- docs/changelog.rst | 5 +++++ docs/intro.txt | 2 +- mypy.ini | 2 +- setup.py | 6 +++--- 7 files changed, 26 insertions(+), 22 deletions(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 1ac8bc5d..f6d4e8f0 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -33,40 +33,40 @@ jobs: with: fetch-depth: '0' - run: git fetch --depth=1 origin +refs/tags/*:refs/tags/* +refs/heads/*:refs/remotes/origin/* - - name: Set up Python 3.8 + - name: Set up Python 3.9 if: github.event_name == 'push' || github.event_name == 'schedule' uses: actions/setup-python@v4 with: - python-version: '3.8' - - name: Build and test (3.8) + python-version: '3.9' + - name: Build and test (3.9) if: github.event_name == 'push' || github.event_name == 'schedule' shell: bash run: | ./.github/workflows/build-test nomypy - - name: Set up Python 3.9 + - name: Set up Python 3.10 uses: actions/setup-python@v4 with: - python-version: '3.9' - - name: Build and test including remote checks (3.9) mypy + python-version: '3.10' + - name: Build and test including remote checks (3.10) mypy if: (matrix.os == 'macos-12') && (github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository) || github.event_name == 'release' || github.event_name == 'schedule' ) shell: bash run: | ./.github/workflows/build-test mypy env: PYTKET_RUN_REMOTE_TESTS: 1 - - name: Build and test including remote checks (3.9) nomypy + - name: Build and test including remote checks (3.10) nomypy if: (matrix.os != 'macos-12') && (github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository) || github.event_name == 'release' || github.event_name == 'schedule') shell: bash run: | ./.github/workflows/build-test nomypy env: PYTKET_RUN_REMOTE_TESTS: 1 - - name: Set up Python 3.10 + - name: Set up Python 3.11 if: github.event_name == 'push' || github.event_name == 'pull_request' || github.event_name == 'schedule' uses: actions/setup-python@v4 with: - python-version: '3.10' - - name: Build and test (3.10) + python-version: '3.11' + - name: Build and test (3.11) if: github.event_name == 'push' || github.event_name == 'pull_request' || github.event_name == 'schedule' shell: bash run: | @@ -117,10 +117,10 @@ jobs: - uses: actions/checkout@v3 with: fetch-depth: '0' - - name: Set up Python 3.9 + - name: Set up Python 3.10 uses: actions/setup-python@v4 with: - python-version: '3.9' + python-version: '3.10' - name: Download all wheels uses: actions/download-artifact@v3 with: diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index aee9792f..81ccfe60 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -14,15 +14,14 @@ jobs: runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v3 - - name: Set up Python 3.9 + - name: Set up Python 3.10 uses: actions/setup-python@v4 with: - python-version: 3.9 + python-version: 3.10 - name: Upgrade pip and install wheel run: pip install --upgrade pip wheel - name: Install pytket qiskit - run: | - pip install . + run: pip install . - name: Install docs dependencies run: | pip install -r .github/workflows/docs/requirements.txt diff --git a/README.md b/README.md index 44258c16..d1ae7020 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ representations. ## Getting started -`pytket-qiskit` is available for Python 3.8, 3.9 and 3.10, on Linux, MacOS +`pytket-qiskit` is available for Python 3.9, 3.10 and 3.11, on Linux, MacOS and Windows. To install, run: ```pip install pytket-qiskit``` diff --git a/docs/changelog.rst b/docs/changelog.rst index ed46b14c..675e35c9 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1,6 +1,11 @@ Changelog ~~~~~~~~~ +Unreleased +---------- + +* Drop support for Python 3.8; add support for 3.11. + 0.33.0 (December 2022) ---------------------- diff --git a/docs/intro.txt b/docs/intro.txt index 70aea340..61d70143 100644 --- a/docs/intro.txt +++ b/docs/intro.txt @@ -9,7 +9,7 @@ representations, simulation and access to the `IBMQ Date: Fri, 6 Jan 2023 08:28:45 +0000 Subject: [PATCH 11/20] update copyright to 2023 (#52) --- pytket/extensions/qiskit/__init__.py | 2 +- pytket/extensions/qiskit/backends/__init__.py | 2 +- pytket/extensions/qiskit/backends/aer.py | 2 +- pytket/extensions/qiskit/backends/config.py | 2 +- pytket/extensions/qiskit/backends/ibm.py | 2 +- pytket/extensions/qiskit/backends/ibmq_emulator.py | 2 +- pytket/extensions/qiskit/qiskit_convert.py | 2 +- pytket/extensions/qiskit/tket_backend.py | 2 +- pytket/extensions/qiskit/tket_job.py | 2 +- pytket/extensions/qiskit/tket_pass.py | 2 +- setup.py | 2 +- tests/backend_test.py | 2 +- tests/conftest.py | 2 +- tests/qiskit_backend_test.py | 2 +- tests/qiskit_convert_test.py | 2 +- 15 files changed, 15 insertions(+), 15 deletions(-) diff --git a/pytket/extensions/qiskit/__init__.py b/pytket/extensions/qiskit/__init__.py index 77362d76..b95e62ab 100644 --- a/pytket/extensions/qiskit/__init__.py +++ b/pytket/extensions/qiskit/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2019-2022 Cambridge Quantum Computing +# Copyright 2019-2023 Cambridge Quantum Computing # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/pytket/extensions/qiskit/backends/__init__.py b/pytket/extensions/qiskit/backends/__init__.py index 205dce7e..05a60635 100644 --- a/pytket/extensions/qiskit/backends/__init__.py +++ b/pytket/extensions/qiskit/backends/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2019-2022 Cambridge Quantum Computing +# Copyright 2019-2023 Cambridge Quantum Computing # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/pytket/extensions/qiskit/backends/aer.py b/pytket/extensions/qiskit/backends/aer.py index b772f33d..0960fd3d 100644 --- a/pytket/extensions/qiskit/backends/aer.py +++ b/pytket/extensions/qiskit/backends/aer.py @@ -1,4 +1,4 @@ -# Copyright 2019-2022 Cambridge Quantum Computing +# Copyright 2019-2023 Cambridge Quantum Computing # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/pytket/extensions/qiskit/backends/config.py b/pytket/extensions/qiskit/backends/config.py index 69398f0c..eb204674 100644 --- a/pytket/extensions/qiskit/backends/config.py +++ b/pytket/extensions/qiskit/backends/config.py @@ -1,4 +1,4 @@ -# Copyright 2021-2022 Cambridge Quantum Computing +# Copyright 2021-2023 Cambridge Quantum Computing # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/pytket/extensions/qiskit/backends/ibm.py b/pytket/extensions/qiskit/backends/ibm.py index 32939e8b..b0a3c2e2 100644 --- a/pytket/extensions/qiskit/backends/ibm.py +++ b/pytket/extensions/qiskit/backends/ibm.py @@ -1,4 +1,4 @@ -# Copyright 2019-2022 Cambridge Quantum Computing +# Copyright 2019-2023 Cambridge Quantum Computing # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/pytket/extensions/qiskit/backends/ibmq_emulator.py b/pytket/extensions/qiskit/backends/ibmq_emulator.py index 471f341f..e29b9abf 100644 --- a/pytket/extensions/qiskit/backends/ibmq_emulator.py +++ b/pytket/extensions/qiskit/backends/ibmq_emulator.py @@ -1,4 +1,4 @@ -# Copyright 2019-2022 Cambridge Quantum Computing +# Copyright 2019-2023 Cambridge Quantum Computing # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/pytket/extensions/qiskit/qiskit_convert.py b/pytket/extensions/qiskit/qiskit_convert.py index 861f197a..d56d68c5 100644 --- a/pytket/extensions/qiskit/qiskit_convert.py +++ b/pytket/extensions/qiskit/qiskit_convert.py @@ -1,4 +1,4 @@ -# Copyright 2019-2022 Cambridge Quantum Computing +# Copyright 2019-2023 Cambridge Quantum Computing # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/pytket/extensions/qiskit/tket_backend.py b/pytket/extensions/qiskit/tket_backend.py index 2983d593..942a15e4 100644 --- a/pytket/extensions/qiskit/tket_backend.py +++ b/pytket/extensions/qiskit/tket_backend.py @@ -1,4 +1,4 @@ -# Copyright 2020-2022 Cambridge Quantum Computing +# Copyright 2020-2023 Cambridge Quantum Computing # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/pytket/extensions/qiskit/tket_job.py b/pytket/extensions/qiskit/tket_job.py index b2f8bc52..c248a8a6 100644 --- a/pytket/extensions/qiskit/tket_job.py +++ b/pytket/extensions/qiskit/tket_job.py @@ -1,4 +1,4 @@ -# Copyright 2020-2022 Cambridge Quantum Computing +# Copyright 2020-2023 Cambridge Quantum Computing # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/pytket/extensions/qiskit/tket_pass.py b/pytket/extensions/qiskit/tket_pass.py index 7baa1e65..3d135933 100644 --- a/pytket/extensions/qiskit/tket_pass.py +++ b/pytket/extensions/qiskit/tket_pass.py @@ -1,4 +1,4 @@ -# Copyright 2019-2022 Cambridge Quantum Computing +# Copyright 2019-2023 Cambridge Quantum Computing # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/setup.py b/setup.py index 77433ecf..79825e15 100644 --- a/setup.py +++ b/setup.py @@ -1,4 +1,4 @@ -# Copyright 2020-2022 Cambridge Quantum Computing +# Copyright 2020-2023 Cambridge Quantum Computing # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/tests/backend_test.py b/tests/backend_test.py index fd260d56..d3a54f61 100644 --- a/tests/backend_test.py +++ b/tests/backend_test.py @@ -1,4 +1,4 @@ -# Copyright 2019-2022 Cambridge Quantum Computing +# Copyright 2019-2023 Cambridge Quantum Computing # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/tests/conftest.py b/tests/conftest.py index bb3a5819..3a34a34e 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,4 +1,4 @@ -# Copyright 2020-2022 Cambridge Quantum Computing +# Copyright 2020-2023 Cambridge Quantum Computing # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/tests/qiskit_backend_test.py b/tests/qiskit_backend_test.py index 38429d00..895d73c4 100644 --- a/tests/qiskit_backend_test.py +++ b/tests/qiskit_backend_test.py @@ -1,4 +1,4 @@ -# Copyright 2020-2022 Cambridge Quantum Computing +# Copyright 2020-2023 Cambridge Quantum Computing # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/tests/qiskit_convert_test.py b/tests/qiskit_convert_test.py index 6d690b9f..1aa6e58c 100644 --- a/tests/qiskit_convert_test.py +++ b/tests/qiskit_convert_test.py @@ -1,4 +1,4 @@ -# Copyright 2019-2022 Cambridge Quantum Computing +# Copyright 2019-2023 Cambridge Quantum Computing # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. From d938cebd72c16692124e869dde75e40d0b968766 Mon Sep 17 00:00:00 2001 From: CalMacCQ <93673602+CalMacCQ@users.noreply.github.com> Date: Tue, 10 Jan 2023 10:41:08 +0000 Subject: [PATCH 12/20] Feature/convert more controlled gates (#50) * support CnY, CnZ, Fix CnRy and use QControlBox * add test for CnRy, CnY and CnZ * add test for QControlBox conversion * fix import * remove MCMT import * split string onto two lines * suggested changes and rename i variable * don't use num_controls variable * update changelog * Update docs/changelog.rst Co-authored-by: Alec Edgington <54802828+cqc-alec@users.noreply.github.com> Co-authored-by: Alec Edgington <54802828+cqc-alec@users.noreply.github.com> Co-authored-by: cqc-melf <70640934+cqc-melf@users.noreply.github.com> --- docs/changelog.rst | 1 + pytket/extensions/qiskit/qiskit_convert.py | 97 ++++++++++++++-------- tests/qiskit_convert_test.py | 42 ++++++++++ 3 files changed, 106 insertions(+), 34 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 675e35c9..350f4bac 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -4,6 +4,7 @@ Changelog Unreleased ---------- +* Handle more multi-controlled gates in ``tk_to_qiskit`` and ``qiskit_to_tk`` converters (including CnY and CnZ). * Drop support for Python 3.8; add support for 3.11. 0.33.0 (December 2022) diff --git a/pytket/extensions/qiskit/qiskit_convert.py b/pytket/extensions/qiskit/qiskit_convert.py index d56d68c5..b5d5889d 100644 --- a/pytket/extensions/qiskit/qiskit_convert.py +++ b/pytket/extensions/qiskit/qiskit_convert.py @@ -53,7 +53,7 @@ ParameterExpression, Reset, ) -from qiskit.circuit.library import CRYGate, RYGate, MCMT, PauliEvolutionGate # type: ignore +from qiskit.circuit.library import CRYGate, RYGate, PauliEvolutionGate # type: ignore from qiskit.extensions.unitary import UnitaryGate # type: ignore from pytket.circuit import ( # type: ignore @@ -67,6 +67,7 @@ CustomGateDef, Bit, Qubit, + QControlBox, ) from pytket._tket.circuit import _TEMP_BIT_NAME # type: ignore from pytket.pauli import Pauli, QubitPauliString # type: ignore @@ -271,42 +272,59 @@ def circuit(self) -> Circuit: return self.tkc def add_qiskit_data(self, data: "QuantumCircuitData") -> None: - for i, qargs, cargs in data: + for instr, qargs, cargs in data: condition_kwargs = {} - if i.condition is not None: - cond_reg = self.cregmap[i.condition[0]] + if instr.condition is not None: + cond_reg = self.cregmap[instr.condition[0]] condition_kwargs = { "condition_bits": [cond_reg[k] for k in range(len(cond_reg))], - "condition_value": i.condition[1], + "condition_value": instr.condition[1], } optype = None - if type(i) == ControlledGate: - if type(i.base_gate) == qiskit_gates.RYGate: + if type(instr) == ControlledGate: + if type(instr.base_gate) == qiskit_gates.RYGate: optype = OpType.CnRy + elif type(instr.base_gate) == qiskit_gates.YGate: + optype = OpType.CnY + elif type(instr.base_gate) == qiskit_gates.ZGate: + optype = OpType.CnZ else: - # Maybe handle multicontrolled gates in a more general way, - # but for now just do CnRy - raise NotImplementedError( - "qiskit ControlledGate with " - + "base gate {} not implemented".format(i.base_gate) - ) - elif type(i) == PauliEvolutionGate: + if type(instr.base_gate) in _known_qiskit_gate: + optype = OpType.QControlBox # QControlBox case handled below + else: + raise NotImplementedError( + f"qiskit ControlledGate with base gate {instr.base_gate}" + + "not implemented" + ) + elif type(instr) == PauliEvolutionGate: pass # Special handling below else: - optype = _known_qiskit_gate[type(i)] + optype = _known_qiskit_gate[type(instr)] qubits = [self.qbmap[qbit] for qbit in qargs] bits = [self.cbmap[bit] for bit in cargs] if optype == OpType.Unitary2qBox: - u = i.to_matrix() + u = instr.to_matrix() ubox = Unitary2qBox(u) # Note reversal of qubits, to account for endianness (pytket unitaries # are ILO-BE == DLO-LE; qiskit unitaries are ILO-LE == DLO-BE). self.tkc.add_unitary2qbox( ubox, qubits[1], qubits[0], **condition_kwargs ) - elif type(i) == PauliEvolutionGate: - qpo = _qpo_from_peg(i, qubits) + elif optype == OpType.QControlBox: + base_tket_gate = _known_qiskit_gate[type(instr.base_gate)] + params = [param_to_tk(p) for p in instr.base_gate.params] + n_base_qubits = instr.base_gate.num_qubits + sub_circ = Circuit(n_base_qubits) + # use base gate name for the CircBox (shows in renderer) + sub_circ.name = instr.base_gate.name.capitalize() + sub_circ.add_gate(base_tket_gate, params, list(range(n_base_qubits))) + c_box = CircBox(sub_circ) + q_ctrl_box = QControlBox(c_box, instr.num_ctrl_qubits) + self.tkc.add_qcontrolbox(q_ctrl_box, qubits) + + elif type(instr) == PauliEvolutionGate: + qpo = _qpo_from_peg(instr, qubits) empty_circ = Circuit(len(qargs)) circ = gen_term_sequence_circuit(qpo, empty_circ) ccbox = CircBox(circ) @@ -314,12 +332,18 @@ def add_qiskit_data(self, data: "QuantumCircuitData") -> None: elif optype == OpType.Barrier: self.tkc.add_barrier(qubits) elif optype in (OpType.CircBox, OpType.CustomGate): - qregs = [QuantumRegister(i.num_qubits, "q")] if i.num_qubits > 0 else [] + qregs = ( + [QuantumRegister(instr.num_qubits, "q")] + if instr.num_qubits > 0 + else [] + ) cregs = ( - [ClassicalRegister(i.num_clbits, "c")] if i.num_clbits > 0 else [] + [ClassicalRegister(instr.num_clbits, "c")] + if instr.num_clbits > 0 + else [] ) builder = CircuitBuilder(qregs, cregs) - builder.add_qiskit_data(i.definition) + builder.add_qiskit_data(instr.definition) subc = builder.circuit() if optype == OpType.CircBox: cbox = CircBox(subc) @@ -327,23 +351,23 @@ def add_qiskit_data(self, data: "QuantumCircuitData") -> None: else: # warning, this will catch all `Gate` instances # that were not picked up as a subclass in _known_qiskit_gate - params = [param_to_tk(p) for p in i.params] + params = [param_to_tk(p) for p in instr.params] gate_def = CustomGateDef.define( - i.name, subc, list(subc.free_symbols()) + instr.name, subc, list(subc.free_symbols()) ) self.tkc.add_custom_gate(gate_def, params, qubits + bits) - elif optype == OpType.CU3 and type(i) == qiskit_gates.CUGate: - if i.params[-1] == 0: + elif optype == OpType.CU3 and type(instr) == qiskit_gates.CUGate: + if instr.params[-1] == 0: self.tkc.add_gate( optype, - [param_to_tk(p) for p in i.params[:-1]], + [param_to_tk(p) for p in instr.params[:-1]], qubits, **condition_kwargs, ) else: raise NotImplementedError("CUGate with nonzero phase") else: - params = [param_to_tk(p) for p in i.params] + params = [param_to_tk(p) for p in instr.params] self.tkc.add_gate(optype, params, qubits + bits, **condition_kwargs) @@ -500,8 +524,10 @@ def append_tk_command_to_qiskit( qargs = [qregmap[q.reg_name][q.index[0]] for q in args] if optype == OpType.CnX: return qcirc.mcx(qargs[:-1], qargs[-1]) - - # special case + if optype == OpType.CnY: + return qcirc.append(qiskit_gates.YGate().control(len(qargs) - 1), qargs) + if optype == OpType.CnZ: + return qcirc.append(qiskit_gates.ZGate().control(len(qargs) - 1), qargs) if optype == OpType.CnRy: # might as well do a bit more checking assert len(op.params) == 1 @@ -511,10 +537,7 @@ def append_tk_command_to_qiskit( # presumably more efficient; single control only new_gate = CRYGate(alpha) else: - new_ry_gate = RYGate(alpha) - new_gate = MCMT( - gate=new_ry_gate, num_ctrl_qubits=len(qargs) - 1, num_target_qubits=1 - ) + new_gate = RYGate(alpha).control(len(qargs) - 1) qcirc.append(new_gate, qargs) return qcirc @@ -556,6 +579,12 @@ def append_tk_command_to_qiskit( # The set of tket gates that can be converted directly to qiskit gates _supported_tket_gates = set(_known_gate_rev_phase.keys()) +_additional_multi_controlled_gates = {OpType.CnY, OpType.CnZ, OpType.CnRy} + +# tket gates which are protected from being decomposed in the rebase +_protected_tket_gates = _supported_tket_gates | _additional_multi_controlled_gates + + Param = Union[float, "sympy.Expr"] # Type for TK1 and U3 parameters # Use the U3 gate for tk1_replacement as this is a member of _supported_tket_gates @@ -566,7 +595,7 @@ def _tk1_to_u3(a: Param, b: Param, c: Param) -> Circuit: # This is a rebase to the set of tket gates which have an exact substitution in qiskit -supported_gate_rebase = RebaseCustom(_supported_tket_gates, _cx_replacement, _tk1_to_u3) +supported_gate_rebase = RebaseCustom(_protected_tket_gates, _cx_replacement, _tk1_to_u3) def tk_to_qiskit( diff --git a/tests/qiskit_convert_test.py b/tests/qiskit_convert_test.py index 1aa6e58c..9c080a9b 100644 --- a/tests/qiskit_convert_test.py +++ b/tests/qiskit_convert_test.py @@ -31,6 +31,7 @@ from qiskit.quantum_info import Pauli # type: ignore from qiskit.transpiler import PassManager # type: ignore from qiskit.circuit.library import RYGate, MCMT # type: ignore +import qiskit.circuit.library.standard_gates as qiskit_gates # type: ignore from qiskit.circuit import Parameter # type: ignore from pytket.circuit import ( # type: ignore Circuit, @@ -729,3 +730,44 @@ def test_parametrized_evolution() -> None: qc: QuantumCircuit = evolved_circ_op.primitive tk_qc: Circuit = qiskit_to_tk(qc) assert len(tk_qc.free_symbols()) == 1 + + +def test_multicontrolled_gate_conversion() -> None: + my_qc = QuantumCircuit(4) + my_qc.append(qiskit_gates.YGate().control(3), [0, 1, 2, 3]) + my_qc.append(qiskit_gates.RYGate(0.25).control(3), [0, 1, 2, 3]) + my_qc.append(qiskit_gates.ZGate().control(3), [0, 1, 2, 3]) + my_tkc = qiskit_to_tk(my_qc) + my_tkc.add_gate(OpType.CnRy, [0.95], [0, 1, 2, 3]) + my_tkc.add_gate(OpType.CnZ, [1, 2, 3, 0]) + my_tkc.add_gate(OpType.CnY, [0, 1, 3, 2]) + unitary_before = my_tkc.get_unitary() + assert my_tkc.n_gates_of_type(OpType.CnY) == 2 + assert my_tkc.n_gates_of_type(OpType.CnZ) == 2 + assert my_tkc.n_gates_of_type(OpType.CnRy) == 2 + my_new_qc = tk_to_qiskit(my_tkc) + qiskit_ops = my_new_qc.count_ops() + assert qiskit_ops["c3y"] and qiskit_ops["c3z"] and qiskit_ops["c3ry"] == 2 + tcirc = qiskit_to_tk(my_new_qc) + unitary_after = tcirc.get_unitary() + assert compare_unitaries(unitary_before, unitary_after) + + +def test_qcontrolbox_conversion() -> None: + qr = QuantumRegister(3) + qc = QuantumCircuit(qr) + c2h_gate = qiskit_gates.HGate().control(2) + qc.append(c2h_gate, qr) + c = qiskit_to_tk(qc) + assert c.n_gates == 1 + assert c.n_gates_of_type(OpType.QControlBox) == 1 + c3rx_gate = qiskit_gates.RXGate(0.7).control(3) + c3rz_gate = qiskit_gates.RZGate(pi / 4).control(3) + c2rzz_gate = qiskit_gates.RZZGate(pi / 3).control(2) + qc2 = QuantumCircuit(4) + qc2.append(c3rz_gate, [0, 1, 3, 2]) + qc2.append(c3rx_gate, [0, 1, 2, 3]) + qc2.append(c2rzz_gate, [0, 1, 2, 3]) + tkc2 = qiskit_to_tk(qc2) + assert tkc2.n_gates == 3 + assert tkc2.n_gates_of_type(OpType.QControlBox) == 3 From e17ae26a43428f232ac1e8f50beb84107c9094b1 Mon Sep 17 00:00:00 2001 From: Alec Edgington <54802828+cqc-alec@users.noreply.github.com> Date: Fri, 13 Jan 2023 17:45:23 +0000 Subject: [PATCH 13/20] Fix (and simplify) handling of endianness and unit ordering (#55) --- docs/changelog.rst | 2 ++ pytket/extensions/qiskit/backends/aer.py | 8 ++--- pytket/extensions/qiskit/qiskit_convert.py | 12 +------ pytket/extensions/qiskit/result_convert.py | 39 +++++----------------- tests/backend_test.py | 11 ++++++ tests/qiskit_convert_test.py | 13 +------- 6 files changed, 27 insertions(+), 58 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 350f4bac..f1712fd3 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -6,6 +6,8 @@ Unreleased * Handle more multi-controlled gates in ``tk_to_qiskit`` and ``qiskit_to_tk`` converters (including CnY and CnZ). * Drop support for Python 3.8; add support for 3.11. +* Fix ordering of registers in statevector simulation results. +* Remove ``reverse_index`` argument in ``tk_to_qiskit()``. 0.33.0 (December 2022) ---------------------- diff --git a/pytket/extensions/qiskit/backends/aer.py b/pytket/extensions/qiskit/backends/aer.py index 0960fd3d..1d0da981 100644 --- a/pytket/extensions/qiskit/backends/aer.py +++ b/pytket/extensions/qiskit/backends/aer.py @@ -160,14 +160,12 @@ def process_circuits( handle_list: List[Optional[ResultHandle]] = [None] * len(circuits) circuit_batches, batch_order = _batch_circuits(circuits, n_shots_list) - reverse_index = replace_implicit_swaps = ( - self.supports_state or self.supports_unitary - ) + replace_implicit_swaps = self.supports_state or self.supports_unitary for (n_shots, batch), indices in zip(circuit_batches, batch_order): qcs = [] for tkc in batch: - qc = tk_to_qiskit(tkc, reverse_index, replace_implicit_swaps) + qc = tk_to_qiskit(tkc, replace_implicit_swaps) if self.supports_state: qc.save_state() elif self.supports_unitary: @@ -350,7 +348,7 @@ def get_result(self, handle: ResultHandle, **kwargs: KwargTypes) -> BackendResul raise CircuitNotRunError(handle) res = job.result() - backresults = qiskit_result_to_backendresult(res, reverse_index=False) + backresults = qiskit_result_to_backendresult(res) for circ_index, backres in enumerate(backresults): newhandle = ResultHandle(handle[0], circ_index) self._cache[newhandle]["result"] = backres diff --git a/pytket/extensions/qiskit/qiskit_convert.py b/pytket/extensions/qiskit/qiskit_convert.py index b5d5889d..b296d7b9 100644 --- a/pytket/extensions/qiskit/qiskit_convert.py +++ b/pytket/extensions/qiskit/qiskit_convert.py @@ -599,25 +599,17 @@ def _tk1_to_u3(a: Param, b: Param, c: Param) -> Circuit: def tk_to_qiskit( - tkcirc: Circuit, reverse_index: bool = False, replace_implicit_swaps: bool = False + tkcirc: Circuit, replace_implicit_swaps: bool = False ) -> QuantumCircuit: """ Converts a pytket :py:class:`Circuit` to a qiskit :py:class:`qiskit.QuantumCircuit`. - In many cases there will be a qiskit gate to exactly replace each tket gate. If no exact replacement can be found for a part of the circuit then an equivalent circuit will be returned using the tket gates which are supported in qiskit. - As tket and qiskit use different qubit ordering conventions - there is the option to reverse the bit indices of the returned circuit - using the reverse_index parameter. - - :param tkcirc: A :py:class:`Circuit` to be converted :type tkcirc: Circuit - :param reverse_index: Reverse the order of wires - :type reverse_index: bool :param replace_implicit_swaps: Implement implicit permutation by adding SWAPs to the end of the circuit. :type replace_implicit_swaps: bool @@ -680,8 +672,6 @@ def tk_to_qiskit( updates[p] = new_p qcirc.assign_parameters(updates, inplace=True) - if reverse_index: - return qcirc.reverse_bits() return qcirc diff --git a/pytket/extensions/qiskit/result_convert.py b/pytket/extensions/qiskit/result_convert.py index 1920b38a..c97451aa 100644 --- a/pytket/extensions/qiskit/result_convert.py +++ b/pytket/extensions/qiskit/result_convert.py @@ -3,7 +3,6 @@ Iterator, Sequence, Set, - Type, Tuple, Optional, Dict, @@ -22,21 +21,6 @@ from pytket.utils.outcomearray import OutcomeArray -def _gen_uids( - labels: Sequence[Tuple[str, int]], derived: Type[UnitID], reverse_index: bool = True -) -> List[UnitID]: - # sorted_labels = sorted(labels, key=lambda x: x[0]) - # see - # https://github.com/Qiskit/qiskit-terra/blob/6148588d25a5a0e96744b541bb0da676779f3204/qiskit/result/postprocess.py#L36 - if reverse_index: - return [ - derived(name, index) - for name, size in reversed(labels) - for index in reversed(range(size)) # reversed to account for little-endian - ] - return [derived(name, index) for name, size in labels for index in range(size)] - - def _get_registers_from_uids(uids: List[UnitID]) -> Dict[str, Set[UnitID]]: registers: Dict[str, Set[UnitID]] = defaultdict(set) for uid in uids: @@ -65,7 +49,7 @@ def _qiskit_ordered_uids(uids: List[UnitID]) -> List[UnitID]: def _hex_to_outar(hexes: Sequence[str], width: int) -> OutcomeArray: ints = [int(hexst, 16) for hexst in hexes] - return OutcomeArray.from_ints(ints, width) + return OutcomeArray.from_ints(ints, width, big_endian=False) # An empty ExperimentResult can be an empty dict, but it can also be a dict @@ -89,19 +73,18 @@ def _result_is_empty_shots(result: ExperimentResult) -> bool: def qiskit_experimentresult_to_backendresult( result: ExperimentResult, ppcirc: Optional[Circuit] = None, - reverse_index: bool = True, ) -> BackendResult: header = result.header width = header.memory_slots c_bits = ( - _gen_uids(header.creg_sizes, Bit, reverse_index) - if hasattr(header, "creg_sizes") + [Bit(name, index) for name, index in header.clbit_labels] + if hasattr(header, "clbit_labels") else None ) q_bits = ( - _gen_uids(header.qreg_sizes, Qubit, reverse_index) - if hasattr(header, "qreg_sizes") + [Qubit(name, index) for name, index in header.qubit_labels] + if hasattr(header, "qubit_labels") else None ) shots, counts, state, unitary = (None,) * 4 @@ -125,10 +108,10 @@ def qiskit_experimentresult_to_backendresult( ) if "statevector" in datadict: - state = np.asarray(datadict["statevector"]) + state = datadict["statevector"].reverse_qargs().data if "unitary" in datadict: - unitary = np.asarray(datadict["unitary"]) + unitary = datadict["unitary"].reverse_qargs().data return BackendResult( c_bits=c_bits, @@ -141,13 +124,9 @@ def qiskit_experimentresult_to_backendresult( ) -def qiskit_result_to_backendresult( - res: Result, reverse_index: bool = True -) -> Iterator[BackendResult]: +def qiskit_result_to_backendresult(res: Result) -> Iterator[BackendResult]: for result in res.results: - yield qiskit_experimentresult_to_backendresult( - result, reverse_index=reverse_index - ) + yield qiskit_experimentresult_to_backendresult(result) def backendresult_to_qiskit_resultdata( diff --git a/tests/backend_test.py b/tests/backend_test.py index d3a54f61..e02403e3 100644 --- a/tests/backend_test.py +++ b/tests/backend_test.py @@ -1161,3 +1161,14 @@ def test_backendinfo_serialization2() -> None: s = json.dumps(backend_info_json) backend_info_json1 = json.loads(s) assert backend_info_json == backend_info_json1 + + +def test_sim_qubit_order() -> None: + # https://github.com/CQCL/pytket-qiskit/issues/54 + backend = AerStateBackend() + circ = Circuit() + circ.add_q_register("a", 1) + circ.add_q_register("b", 1) + circ.X(Qubit("a", 0)) + s = backend.run_circuit(circ).get_state() + assert np.isclose(abs(s[2]), 1.0) diff --git a/tests/qiskit_convert_test.py b/tests/qiskit_convert_test.py index 9c080a9b..3e503dee 100644 --- a/tests/qiskit_convert_test.py +++ b/tests/qiskit_convert_test.py @@ -46,11 +46,7 @@ from pytket.extensions.qiskit import tk_to_qiskit, qiskit_to_tk from pytket.extensions.qiskit.qiskit_convert import _gate_str_2_optype from pytket.extensions.qiskit.tket_pass import TketPass, TketAutoPass -from pytket.extensions.qiskit.result_convert import ( - qiskit_result_to_backendresult, - backendresult_to_qiskit_resultdata, - _gen_uids, -) +from pytket.extensions.qiskit.result_convert import qiskit_result_to_backendresult from pytket.passes import RebaseTket, DecomposeBoxes, FullPeepholeOptimise, SequencePass # type: ignore from pytket.utils.results import ( compare_statevectors, @@ -483,13 +479,6 @@ def test_convert_result() -> None: assert tk_res.get_counts(one_bits) == Counter({(1, 1): 10}) assert tk_res.get_counts(zero_bits) == Counter({(0, 0, 0, 0, 0): 10}) - qbits = _gen_uids([(reg.name, reg.size) for reg in (qr1, qr2)], Qubit) - cbits = _gen_uids([(reg.name, reg.size) for reg in (cr, cr2)], Bit) - - assert qisk_result.results[0].data.to_dict() == backendresult_to_qiskit_resultdata( - tk_res, cbits, qbits, None - ) - def add_x( qbit: int, qr: QuantumRegister, circuits: List[Union[Circuit, QuantumCircuit]] From 43adf192f90f894f80c1e267140414dd19f85c41 Mon Sep 17 00:00:00 2001 From: cqc-melf <70640934+cqc-melf@users.noreply.github.com> Date: Tue, 17 Jan 2023 10:28:24 +0000 Subject: [PATCH 14/20] fix python version in docs build (#57) --- .github/workflows/docs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 81ccfe60..9b18e366 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -17,7 +17,7 @@ jobs: - name: Set up Python 3.10 uses: actions/setup-python@v4 with: - python-version: 3.10 + python-version: '3.10' - name: Upgrade pip and install wheel run: pip install --upgrade pip wheel - name: Install pytket qiskit From 1893d3787121166949dcb386d21e875c08ebb943 Mon Sep 17 00:00:00 2001 From: CalMacCQ <93673602+CalMacCQ@users.noreply.github.com> Date: Tue, 17 Jan 2023 19:17:50 +0000 Subject: [PATCH 15/20] Update docs (#56) * update .gitignore * update outdated IBMQEmulator documentation * use borland pygments and sphinx-copybutton * rename quantinuum logo * use #544d4d grey instead of blue for API docs * update build-docs * fix index typo * shorten string * typo --- .../{Quantinuum_logo2.png => Quantinuum_logo.png} | Bin .github/workflows/docs/build-docs | 4 ++-- .github/workflows/docs/conf.py | 5 +++-- .github/workflows/docs/requirements.txt | 1 + .gitignore | 1 + docs/_static/custom.css | 2 +- docs/intro.txt | 2 +- pytket/extensions/qiskit/backends/ibmq_emulator.py | 2 +- 8 files changed, 10 insertions(+), 7 deletions(-) rename .github/workflows/docs/{Quantinuum_logo2.png => Quantinuum_logo.png} (100%) diff --git a/.github/workflows/docs/Quantinuum_logo2.png b/.github/workflows/docs/Quantinuum_logo.png similarity index 100% rename from .github/workflows/docs/Quantinuum_logo2.png rename to .github/workflows/docs/Quantinuum_logo.png diff --git a/.github/workflows/docs/build-docs b/.github/workflows/docs/build-docs index 76657f5f..89e4d5ba 100755 --- a/.github/workflows/docs/build-docs +++ b/.github/workflows/docs/build-docs @@ -40,9 +40,9 @@ def build_module_docs(): mod_docs = MODULES_DIR / "docs" mod_build = mod_docs / "build" conf_copy = mod_docs / "conf.py" - logo_copy = mod_docs / "Quantinuum_logo2.png" + logo_copy = mod_docs / "Quantinuum_logo.png" shutil.copy(DOCS_DIR / "conf.py", conf_copy) - shutil.copy(DOCS_DIR / "Quantinuum_logo2.png", logo_copy) + shutil.copy(DOCS_DIR / "Quantinuum_logo.png", logo_copy) remove_dir(mod_build) index_rst = mod_docs / "index.rst" with open(mod_docs / "intro.txt", "r") as f: diff --git a/.github/workflows/docs/conf.py b/.github/workflows/docs/conf.py index 1195c2eb..a87ef2c2 100644 --- a/.github/workflows/docs/conf.py +++ b/.github/workflows/docs/conf.py @@ -10,9 +10,10 @@ "sphinx.ext.autosummary", "sphinx.ext.intersphinx", "sphinx.ext.mathjax", + "sphinx_copybutton", ] -pygments_style = "pastie" +pygments_style = "borland" html_theme = "sphinx_book_theme" @@ -26,7 +27,7 @@ html_css_files = ["custom.css"] -html_logo = "Quantinuum_logo2.png" +html_logo = "Quantinuum_logo.png" # -- Extension configuration ------------------------------------------------- diff --git a/.github/workflows/docs/requirements.txt b/.github/workflows/docs/requirements.txt index 382fc378..31e91260 100644 --- a/.github/workflows/docs/requirements.txt +++ b/.github/workflows/docs/requirements.txt @@ -1,2 +1,3 @@ sphinx ~= 4.3.2 sphinx_book_theme +sphinx-copybutton diff --git a/.gitignore b/.gitignore index 7e842891..fb1c8136 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ build dist *.pyc .vscode +.venv .mypy_cache .hypothesis obj diff --git a/docs/_static/custom.css b/docs/_static/custom.css index 6552cb58..732d595d 100644 --- a/docs/_static/custom.css +++ b/docs/_static/custom.css @@ -32,7 +32,7 @@ a:visited, .sig-param, .std.std-ref, a { - color: #2563EB; + color: #544d4d; } :root { diff --git a/docs/intro.txt b/docs/intro.txt index 61d70143..1ed1af80 100644 --- a/docs/intro.txt +++ b/docs/intro.txt @@ -76,7 +76,7 @@ and several types of simulator. - Unitary simulator * [1] ``AerBackend`` is noiseless by default and has no architecture. However it can accept a user defined ``NoiseModel`` and ``Architecture``. -* In addition to the backends above the pytket-qiskit extension also has the ``TketBackend``. This allows a tket ``Backend``s and compilation passes to be used directly through qiskit. see the `Notebook example `_ on qiskit integration. +* In addition to the backends above the pytket-qiskit extension also has the ``TketBackend``. This allows a tket ``Backend`` to be used directly through qiskit. see the `notebook example `_ on qiskit integration. Default Compilation =================== diff --git a/pytket/extensions/qiskit/backends/ibmq_emulator.py b/pytket/extensions/qiskit/backends/ibmq_emulator.py index e29b9abf..31f376b6 100644 --- a/pytket/extensions/qiskit/backends/ibmq_emulator.py +++ b/pytket/extensions/qiskit/backends/ibmq_emulator.py @@ -55,7 +55,7 @@ class IBMQEmulatorBackend(Backend): - """A backend which uses the ibmq_qasm_simulator to emulate the behaviour of + """A backend which uses the AerBackend simulator to emulate the behaviour of IBMQBackend. Performs the same compilation and predicate checks as IBMQBackend. Requires a valid IBMQ account. From 157a945ba6c77d58d2c1c6eac229367efd256374 Mon Sep 17 00:00:00 2001 From: melf Date: Wed, 18 Jan 2023 10:10:33 +0000 Subject: [PATCH 16/20] update version --- _metadata.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_metadata.py b/_metadata.py index a8e89001..0e9a7b14 100644 --- a/_metadata.py +++ b/_metadata.py @@ -1,2 +1,2 @@ -__extension_version__ = "0.33.0" +__extension_version__ = "0.34.0" __extension_name__ = "pytket-qiskit" From 8ba85366cd5c6c888f7a9c233a923043bf165d91 Mon Sep 17 00:00:00 2001 From: melf Date: Wed, 18 Jan 2023 10:10:51 +0000 Subject: [PATCH 17/20] update changelog --- docs/changelog.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index f1712fd3..386025f2 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1,8 +1,8 @@ Changelog ~~~~~~~~~ -Unreleased ----------- +0.34.0 (January 2022) +--------------------- * Handle more multi-controlled gates in ``tk_to_qiskit`` and ``qiskit_to_tk`` converters (including CnY and CnZ). * Drop support for Python 3.8; add support for 3.11. From 8530c0ab2bcdafd66c962f25420069a5d9c25279 Mon Sep 17 00:00:00 2001 From: melf Date: Wed, 18 Jan 2023 10:11:15 +0000 Subject: [PATCH 18/20] update pytket version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 79825e15..82cf85da 100644 --- a/setup.py +++ b/setup.py @@ -44,7 +44,7 @@ packages=find_namespace_packages(include=["pytket.*"]), include_package_data=True, install_requires=[ - "pytket == 1.11.0rc0", + "pytket ~= 1.11", "qiskit ~= 0.39.0", "qiskit_ibm_runtime ~= 0.8.0", ], From 5dee34cf1a7e7e47a804a4c5a720d7f9a8409ca7 Mon Sep 17 00:00:00 2001 From: melf Date: Wed, 18 Jan 2023 10:12:33 +0000 Subject: [PATCH 19/20] update pytket version in changelog --- docs/changelog.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/changelog.rst b/docs/changelog.rst index 386025f2..8afc818e 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -8,6 +8,7 @@ Changelog * Drop support for Python 3.8; add support for 3.11. * Fix ordering of registers in statevector simulation results. * Remove ``reverse_index`` argument in ``tk_to_qiskit()``. +* Updated pytket version requirement to 1.11. 0.33.0 (December 2022) ---------------------- From a5d7a89cbe4cd83bc8e78550aa086786c8f026e1 Mon Sep 17 00:00:00 2001 From: cqc-melf <70640934+cqc-melf@users.noreply.github.com> Date: Wed, 18 Jan 2023 10:21:03 +0000 Subject: [PATCH 20/20] update changelog to 2023 --- docs/changelog.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 8afc818e..917f2f57 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1,7 +1,7 @@ Changelog ~~~~~~~~~ -0.34.0 (January 2022) +0.34.0 (January 2023) --------------------- * Handle more multi-controlled gates in ``tk_to_qiskit`` and ``qiskit_to_tk`` converters (including CnY and CnZ).