diff --git a/poetry.lock b/poetry.lock index 186f9c1a76..b5f2bbf93e 100644 --- a/poetry.lock +++ b/poetry.lock @@ -190,8 +190,7 @@ version = "2.0.0" description = "Foreign Function Interface for Python calling C code." optional = false python-versions = ">=3.9" -groups = ["docs"] -markers = "implementation_name == \"pypy\"" +groups = ["docs", "tests"] files = [ {file = "cffi-2.0.0-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:0cf2d91ecc3fcc0625c2c530fe004f82c110405f101548512cce44322fa8ac44"}, {file = "cffi-2.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f73b96c41e3b2adedc34a7356e64c8eb96e03a3782b535e043a986276ce12a49"}, @@ -278,6 +277,7 @@ files = [ {file = "cffi-2.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:b882b3df248017dba09d6b16defe9b5c407fe32fc7c65a9c69798e6175601be9"}, {file = "cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529"}, ] +markers = {docs = "implementation_name == \"pypy\""} [package.dependencies] pycparser = {version = "*", markers = "implementation_name != \"PyPy\""} @@ -406,6 +406,27 @@ files = [ ] markers = {main = "extra == \"qir\" or extra == \"cudaq\""} +[[package]] +name = "clarabel" +version = "0.11.1" +description = "Clarabel Conic Interior Point Solver for Rust / Python" +optional = false +python-versions = ">=3.9" +groups = ["tests"] +files = [ + {file = "clarabel-0.11.1-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:c39160e4222040f051f2a0598691c4f9126b4d17f5b9e7678f76c71d611e12d8"}, + {file = "clarabel-0.11.1-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:8963687ee250d27310d139eea5a6816f9c3ae31f33691b56579ca4f0f0b64b63"}, + {file = "clarabel-0.11.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4837b9d0db01e98239f04b1e3526a6cf568529d3c19a8b3f591befdc467f9bb"}, + {file = "clarabel-0.11.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c8c41aaa6f3f8c0f3bd9d86c3e568dcaee079562c075bd2ec9fb3a80287380ef"}, + {file = "clarabel-0.11.1-cp39-abi3-win_amd64.whl", hash = "sha256:557d5148a4377ae1980b65d00605ae870a8f34f95f0f6a41e04aa6d3edf67148"}, + {file = "clarabel-0.11.1.tar.gz", hash = "sha256:e7c41c47f0e59aeab99aefff9e58af4a8753ee5269bbeecbd5526fc6f41b9598"}, +] + +[package.dependencies] +cffi = "*" +numpy = "*" +scipy = "*" + [[package]] name = "cma" version = "3.4.0" @@ -1023,6 +1044,143 @@ files = [ [package.dependencies] cutensor-cu12 = ">=2.3.1,<3" +[[package]] +name = "cvxpy" +version = "1.7.5" +description = "A domain-specific language for modeling convex optimization problems in Python." +optional = false +python-versions = ">=3.9" +groups = ["tests"] +markers = "python_version == \"3.10\"" +files = [ + {file = "cvxpy-1.7.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a9938ea90898da51b1129ba9c185cd774d83fdbea3eb0099cd86d47e37ed5297"}, + {file = "cvxpy-1.7.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f0a4818665c3231a5a35001c41f691471b35e2231295f85ddf6044f3982f2f88"}, + {file = "cvxpy-1.7.5-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bd50c29539fb39cc53de93a689e73019cd26c1b80fc29aba7a63cc0ae5ec7b01"}, + {file = "cvxpy-1.7.5-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8c05116b9633747857758ca105f2744a9c27bb9dbed771087e5712c4405f2517"}, + {file = "cvxpy-1.7.5-cp310-cp310-win_amd64.whl", hash = "sha256:3207a3cf7360d176fe7f1dfe172846d7a3befd9b1db604c0082e4fa242373aff"}, + {file = "cvxpy-1.7.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0df3bc1aee0431ee6419cfc77fb7543ad7588150b9bb5d8ef44da7a76770ba1d"}, + {file = "cvxpy-1.7.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:86876084d1874c837b6dc9dad61ba1e873e979d06462fdc149a6ba0b067a8638"}, + {file = "cvxpy-1.7.5-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7633c2a369188aa0fa3df4a767267774257c9dba71ac8e5b9e8eefb17e2613f8"}, + {file = "cvxpy-1.7.5-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9f9d93892f0805a9fa1b0702ca4c6d3b8deb056ab0140a58f41b933fe8f28aae"}, + {file = "cvxpy-1.7.5-cp311-cp311-win_amd64.whl", hash = "sha256:911575f28ecd3fd913165354aad24ebfe264a59a1d86a2c0e296177c6a13092f"}, + {file = "cvxpy-1.7.5-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:6c397b86ef2109b99ec10d4fb144a826af840e1111167d307c52c96719ac5f57"}, + {file = "cvxpy-1.7.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:20bacc1781b5b168e0272688d8652cef7433a4d07dea2482e790e1bdcee4f46e"}, + {file = "cvxpy-1.7.5-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:573396b116cff9c46952c885d9c06db1fc7a6e4838feb2fcba2982d521140205"}, + {file = "cvxpy-1.7.5-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5926ca62e6998f160ecf4c4acc139eb0fe8c28453c904e1c3d7b93b5b40e4303"}, + {file = "cvxpy-1.7.5-cp312-cp312-win_amd64.whl", hash = "sha256:e8308b88b515567d7a5a5762c8e7c971692e1022a924613d808648916c20834b"}, + {file = "cvxpy-1.7.5-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:56718a649e7d7c593becb1d088d7c1c0f073df821e20baead80e3662a083a34f"}, + {file = "cvxpy-1.7.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ca12e393acd83973ec56b5ac9194db403a4f99af451d4ea041f27b3e432acd8d"}, + {file = "cvxpy-1.7.5-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ae3d4b7498a1419689566fa6e20d9c5479c384ca950ee7403c51e70425059aa5"}, + {file = "cvxpy-1.7.5-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:13ed867017ebe3c6bf2e34aa108208237eb9d655b9897687af8c98ed282f7004"}, + {file = "cvxpy-1.7.5-cp313-cp313-win_amd64.whl", hash = "sha256:d71688a5725ee61666cc9cf456f048d0016ae96c206c1030af06f3ad803b5d22"}, + {file = "cvxpy-1.7.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:de23fad688520f099c476e70917a28e9162d58496c9f12d29bde01eb58b0d2e2"}, + {file = "cvxpy-1.7.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e416efb52ff89e2dffa2079ccca8034b59f27d5414cf92674d89bfb89a6a61ad"}, + {file = "cvxpy-1.7.5-cp39-cp39-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:806d9f435a062cb05dfb63812738d973ce209e58df72fa424cf9bbae5320996e"}, + {file = "cvxpy-1.7.5-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0ad9e26897584b441c95ea824a0b6fc0f0ffd2260c1435e3c1f1183c28817142"}, + {file = "cvxpy-1.7.5-cp39-cp39-win_amd64.whl", hash = "sha256:c570d240ba63c1c6dcc34a40c405e1057ae7faade64691a3f25ba8ca3b534cb1"}, + {file = "cvxpy-1.7.5.tar.gz", hash = "sha256:4b512218001c27659e16fc914a2490038635874681032c3c3485ff1099b83f5d"}, +] + +[package.dependencies] +clarabel = ">=0.5.0" +numpy = ">=1.22.4" +osqp = ">=1.0.0" +scipy = ">=1.13.0" +scs = ">=3.2.4.post1" + +[package.extras] +cbc = ["cylp (>=0.91.5)"] +cuopt = ["cuopt-cu12 (>=25.5)", "nvidia-cuda-runtime-cu12 (>=12.8,<13.0)"] +cvxopt = ["cvxopt"] +daqp = ["daqp"] +diffcp = ["diffcp"] +doc = ["sphinx", "sphinx-design", "sphinx-immaterial (>=0.11.7)", "sphinx-inline-tabs", "sphinxcontrib.jquery"] +ecos = ["ecos"] +ecos-bb = ["ecos"] +glop = ["ortools (>=9.7,<9.15)"] +glpk = ["cvxopt"] +glpk-mi = ["cvxopt"] +gurobi = ["gurobipy"] +highs = ["highspy"] +mosek = ["Mosek"] +pdlp = ["ortools (>=9.7,<9.15)"] +piqp = ["piqp"] +proxqp = ["proxsuite"] +qoco = ["qoco"] +scip = ["PySCIPOpt"] +scipy = ["scipy"] +testing = ["hypothesis", "pytest"] +xpress = ["xpress (>=9.5)"] + +[[package]] +name = "cvxpy" +version = "1.8.1" +description = "A domain-specific language for modeling convex optimization problems in Python." +optional = false +python-versions = ">=3.11" +groups = ["tests"] +markers = "python_version >= \"3.11\"" +files = [ + {file = "cvxpy-1.8.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:08c1ca0559835dca624d771a4343b59f0eea1c1113de71d7973cd1329841b437"}, + {file = "cvxpy-1.8.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:165a9e2286d8ab5774f6a38ec2075383bbc01212d81d02ee05d1e8a0f219ed29"}, + {file = "cvxpy-1.8.1-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:636b02913b4366835cab791e8e28d8cf2a7fa2de44c0f590e899cfbc8644acd0"}, + {file = "cvxpy-1.8.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fbe4758ef9a07f9ecb05154c84d4097b9ebf3280ce3130e8cfdf4757bb7d229d"}, + {file = "cvxpy-1.8.1-cp311-cp311-win_amd64.whl", hash = "sha256:295f20f4c5130f09ca1eb493a422f718f5726b2ebc0ba984bfebe96c9eb5fe30"}, + {file = "cvxpy-1.8.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:4ad9cc028962247f5116d118136ac462023598f4d77ef5a27eecd584cf99eb5f"}, + {file = "cvxpy-1.8.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a27c3c291e753910600326c9046df67089c6930ab436835da06227452d9f9fb5"}, + {file = "cvxpy-1.8.1-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4c977b3e0ba8f38a5614f5da5c22c5cd82b99730cc56e13294e66e2e2a1494e7"}, + {file = "cvxpy-1.8.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:96803ca7564aaf74821998093c37c92910732e137271474e7a1eaa0fbdb36bd2"}, + {file = "cvxpy-1.8.1-cp312-cp312-win_amd64.whl", hash = "sha256:291be80b58240fea336dc0b72ac7d4c2ed484d8aefe7006ff0dfbfbff6ad56a9"}, + {file = "cvxpy-1.8.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:5c54c766a8d274d6ad9105b04b574055fbab1032863d08c3d7027eb10671163f"}, + {file = "cvxpy-1.8.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e2597e898995dabf69a7052c39f234b484bf9f3721dbf616956cc6c09c01f54e"}, + {file = "cvxpy-1.8.1-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8258e66e519035980732dd542d180bf180f5d1af35ddbd983d363836ea9c47a8"}, + {file = "cvxpy-1.8.1-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:166dd712fa5766d76425d1b6687c9a6375b03bb3c79cd14dcdf86f07d53256e2"}, + {file = "cvxpy-1.8.1-cp313-cp313-win_amd64.whl", hash = "sha256:e7d8348d743c6d49918ed9716e7f1d4fa7a181602c37bf6c169b83e3d5cb02ee"}, + {file = "cvxpy-1.8.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:41fea926757ec08a8cbca06c3ac609f039281222b1e9b043b550ee7e833d8fe1"}, + {file = "cvxpy-1.8.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:af13f000404467599a48f0b8a16f8a9fc003be804e65193d763e4f0af8d75ade"}, + {file = "cvxpy-1.8.1-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ccce77781cdd0cd6e7222516dfeac1718860ee0ce2289ec07a27c74a70fae53c"}, + {file = "cvxpy-1.8.1-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:eb7677311a487f4fe4a5a12156619486f1c4531f745a9b9b2d0b759791b21911"}, + {file = "cvxpy-1.8.1-cp314-cp314-win_amd64.whl", hash = "sha256:e904716c1d9a7e2a482e40c2cbbc431989cfb09a6c15a9f053b64b5f397d3803"}, + {file = "cvxpy-1.8.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:0078446f0bb014f2c673d5a73fb06c08d2e000ab80e15bc43880ce8eddd0c586"}, + {file = "cvxpy-1.8.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:8d6664df446dc67024b1eed713f91327b642fab7dd59c1737e0b1c0787bdea34"}, + {file = "cvxpy-1.8.1-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:38ba6e8153c86dd8bf950accaf115f83b57a1d7130af81aedab81e112fd24f58"}, + {file = "cvxpy-1.8.1-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f0097a669e9c3008de565f2d773ef57b5e2548c3ac45aad6f1920bf4a0e3c823"}, + {file = "cvxpy-1.8.1.tar.gz", hash = "sha256:3fbdb1f81be7237c58742b1618bb9f809eeacf6c131705e2540b87ecef9cf402"}, +] + +[package.dependencies] +clarabel = ">=0.5.0" +highspy = ">=1.11.0" +numpy = ">=2.0.0" +osqp = ">=1.0.0" +scipy = ">=1.13.0" +scs = ">=3.2.4.post1" + +[package.extras] +cbc = ["cylp (>=0.91.5)"] +cvxopt = ["cvxopt"] +daqp = ["daqp"] +diffcp = ["diffcp"] +doc = ["sphinx", "sphinx-design", "sphinx-immaterial (>=0.11.7)", "sphinx-inline-tabs", "sphinxcontrib.jquery"] +ecos = ["ecos"] +ecos-bb = ["ecos"] +glop = ["ortools (>=9.7,<9.15)"] +glpk = ["cvxopt"] +glpk-mi = ["cvxopt"] +gurobi = ["gurobipy"] +highs = ["highspy"] +knitro = ["knitro"] +mosek = ["Mosek"] +pdlp = ["ortools (>=9.7,<9.15)"] +piqp = ["piqp"] +proxqp = ["proxsuite"] +qoco = ["qoco"] +qpalm = ["qpalm (>=1.2.5,<1.3.0)"] +scip = ["PySCIPOpt"] +scipy = ["scipy"] +testing = ["hypothesis", "pytest"] +xpress = ["xpress (>=9.5)"] + [[package]] name = "cycler" version = "0.12.1" @@ -1372,72 +1530,160 @@ sphinx-basic-ng = "*" [[package]] name = "greenlet" -version = "3.3.1" +version = "3.3.2" description = "Lightweight in-process concurrent programming" optional = false python-versions = ">=3.10" groups = ["main"] markers = "platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\"" files = [ - {file = "greenlet-3.3.1-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:04bee4775f40ecefcdaa9d115ab44736cd4b9c5fba733575bfe9379419582e13"}, - {file = "greenlet-3.3.1-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:50e1457f4fed12a50e427988a07f0f9df53cf0ee8da23fab16e6732c2ec909d4"}, - {file = "greenlet-3.3.1-cp310-cp310-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:070472cd156f0656f86f92e954591644e158fd65aa415ffbe2d44ca77656a8f5"}, - {file = "greenlet-3.3.1-cp310-cp310-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:1108b61b06b5224656121c3c8ee8876161c491cbe74e5c519e0634c837cf93d5"}, - {file = "greenlet-3.3.1-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3a300354f27dd86bae5fbf7002e6dd2b3255cd372e9242c933faf5e859b703fe"}, - {file = "greenlet-3.3.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e84b51cbebf9ae573b5fbd15df88887815e3253fc000a7d0ff95170e8f7e9729"}, - {file = "greenlet-3.3.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e0093bd1a06d899892427217f0ff2a3c8f306182b8c754336d32e2d587c131b4"}, - {file = "greenlet-3.3.1-cp310-cp310-win_amd64.whl", hash = "sha256:7932f5f57609b6a3b82cc11877709aa7a98e3308983ed93552a1c377069b20c8"}, - {file = "greenlet-3.3.1-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:5fd23b9bc6d37b563211c6abbb1b3cab27db385a4449af5c32e932f93017080c"}, - {file = "greenlet-3.3.1-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:09f51496a0bfbaa9d74d36a52d2580d1ef5ed4fdfcff0a73730abfbbbe1403dd"}, - {file = "greenlet-3.3.1-cp311-cp311-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:cb0feb07fe6e6a74615ee62a880007d976cf739b6669cce95daa7373d4fc69c5"}, - {file = "greenlet-3.3.1-cp311-cp311-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:67ea3fc73c8cd92f42467a72b75e8f05ed51a0e9b1d15398c913416f2dafd49f"}, - {file = "greenlet-3.3.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:39eda9ba259cc9801da05351eaa8576e9aa83eb9411e8f0c299e05d712a210f2"}, - {file = "greenlet-3.3.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e2e7e882f83149f0a71ac822ebf156d902e7a5d22c9045e3e0d1daf59cee2cc9"}, - {file = "greenlet-3.3.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:80aa4d79eb5564f2e0a6144fcc744b5a37c56c4a92d60920720e99210d88db0f"}, - {file = "greenlet-3.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:32e4ca9777c5addcbf42ff3915d99030d8e00173a56f80001fb3875998fe410b"}, - {file = "greenlet-3.3.1-cp311-cp311-win_arm64.whl", hash = "sha256:da19609432f353fed186cc1b85e9440db93d489f198b4bdf42ae19cc9d9ac9b4"}, - {file = "greenlet-3.3.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:7e806ca53acf6d15a888405880766ec84721aa4181261cd11a457dfe9a7a4975"}, - {file = "greenlet-3.3.1-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d842c94b9155f1c9b3058036c24ffb8ff78b428414a19792b2380be9cecf4f36"}, - {file = "greenlet-3.3.1-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:20fedaadd422fa02695f82093f9a98bad3dab5fcda793c658b945fcde2ab27ba"}, - {file = "greenlet-3.3.1-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c620051669fd04ac6b60ebc70478210119c56e2d5d5df848baec4312e260e4ca"}, - {file = "greenlet-3.3.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:14194f5f4305800ff329cbf02c5fcc88f01886cadd29941b807668a45f0d2336"}, - {file = "greenlet-3.3.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7b2fe4150a0cf59f847a67db8c155ac36aed89080a6a639e9f16df5d6c6096f1"}, - {file = "greenlet-3.3.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:49f4ad195d45f4a66a0eb9c1ba4832bb380570d361912fa3554746830d332149"}, - {file = "greenlet-3.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:cc98b9c4e4870fa983436afa999d4eb16b12872fab7071423d5262fa7120d57a"}, - {file = "greenlet-3.3.1-cp312-cp312-win_arm64.whl", hash = "sha256:bfb2d1763d777de5ee495c85309460f6fd8146e50ec9d0ae0183dbf6f0a829d1"}, - {file = "greenlet-3.3.1-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:7ab327905cabb0622adca5971e488064e35115430cec2c35a50fd36e72a315b3"}, - {file = "greenlet-3.3.1-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:65be2f026ca6a176f88fb935ee23c18333ccea97048076aef4db1ef5bc0713ac"}, - {file = "greenlet-3.3.1-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7a3ae05b3d225b4155bda56b072ceb09d05e974bc74be6c3fc15463cf69f33fd"}, - {file = "greenlet-3.3.1-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:12184c61e5d64268a160226fb4818af4df02cfead8379d7f8b99a56c3a54ff3e"}, - {file = "greenlet-3.3.1-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6423481193bbbe871313de5fd06a082f2649e7ce6e08015d2a76c1e9186ca5b3"}, - {file = "greenlet-3.3.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:33a956fe78bbbda82bfc95e128d61129b32d66bcf0a20a1f0c08aa4839ffa951"}, - {file = "greenlet-3.3.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4b065d3284be43728dd280f6f9a13990b56470b81be20375a207cdc814a983f2"}, - {file = "greenlet-3.3.1-cp313-cp313-win_amd64.whl", hash = "sha256:27289986f4e5b0edec7b5a91063c109f0276abb09a7e9bdab08437525977c946"}, - {file = "greenlet-3.3.1-cp313-cp313-win_arm64.whl", hash = "sha256:2f080e028001c5273e0b42690eaf359aeef9cb1389da0f171ea51a5dc3c7608d"}, - {file = "greenlet-3.3.1-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:bd59acd8529b372775cd0fcbc5f420ae20681c5b045ce25bd453ed8455ab99b5"}, - {file = "greenlet-3.3.1-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b31c05dd84ef6871dd47120386aed35323c944d86c3d91a17c4b8d23df62f15b"}, - {file = "greenlet-3.3.1-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:02925a0bfffc41e542c70aa14c7eda3593e4d7e274bfcccca1827e6c0875902e"}, - {file = "greenlet-3.3.1-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3e0f3878ca3a3ff63ab4ea478585942b53df66ddde327b59ecb191b19dbbd62d"}, - {file = "greenlet-3.3.1-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:34a729e2e4e4ffe9ae2408d5ecaf12f944853f40ad724929b7585bca808a9d6f"}, - {file = "greenlet-3.3.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:aec9ab04e82918e623415947921dea15851b152b822661cce3f8e4393c3df683"}, - {file = "greenlet-3.3.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:71c767cf281a80d02b6c1bdc41c9468e1f5a494fb11bc8688c360524e273d7b1"}, - {file = "greenlet-3.3.1-cp314-cp314-win_amd64.whl", hash = "sha256:96aff77af063b607f2489473484e39a0bbae730f2ea90c9e5606c9b73c44174a"}, - {file = "greenlet-3.3.1-cp314-cp314-win_arm64.whl", hash = "sha256:b066e8b50e28b503f604fa538adc764a638b38cf8e81e025011d26e8a627fa79"}, - {file = "greenlet-3.3.1-cp314-cp314t-macosx_11_0_universal2.whl", hash = "sha256:3e63252943c921b90abb035ebe9de832c436401d9c45f262d80e2d06cc659242"}, - {file = "greenlet-3.3.1-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:76e39058e68eb125de10c92524573924e827927df5d3891fbc97bd55764a8774"}, - {file = "greenlet-3.3.1-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c9f9d5e7a9310b7a2f416dd13d2e3fd8b42d803968ea580b7c0f322ccb389b97"}, - {file = "greenlet-3.3.1-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4b9721549a95db96689458a1e0ae32412ca18776ed004463df3a9299c1b257ab"}, - {file = "greenlet-3.3.1-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:92497c78adf3ac703b57f1e3813c2d874f27f71a178f9ea5887855da413cd6d2"}, - {file = "greenlet-3.3.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ed6b402bc74d6557a705e197d47f9063733091ed6357b3de33619d8a8d93ac53"}, - {file = "greenlet-3.3.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:59913f1e5ada20fde795ba906916aea25d442abcc0593fba7e26c92b7ad76249"}, - {file = "greenlet-3.3.1-cp314-cp314t-win_amd64.whl", hash = "sha256:301860987846c24cb8964bdec0e31a96ad4a2a801b41b4ef40963c1b44f33451"}, - {file = "greenlet-3.3.1.tar.gz", hash = "sha256:41848f3230b58c08bb43dee542e74a2a2e34d3c59dc3076cec9151aeeedcae98"}, + {file = "greenlet-3.3.2-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:9bc885b89709d901859cf95179ec9f6bb67a3d2bb1f0e88456461bd4b7f8fd0d"}, + {file = "greenlet-3.3.2-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b568183cf65b94919be4438dc28416b234b678c608cafac8874dfeeb2a9bbe13"}, + {file = "greenlet-3.3.2-cp310-cp310-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:527fec58dc9f90efd594b9b700662ed3fb2493c2122067ac9c740d98080a620e"}, + {file = "greenlet-3.3.2-cp310-cp310-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:508c7f01f1791fbc8e011bd508f6794cb95397fdb198a46cb6635eb5b78d85a7"}, + {file = "greenlet-3.3.2-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ad0c8917dd42a819fe77e6bdfcb84e3379c0de956469301d9fd36427a1ca501f"}, + {file = "greenlet-3.3.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:97245cc10e5515dbc8c3104b2928f7f02b6813002770cfaffaf9a6e0fc2b94ef"}, + {file = "greenlet-3.3.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8c1fdd7d1b309ff0da81d60a9688a8bd044ac4e18b250320a96fc68d31c209ca"}, + {file = "greenlet-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:5d0e35379f93a6d0222de929a25ab47b5eb35b5ef4721c2b9cbcc4036129ff1f"}, + {file = "greenlet-3.3.2-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:c56692189a7d1c7606cb794be0a8381470d95c57ce5be03fb3d0ef57c7853b86"}, + {file = "greenlet-3.3.2-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1ebd458fa8285960f382841da585e02201b53a5ec2bac6b156fc623b5ce4499f"}, + {file = "greenlet-3.3.2-cp311-cp311-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a443358b33c4ec7b05b79a7c8b466f5d275025e750298be7340f8fc63dff2a55"}, + {file = "greenlet-3.3.2-cp311-cp311-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:4375a58e49522698d3e70cc0b801c19433021b5c37686f7ce9c65b0d5c8677d2"}, + {file = "greenlet-3.3.2-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8e2cd90d413acbf5e77ae41e5d3c9b3ac1d011a756d7284d7f3f2b806bbd6358"}, + {file = "greenlet-3.3.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:442b6057453c8cb29b4fb36a2ac689382fc71112273726e2423f7f17dc73bf99"}, + {file = "greenlet-3.3.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:45abe8eb6339518180d5a7fa47fa01945414d7cca5ecb745346fc6a87d2750be"}, + {file = "greenlet-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:1e692b2dae4cc7077cbb11b47d258533b48c8fde69a33d0d8a82e2fe8d8531d5"}, + {file = "greenlet-3.3.2-cp311-cp311-win_arm64.whl", hash = "sha256:02b0a8682aecd4d3c6c18edf52bc8e51eacdd75c8eac52a790a210b06aa295fd"}, + {file = "greenlet-3.3.2-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:ac8d61d4343b799d1e526db579833d72f23759c71e07181c2d2944e429eb09cd"}, + {file = "greenlet-3.3.2-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3ceec72030dae6ac0c8ed7591b96b70410a8be370b6a477b1dbc072856ad02bd"}, + {file = "greenlet-3.3.2-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a2a5be83a45ce6188c045bcc44b0ee037d6a518978de9a5d97438548b953a1ac"}, + {file = "greenlet-3.3.2-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ae9e21c84035c490506c17002f5c8ab25f980205c3e61ddb3a2a2a2e6c411fcb"}, + {file = "greenlet-3.3.2-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:43e99d1749147ac21dde49b99c9abffcbc1e2d55c67501465ef0930d6e78e070"}, + {file = "greenlet-3.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4c956a19350e2c37f2c48b336a3afb4bff120b36076d9d7fb68cb44e05d95b79"}, + {file = "greenlet-3.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6c6f8ba97d17a1e7d664151284cb3315fc5f8353e75221ed4324f84eb162b395"}, + {file = "greenlet-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:34308836d8370bddadb41f5a7ce96879b72e2fdfb4e87729330c6ab52376409f"}, + {file = "greenlet-3.3.2-cp312-cp312-win_arm64.whl", hash = "sha256:d3a62fa76a32b462a97198e4c9e99afb9ab375115e74e9a83ce180e7a496f643"}, + {file = "greenlet-3.3.2-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:aa6ac98bdfd716a749b84d4034486863fd81c3abde9aa3cf8eff9127981a4ae4"}, + {file = "greenlet-3.3.2-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ab0c7e7901a00bc0a7284907273dc165b32e0d109a6713babd04471327ff7986"}, + {file = "greenlet-3.3.2-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d248d8c23c67d2291ffd47af766e2a3aa9fa1c6703155c099feb11f526c63a92"}, + {file = "greenlet-3.3.2-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:ccd21bb86944ca9be6d967cf7691e658e43417782bce90b5d2faeda0ff78a7dd"}, + {file = "greenlet-3.3.2-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b6997d360a4e6a4e936c0f9625b1c20416b8a0ea18a8e19cabbefc712e7397ab"}, + {file = "greenlet-3.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:64970c33a50551c7c50491671265d8954046cb6e8e2999aacdd60e439b70418a"}, + {file = "greenlet-3.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1a9172f5bf6bd88e6ba5a84e0a68afeac9dc7b6b412b245dd64f52d83c81e55b"}, + {file = "greenlet-3.3.2-cp313-cp313-win_amd64.whl", hash = "sha256:a7945dd0eab63ded0a48e4dcade82939783c172290a7903ebde9e184333ca124"}, + {file = "greenlet-3.3.2-cp313-cp313-win_arm64.whl", hash = "sha256:394ead29063ee3515b4e775216cb756b2e3b4a7e55ae8fd884f17fa579e6b327"}, + {file = "greenlet-3.3.2-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:8d1658d7291f9859beed69a776c10822a0a799bc4bfe1bd4272bb60e62507dab"}, + {file = "greenlet-3.3.2-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:18cb1b7337bca281915b3c5d5ae19f4e76d35e1df80f4ad3c1a7be91fadf1082"}, + {file = "greenlet-3.3.2-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c2e47408e8ce1c6f1ceea0dffcdf6ebb85cc09e55c7af407c99f1112016e45e9"}, + {file = "greenlet-3.3.2-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e3cb43ce200f59483eb82949bf1835a99cf43d7571e900d7c8d5c62cdf25d2f9"}, + {file = "greenlet-3.3.2-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:63d10328839d1973e5ba35e98cccbca71b232b14051fd957b6f8b6e8e80d0506"}, + {file = "greenlet-3.3.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8e4ab3cfb02993c8cc248ea73d7dae6cec0253e9afa311c9b37e603ca9fad2ce"}, + {file = "greenlet-3.3.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:94ad81f0fd3c0c0681a018a976e5c2bd2ca2d9d94895f23e7bb1af4e8af4e2d5"}, + {file = "greenlet-3.3.2-cp314-cp314-win_amd64.whl", hash = "sha256:8c4dd0f3997cf2512f7601563cc90dfb8957c0cff1e3a1b23991d4ea1776c492"}, + {file = "greenlet-3.3.2-cp314-cp314-win_arm64.whl", hash = "sha256:cd6f9e2bbd46321ba3bbb4c8a15794d32960e3b0ae2cc4d49a1a53d314805d71"}, + {file = "greenlet-3.3.2-cp314-cp314t-macosx_11_0_universal2.whl", hash = "sha256:e26e72bec7ab387ac80caa7496e0f908ff954f31065b0ffc1f8ecb1338b11b54"}, + {file = "greenlet-3.3.2-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b466dff7a4ffda6ca975979bab80bdadde979e29fc947ac3be4451428d8b0e4"}, + {file = "greenlet-3.3.2-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b8bddc5b73c9720bea487b3bffdb1840fe4e3656fba3bd40aa1489e9f37877ff"}, + {file = "greenlet-3.3.2-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:59b3e2c40f6706b05a9cd299c836c6aa2378cabe25d021acd80f13abf81181cf"}, + {file = "greenlet-3.3.2-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b26b0f4428b871a751968285a1ac9648944cea09807177ac639b030bddebcea4"}, + {file = "greenlet-3.3.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:1fb39a11ee2e4d94be9a76671482be9398560955c9e568550de0224e41104727"}, + {file = "greenlet-3.3.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:20154044d9085151bc309e7689d6f7ba10027f8f5a8c0676ad398b951913d89e"}, + {file = "greenlet-3.3.2-cp314-cp314t-win_amd64.whl", hash = "sha256:c04c5e06ec3e022cbfe2cd4a846e1d4e50087444f875ff6d2c2ad8445495cf1a"}, + {file = "greenlet-3.3.2.tar.gz", hash = "sha256:2eaf067fc6d886931c7962e8c6bede15d2f01965560f3359b27c80bde2d151f2"}, ] [package.extras] docs = ["Sphinx", "furo"] test = ["objgraph", "psutil", "setuptools"] +[[package]] +name = "highspy" +version = "1.13.1" +description = "A thin set of pybind11 wrappers to HiGHS" +optional = false +python-versions = ">=3.8" +groups = ["tests"] +markers = "python_version >= \"3.11\"" +files = [ + {file = "highspy-1.13.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f668e549eea34f0e84066286745d9d6fa02e6892cf708741dd3e6f674a2cc105"}, + {file = "highspy-1.13.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:19055e037f0bd4cd21549c395a1f525163f2efe1f17a714cf609513ee56e45dd"}, + {file = "highspy-1.13.1-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e54e94bf765359f2ff1a02d9e53b8f663d5b41ee02d6d88f5bebdecc22fc156f"}, + {file = "highspy-1.13.1-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a77bc10d1d699d1f536de6da694c28537e978ef96fbac6265e37b6563f06b67"}, + {file = "highspy-1.13.1-cp310-cp310-manylinux_2_26_i686.manylinux_2_28_i686.whl", hash = "sha256:599f3e01871c25c5c350bfe389c0236368556d4c6e2d0c4e375cf3a58a92bffb"}, + {file = "highspy-1.13.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9423446e0fe2463876a7c494370504b258a62766ee19b830ccd09cf852b3073b"}, + {file = "highspy-1.13.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:77e434faf1b1530d52a974f9905aa70fcadaf580652ae64a4826e22277ab09a4"}, + {file = "highspy-1.13.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:178bd19c47f4d179c4ca2c3ce6a6bafd2f6b808e6aa0c7f0609fa527d96f11f7"}, + {file = "highspy-1.13.1-cp310-cp310-win32.whl", hash = "sha256:3f1f324a32e3be2f94ecdb27b5edc325302817d29571d6cd340dbe9200624146"}, + {file = "highspy-1.13.1-cp310-cp310-win_amd64.whl", hash = "sha256:4ceb706d16d638f1faa5294733e2a030fd41d140bae7606a2747ba8a984a2239"}, + {file = "highspy-1.13.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a756dc2339f56d5979ddff1081ed49b68e272cae57ce33e44df6c9a64c306381"}, + {file = "highspy-1.13.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9a215cfb0975cc70a90cea5663d3a0c65c675ced50f0c3148727cac9b3b27a58"}, + {file = "highspy-1.13.1-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4d98fe763e42980e253edb8832c4fc719e15107d32ae80802dcb43bf506bec20"}, + {file = "highspy-1.13.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bd5a921cdea21e816a1b1b36944803a51b72b0a87f7b7e00635ec9cd6aefca60"}, + {file = "highspy-1.13.1-cp311-cp311-manylinux_2_26_i686.manylinux_2_28_i686.whl", hash = "sha256:cdfc79cf4395434d27cc84a965e7bc9e76e59b38defb3879b694be6bbd44ff28"}, + {file = "highspy-1.13.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c1087def948268ef7100acea50d029f8ffce3db1d623dce3112babfe677dab90"}, + {file = "highspy-1.13.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4bfbc28842ec5286b7db14ff3f9dcd772196327242183a65209f9558c5562888"}, + {file = "highspy-1.13.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5d08e309f514dad949453b3f962dc1c6f757e6d7db34f670e14f8dd27fb0e4d5"}, + {file = "highspy-1.13.1-cp311-cp311-win32.whl", hash = "sha256:46feb46c3109e9b66dc53db1804e647e0351234c603fcc53287c1d3d53998d08"}, + {file = "highspy-1.13.1-cp311-cp311-win_amd64.whl", hash = "sha256:2a2dc6b909284de95f84d288cfecafe2826245ae108dc33887e999bd8f9df75f"}, + {file = "highspy-1.13.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:31f9f7001b9a6afd1cb06e5f3ad24848aa0df78a32b004538f2630535a881e7d"}, + {file = "highspy-1.13.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce77b3771c20715e4552b890b9a2f4eee33faf1bd86ab08c6a7b00424ebe12b3"}, + {file = "highspy-1.13.1-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f469f0a340870e1f16324a096dead3775857470b7e9d552b08a878a945f34917"}, + {file = "highspy-1.13.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f00b426b09e28306b279645beec2f892dd652ad41ec1597b742865bb844dd38d"}, + {file = "highspy-1.13.1-cp312-cp312-manylinux_2_26_i686.manylinux_2_28_i686.whl", hash = "sha256:dce26ba2926612847be6d3e01ee98df2af8472a99de8ad9dc562060f6c8e5d0a"}, + {file = "highspy-1.13.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:506038db5c4732a4b65755aa63f580cef91e1a99a5d1399e311dc31d3300dadd"}, + {file = "highspy-1.13.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:eda07ca3ec5506d279679d775dedc447fbcc3711814c5f2e22d2d063598586af"}, + {file = "highspy-1.13.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ce9481fb96771c3b74592e1a94cc8dc2748d18eafb0bad6a03ebca5f4cfaa8fd"}, + {file = "highspy-1.13.1-cp312-cp312-win32.whl", hash = "sha256:0a10b8d7bc6a2a50226bc6821f21ed5f456479950271e742aff8bc97412c4591"}, + {file = "highspy-1.13.1-cp312-cp312-win_amd64.whl", hash = "sha256:26f023093ed2fa2407f12a4a7dc9c1de253cd14228874e58e6719d78a74e2a9c"}, + {file = "highspy-1.13.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0a255204f4ec79f5e447765d745e41bf3115a6c196ecfab5ed636d1ff53c0401"}, + {file = "highspy-1.13.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:cbb7509b5606a1ac7bc1fff794cebeb668f43531678f898803c12cbb694bea61"}, + {file = "highspy-1.13.1-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e2e572c9ec5eb0fd5d178690981116413f277cb59d150bf271d927161335df23"}, + {file = "highspy-1.13.1-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e577ff0fdeccc7e207be8577dd8b223816d024c40c1b7af4afb6e96818f4544b"}, + {file = "highspy-1.13.1-cp313-cp313-manylinux_2_26_i686.manylinux_2_28_i686.whl", hash = "sha256:dc8677bb6da2216fd72110d95d904022bf3150832441eb08562bdb8d2c5aeb6c"}, + {file = "highspy-1.13.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3ec5adcef1028b40ae6d76d03c24b512c5f33849c5e09b70c15734b0e48c68ca"}, + {file = "highspy-1.13.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:1a435dd11fcefab2e9e0ad90d75a459a656b177ef3d1173b31db889808580e92"}, + {file = "highspy-1.13.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0f473e94b19c186fda0abed1e31d3682ac4a9109930e77a1901c63f1b3d7d772"}, + {file = "highspy-1.13.1-cp313-cp313-win32.whl", hash = "sha256:1464ed94e467de3cc20fdf3779609dd13aa91db8d11305b1d8f6a029ae129f33"}, + {file = "highspy-1.13.1-cp313-cp313-win_amd64.whl", hash = "sha256:620fad11a92517d525300ad70f27f84f41e8c0af10ece5ae5537f2be13ae0970"}, + {file = "highspy-1.13.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:0868538ce474be93219013fa242fe3ddf0859562e3b354b50786da03c96b941a"}, + {file = "highspy-1.13.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:d3f38a68783d690a4fe14521fbad18cbeae6121e1785f1dbdf5c045bcb35a926"}, + {file = "highspy-1.13.1-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:edf109c83d1488e0305f8fce88b9a3fc4fa7655b0b72c6cdb4437bad2a4a7fc0"}, + {file = "highspy-1.13.1-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:56cb459c01696c83d2d65057e03df2cb809fb9cc9357f91d30b1af192765d809"}, + {file = "highspy-1.13.1-cp314-cp314-manylinux_2_26_i686.manylinux_2_28_i686.whl", hash = "sha256:aada6027a92401967476b93ce10f13c0d7c45aedfb322c8049b5d2672fbce5a8"}, + {file = "highspy-1.13.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:d2072f3a303b9ac988e9e37b5d7942cbba8c9fce7a323357122429c1a85c344b"}, + {file = "highspy-1.13.1-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:755d924e7650703e217debd69f566da078cdf7f9bd957ccd88c3be134c63c8f5"}, + {file = "highspy-1.13.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:516c5b5a7d01d7c073206f787316c60f4800994cf3a947031f336e737177f6cc"}, + {file = "highspy-1.13.1-cp314-cp314-win32.whl", hash = "sha256:4cfff7f50615a588a760b33cd2dd37761679b400196213015230db1cd6c46232"}, + {file = "highspy-1.13.1-cp314-cp314-win_amd64.whl", hash = "sha256:242d00f46b09c9d6f077881739d7487030a9ed2c56bcd28f3e8d5942da407df4"}, + {file = "highspy-1.13.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:29b23f4eb812847d1e4e0c1dac5d13986ee0f834a9239ab64052d0c260c05ec7"}, + {file = "highspy-1.13.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1ec688c746044ab0a53f2fb180bb5d1561019ebd7333981f5c2b10e5c00c65fb"}, + {file = "highspy-1.13.1-cp38-cp38-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b39583a9fd98e8a183d1c760465ab33a8cc41e71931e1d043ddbcf9ec6ff2656"}, + {file = "highspy-1.13.1-cp38-cp38-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a1fe2131e8ef33fe0490c6652c9cfb6f435f64015f67e266efec77ed2ac5ad13"}, + {file = "highspy-1.13.1-cp38-cp38-manylinux_2_26_i686.manylinux_2_28_i686.whl", hash = "sha256:b448f2a70f94d767814bb2546f1b54c3a8c861460f923286c1424a319bb31c50"}, + {file = "highspy-1.13.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:0f2761ad54aaaf882879511188512bedc28dbf7a0e70ace71679137f38dcc9f1"}, + {file = "highspy-1.13.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:631658ea8e43891647cb7025b10fd87d970b2a253b8a3d6f6dab5beba99f593d"}, + {file = "highspy-1.13.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:722c13af162b17a3d2e16097639890c127e3a07f05e1e5d934d254fef38edf74"}, + {file = "highspy-1.13.1-cp38-cp38-win32.whl", hash = "sha256:da15ba6917ab0b32b8d0dec96a6fae7c48c06769b0eede4b81d61f5b44795ea0"}, + {file = "highspy-1.13.1-cp38-cp38-win_amd64.whl", hash = "sha256:033c220df1377e1bab7fad2d667dcb1e9ac3a291d278553bf762f92268761976"}, + {file = "highspy-1.13.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0a0c46e24c94ae27b6c544beae742a3fe5734a1335a8dcc2a0c9e519999d989d"}, + {file = "highspy-1.13.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5dbcac505d878749469501d78b6c15f30b5e93998f2946429dfc4269817127a6"}, + {file = "highspy-1.13.1-cp39-cp39-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d427a6b2558af4719e5c88c219a1432ef4c5e78d60644126a21cf3b3d211e0b2"}, + {file = "highspy-1.13.1-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2bb25f0374e4a8889a53f4f94e677bbebf23b37479481da078bf8a3f55b6aae7"}, + {file = "highspy-1.13.1-cp39-cp39-manylinux_2_26_i686.manylinux_2_28_i686.whl", hash = "sha256:c9bb6ee2697a54cd3ac059ec8f2237596e91aafa7045795e63151a47b0fe980e"}, + {file = "highspy-1.13.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:3f8458006075d68c26cddda048dd3bc8cbeddc30bb749b92a87bf33450dafac1"}, + {file = "highspy-1.13.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:4d92cc01aa54117df5a7385383af9d6cb55b0dda58ea1b6dc12e6420c2751c77"}, + {file = "highspy-1.13.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a046bd1734a7a07af4fd02ca0131f72f80d368d7c1b9a7e8679f20056243afd4"}, + {file = "highspy-1.13.1-cp39-cp39-win32.whl", hash = "sha256:769cb6778e7e038031fcda0d92181b339ac86ed04128316093be1d2d7efea78a"}, + {file = "highspy-1.13.1-cp39-cp39-win_amd64.whl", hash = "sha256:b3e9dcb0fcb52cff85f5350cab3468216948e4a35ab9357a7cfd3fd6304ba393"}, + {file = "highspy-1.13.1.tar.gz", hash = "sha256:7888873501c6ca3e0fa19fee960c8b3cb1c64132c5a9b514903cc7e259b5b0c7"}, +] + +[package.dependencies] +numpy = "*" + +[package.extras] +test = ["numpy", "pytest"] + [[package]] name = "idna" version = "3.11" @@ -1593,7 +1839,7 @@ version = "3.1.6" description = "A very fast and expressive template engine." optional = false python-versions = ">=3.7" -groups = ["docs"] +groups = ["docs", "tests"] files = [ {file = "jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"}, {file = "jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d"}, @@ -1611,7 +1857,7 @@ version = "1.5.3" description = "Lightweight pipelining with Python functions" optional = false python-versions = ">=3.9" -groups = ["main"] +groups = ["main", "tests"] files = [ {file = "joblib-1.5.3-py3-none-any.whl", hash = "sha256:5fc3c5039fc5ca8c0276333a188bbd59d6b7ab37fe6632daa76bc7f9ec18e713"}, {file = "joblib-1.5.3.tar.gz", hash = "sha256:8561a3269e6801106863fd0d6d84bb737be9e7631e33aaed3fb9ce5953688da3"}, @@ -1906,7 +2152,7 @@ version = "3.0.3" description = "Safely add untrusted strings to HTML/XML markup." optional = false python-versions = ">=3.9" -groups = ["main", "docs"] +groups = ["main", "docs", "tests"] files = [ {file = "markupsafe-3.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2f981d352f04553a7171b8e44369f2af4055f888dfb147d55e42d29e29e74559"}, {file = "markupsafe-3.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e1c1493fb6e50ab01d20a22826e57520f1284df32f2d8601fdd90b6304601419"}, @@ -2129,7 +2375,7 @@ version = "1.3.0" description = "Python library for arbitrary-precision floating-point arithmetic" optional = false python-versions = "*" -groups = ["main"] +groups = ["main", "tests"] files = [ {file = "mpmath-1.3.0-py3-none-any.whl", hash = "sha256:a0b2b9fe80bbcd81a6647ff13108738cfb482d481d826cc0e02f5b35e5c88d2c"}, {file = "mpmath-1.3.0.tar.gz", hash = "sha256:7a28eb2a9774d00c7bc92411c19a89209d5da7c4c9a9e227be8330a23a25b91f"}, @@ -2447,6 +2693,64 @@ document = ["ase", "cmaes (>=0.12.0)", "fvcore", "kaleido (<0.4)", "lightgbm", " optional = ["boto3", "cmaes (>=0.12.0)", "google-cloud-storage", "greenlet", "grpcio", "matplotlib (!=3.6.0)", "pandas", "plotly (>=4.9.0)", "protobuf (>=5.28.1)", "redis", "scikit-learn (>=0.24.2)", "scipy", "torch"] test = ["fakeredis[lua]", "greenlet", "grpcio", "kaleido (<0.4)", "moto", "protobuf (>=5.28.1)", "pytest", "pytest-xdist", "scipy (>=1.9.2)", "torch"] +[[package]] +name = "osqp" +version = "1.1.1" +description = "OSQP: The Operator Splitting QP Solver" +optional = false +python-versions = ">=3.8" +groups = ["tests"] +files = [ + {file = "osqp-1.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:415096d3cf1710a2200a7e70c0c69591abef9081ce3ef8efb8fe16b14e214726"}, + {file = "osqp-1.1.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b3f26a5deb848e577d3b8b03c129be141756f3675297c38c128d556ab6216fb8"}, + {file = "osqp-1.1.1-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9974235f05905317cd01cf6c6e526fa97f9097812c2c5c3e4dc479c07cdf9d55"}, + {file = "osqp-1.1.1-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f7328e138fe8c2f40a8235d1f47593a0437bc48e29aad5c14ab7b3dafa6baf17"}, + {file = "osqp-1.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:de3aaa7b3db1c61c288d710be5b190894d0475d3fdb13969a6fe823f6c0c5634"}, + {file = "osqp-1.1.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:48a6f62df0ec55a5a3a445e4143f51a813931f1e48ac006b15b7e5c9899e2937"}, + {file = "osqp-1.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0e569d36955e1a69129f391bb27b2240b3b69d0bcff28e5d19446013dda59836"}, + {file = "osqp-1.1.1-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9fd6d87d5aa17161c43b95e44ab53c76cef466b851cc4ed32da658596cb0a0a1"}, + {file = "osqp-1.1.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2a0481c1f19f70eea9e9883b176eb37b64cd52525920c9ed765acb02411998ae"}, + {file = "osqp-1.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:d7524d22e91a8381ed30eecbfdf82935528f84b3d8a1b5ad1f8dd84dff3fc07e"}, + {file = "osqp-1.1.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ca4e41477852f725293c666ffa5f795413151c9a14155a7750dff25d3107b851"}, + {file = "osqp-1.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:25cd4e8995d18b65c54d1163769797665b9ca5a8a0009f1c4adf4dafe30e33be"}, + {file = "osqp-1.1.1-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ed006d74017578fe98a2afad77f4bbeb096f2d64aa00f50809bb394a7bbd98bf"}, + {file = "osqp-1.1.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:61aca4a356d1555d13c26166c282b9b7985c6c715baf093f839e338e6b49aca0"}, + {file = "osqp-1.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:cd4ac30fd125e12ef5b67836442ebd3bb90925828816e0253e96a203197f5dc7"}, + {file = "osqp-1.1.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4da548997e7187b1b55358ef291fbb3f9d29b6103917bedbbe77ab8d2307a43a"}, + {file = "osqp-1.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e33d9de8e6d68a77ef5ca3fee77d42fac89fb5c3fbac3ab5df452176009d28be"}, + {file = "osqp-1.1.1-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:64c45eb7a2ef39751417d964c792f3bfe396642b8bc1ae6eca7b28aaa7398ca5"}, + {file = "osqp-1.1.1-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b3c726d8516d90b2d6acb47acf0bef248188119c52692cca307e418f0f2d8fad"}, + {file = "osqp-1.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:b1bd86a9fb19f484705acdff47ec89d68af5c12fba9def921df503bc6bca8e39"}, + {file = "osqp-1.1.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:42315f8047708c7a2ae184df2255a2b5d323164e67a20df5c03ecd9b4208f2f7"}, + {file = "osqp-1.1.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:610a4ecba7a274348f95eeb3c6d56d131207482b6ad95bd20e2a5e4f87111887"}, + {file = "osqp-1.1.1-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a1532b0ade13cb10d8875e121e6131448528fb79e931ffb5dccef555b26b464e"}, + {file = "osqp-1.1.1-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a1ee59dbda22d283de001e7948f7523f509279f7131d5abf0e53fc5ab66b8bb0"}, + {file = "osqp-1.1.1-cp314-cp314-win_amd64.whl", hash = "sha256:514b2e1d14b5bad9a91ff4dbcbad8da75ef4fb5eee18864e0bbbb620fc6dbcd7"}, + {file = "osqp-1.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:416b38a30dcee915b9abe0acb54306a173f08fb4d58bdd21ff9b89ea048da39d"}, + {file = "osqp-1.1.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:32b7c4d759766064d76a8165dee823e956f7091e62e0194c2ef22c8209b302c7"}, + {file = "osqp-1.1.1-cp38-cp38-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4d669fd429e717df123ba2913f0aaee2df42e1739380eb10b9ebc07312c804c4"}, + {file = "osqp-1.1.1-cp38-cp38-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:be5ec70477c038d78048de3e9c4f1600c33bd08dcbfb0cebccc054eaac86b081"}, + {file = "osqp-1.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:5f382886682aee5e6536b80272fb955eaa1c89b83770a4cfd2474449a2753409"}, + {file = "osqp-1.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e2eb72980685a59d57bcb61a32559bddb61deaf3ee275a68e70c77ecb9da2910"}, + {file = "osqp-1.1.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:24a9c749a0d8d9378483c55a8519244e1c6789c6f3c4638a6e546178c70fccc4"}, + {file = "osqp-1.1.1-cp39-cp39-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1e8c0078682646260a8c154fd9042f006a60426736ffa495ac1c358723a1d7f7"}, + {file = "osqp-1.1.1-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e506467e88d9552f07bb2005adce569619d01fd8d2c8676213e7cfede2feeb24"}, + {file = "osqp-1.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:89988e8661ab43b139013e9e37c34e18d5ae0c084f296db87c31b97a8d95b9be"}, + {file = "osqp-1.1.1.tar.gz", hash = "sha256:1719e6a88f2ec2bd5dab06131331d1433152fb222372832727d9eb5604d7acf4"}, +] + +[package.dependencies] +jinja2 = "*" +joblib = "*" +numpy = ">=1.7" +scipy = ">=0.13.2" +setuptools = "*" + +[package.extras] +cu12 = ["osqp-cu12"] +dev = ["pre-commit", "pytest (>=6)", "scipy (!=1.12.0)", "torch"] +mkl = ["osqp-mkl"] + [[package]] name = "packaging" version = "26.0" @@ -2558,61 +2862,61 @@ xml = ["lxml (>=4.9.2)"] [[package]] name = "pandas" -version = "3.0.0" +version = "3.0.1" description = "Powerful data structures for data analysis, time series, and statistics" optional = false python-versions = ">=3.11" groups = ["docs"] markers = "python_version >= \"3.11\"" files = [ - {file = "pandas-3.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d64ce01eb9cdca96a15266aa679ae50212ec52757c79204dbc7701a222401850"}, - {file = "pandas-3.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:613e13426069793aa1ec53bdcc3b86e8d32071daea138bbcf4fa959c9cdaa2e2"}, - {file = "pandas-3.0.0-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0192fee1f1a8e743b464a6607858ee4b071deb0b118eb143d71c2a1d170996d5"}, - {file = "pandas-3.0.0-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f0b853319dec8d5e0c8b875374c078ef17f2269986a78168d9bd57e49bf650ae"}, - {file = "pandas-3.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:707a9a877a876c326ae2cb640fbdc4ef63b0a7b9e2ef55c6df9942dcee8e2af9"}, - {file = "pandas-3.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:afd0aa3d0b5cda6e0b8ffc10dbcca3b09ef3cbcd3fe2b27364f85fdc04e1989d"}, - {file = "pandas-3.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:113b4cca2614ff7e5b9fee9b6f066618fe73c5a83e99d721ffc41217b2bf57dd"}, - {file = "pandas-3.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:c14837eba8e99a8da1527c0280bba29b0eb842f64aa94982c5e21227966e164b"}, - {file = "pandas-3.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:9803b31f5039b3c3b10cc858c5e40054adb4b29b4d81cb2fd789f4121c8efbcd"}, - {file = "pandas-3.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:14c2a4099cd38a1d18ff108168ea417909b2dea3bd1ebff2ccf28ddb6a74d740"}, - {file = "pandas-3.0.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d257699b9a9960e6125686098d5714ac59d05222bef7a5e6af7a7fd87c650801"}, - {file = "pandas-3.0.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:69780c98f286076dcafca38d8b8eee1676adf220199c0a39f0ecbf976b68151a"}, - {file = "pandas-3.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4a66384f017240f3858a4c8a7cf21b0591c3ac885cddb7758a589f0f71e87ebb"}, - {file = "pandas-3.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:be8c515c9bc33989d97b89db66ea0cececb0f6e3c2a87fcc8b69443a6923e95f"}, - {file = "pandas-3.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:a453aad8c4f4e9f166436994a33884442ea62aa8b27d007311e87521b97246e1"}, - {file = "pandas-3.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:da768007b5a33057f6d9053563d6b74dd6d029c337d93c6d0d22a763a5c2ecc0"}, - {file = "pandas-3.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b78d646249b9a2bc191040988c7bb524c92fa8534fb0898a0741d7e6f2ffafa6"}, - {file = "pandas-3.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bc9cba7b355cb4162442a88ce495e01cb605f17ac1e27d6596ac963504e0305f"}, - {file = "pandas-3.0.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3c9a1a149aed3b6c9bf246033ff91e1b02d529546c5d6fb6b74a28fea0cf4c70"}, - {file = "pandas-3.0.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:95683af6175d884ee89471842acfca29172a85031fccdabc35e50c0984470a0e"}, - {file = "pandas-3.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1fbbb5a7288719e36b76b4f18d46ede46e7f916b6c8d9915b756b0a6c3f792b3"}, - {file = "pandas-3.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8e8b9808590fa364416b49b2a35c1f4cf2785a6c156935879e57f826df22038e"}, - {file = "pandas-3.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:98212a38a709feb90ae658cb6227ea3657c22ba8157d4b8f913cd4c950de5e7e"}, - {file = "pandas-3.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:177d9df10b3f43b70307a149d7ec49a1229a653f907aa60a48f1877d0e6be3be"}, - {file = "pandas-3.0.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2713810ad3806767b89ad3b7b69ba153e1c6ff6d9c20f9c2140379b2a98b6c98"}, - {file = "pandas-3.0.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:15d59f885ee5011daf8335dff47dcb8a912a27b4ad7826dc6cbe809fd145d327"}, - {file = "pandas-3.0.0-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:24e6547fb64d2c92665dd2adbfa4e85fa4fd70a9c070e7cfb03b629a0bbab5eb"}, - {file = "pandas-3.0.0-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:48ee04b90e2505c693d3f8e8f524dab8cb8aaf7ddcab52c92afa535e717c4812"}, - {file = "pandas-3.0.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:66f72fb172959af42a459e27a8d8d2c7e311ff4c1f7db6deb3b643dbc382ae08"}, - {file = "pandas-3.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:4a4a400ca18230976724a5066f20878af785f36c6756e498e94c2a5e5d57779c"}, - {file = "pandas-3.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:940eebffe55528074341a5a36515f3e4c5e25e958ebbc764c9502cfc35ba3faa"}, - {file = "pandas-3.0.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:597c08fb9fef0edf1e4fa2f9828dd27f3d78f9b8c9b4a748d435ffc55732310b"}, - {file = "pandas-3.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:447b2d68ac5edcbf94655fe909113a6dba6ef09ad7f9f60c80477825b6c489fe"}, - {file = "pandas-3.0.0-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:debb95c77ff3ed3ba0d9aa20c3a2f19165cc7956362f9873fce1ba0a53819d70"}, - {file = "pandas-3.0.0-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fedabf175e7cd82b69b74c30adbaa616de301291a5231138d7242596fc296a8d"}, - {file = "pandas-3.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:412d1a89aab46889f3033a386912efcdfa0f1131c5705ff5b668dda88305e986"}, - {file = "pandas-3.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:e979d22316f9350c516479dd3a92252be2937a9531ed3a26ec324198a99cdd49"}, - {file = "pandas-3.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:083b11415b9970b6e7888800c43c82e81a06cd6b06755d84804444f0007d6bb7"}, - {file = "pandas-3.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:5db1e62cb99e739fa78a28047e861b256d17f88463c76b8dafc7c1338086dca8"}, - {file = "pandas-3.0.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:697b8f7d346c68274b1b93a170a70974cdc7d7354429894d5927c1effdcccd73"}, - {file = "pandas-3.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:8cb3120f0d9467ed95e77f67a75e030b67545bcfa08964e349252d674171def2"}, - {file = "pandas-3.0.0-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:33fd3e6baa72899746b820c31e4b9688c8e1b7864d7aec2de7ab5035c285277a"}, - {file = "pandas-3.0.0-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a8942e333dc67ceda1095227ad0febb05a3b36535e520154085db632c40ad084"}, - {file = "pandas-3.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:783ac35c4d0fe0effdb0d67161859078618b1b6587a1af15928137525217a721"}, - {file = "pandas-3.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:125eb901e233f155b268bbef9abd9afb5819db74f0e677e89a61b246228c71ac"}, - {file = "pandas-3.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b86d113b6c109df3ce0ad5abbc259fe86a1bd4adfd4a31a89da42f84f65509bb"}, - {file = "pandas-3.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:1c39eab3ad38f2d7a249095f0a3d8f8c22cc0f847e98ccf5bbe732b272e2d9fa"}, - {file = "pandas-3.0.0.tar.gz", hash = "sha256:0facf7e87d38f721f0af46fe70d97373a37701b1c09f7ed7aeeb292ade5c050f"}, + {file = "pandas-3.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:de09668c1bf3b925c07e5762291602f0d789eca1b3a781f99c1c78f6cac0e7ea"}, + {file = "pandas-3.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:24ba315ba3d6e5806063ac6eb717504e499ce30bd8c236d8693a5fd3f084c796"}, + {file = "pandas-3.0.1-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:406ce835c55bac912f2a0dcfaf27c06d73c6b04a5dde45f1fd3169ce31337389"}, + {file = "pandas-3.0.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:830994d7e1f31dd7e790045235605ab61cff6c94defc774547e8b7fdfbff3dc7"}, + {file = "pandas-3.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a64ce8b0f2de1d2efd2ae40b0abe7f8ae6b29fbfb3812098ed5a6f8e235ad9bf"}, + {file = "pandas-3.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9832c2c69da24b602c32e0c7b1b508a03949c18ba08d4d9f1c1033426685b447"}, + {file = "pandas-3.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:84f0904a69e7365f79a0c77d3cdfccbfb05bf87847e3a51a41e1426b0edb9c79"}, + {file = "pandas-3.0.1-cp311-cp311-win_arm64.whl", hash = "sha256:4a68773d5a778afb31d12e34f7dd4612ab90de8c6fb1d8ffe5d4a03b955082a1"}, + {file = "pandas-3.0.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:476f84f8c20c9f5bc47252b66b4bb25e1a9fc2fa98cead96744d8116cb85771d"}, + {file = "pandas-3.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0ab749dfba921edf641d4036c4c21c0b3ea70fea478165cb98a998fb2a261955"}, + {file = "pandas-3.0.1-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b8e36891080b87823aff3640c78649b91b8ff6eea3c0d70aeabd72ea43ab069b"}, + {file = "pandas-3.0.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:532527a701281b9dd371e2f582ed9094f4c12dd9ffb82c0c54ee28d8ac9520c4"}, + {file = "pandas-3.0.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:356e5c055ed9b0da1580d465657bc7d00635af4fd47f30afb23025352ba764d1"}, + {file = "pandas-3.0.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9d810036895f9ad6345b8f2a338dd6998a74e8483847403582cab67745bff821"}, + {file = "pandas-3.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:536232a5fe26dd989bd633e7a0c450705fdc86a207fec7254a55e9a22950fe43"}, + {file = "pandas-3.0.1-cp312-cp312-win_arm64.whl", hash = "sha256:0f463ebfd8de7f326d38037c7363c6dacb857c5881ab8961fb387804d6daf2f7"}, + {file = "pandas-3.0.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5272627187b5d9c20e55d27caf5f2cd23e286aba25cadf73c8590e432e2b7262"}, + {file = "pandas-3.0.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:661e0f665932af88c7877f31da0dc743fe9c8f2524bdffe23d24fdcb67ef9d56"}, + {file = "pandas-3.0.1-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:75e6e292ff898679e47a2199172593d9f6107fd2dd3617c22c2946e97d5df46e"}, + {file = "pandas-3.0.1-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1ff8cf1d2896e34343197685f432450ec99a85ba8d90cce2030c5eee2ef98791"}, + {file = "pandas-3.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:eca8b4510f6763f3d37359c2105df03a7a221a508f30e396a51d0713d462e68a"}, + {file = "pandas-3.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:06aff2ad6f0b94a17822cf8b83bbb563b090ed82ff4fe7712db2ce57cd50d9b8"}, + {file = "pandas-3.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:9fea306c783e28884c29057a1d9baa11a349bbf99538ec1da44c8476563d1b25"}, + {file = "pandas-3.0.1-cp313-cp313-win_arm64.whl", hash = "sha256:a8d37a43c52917427e897cb2e429f67a449327394396a81034a4449b99afda59"}, + {file = "pandas-3.0.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:d54855f04f8246ed7b6fc96b05d4871591143c46c0b6f4af874764ed0d2d6f06"}, + {file = "pandas-3.0.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4e1b677accee34a09e0dc2ce5624e4a58a1870ffe56fc021e9caf7f23cd7668f"}, + {file = "pandas-3.0.1-cp313-cp313t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a9cabbdcd03f1b6cd254d6dda8ae09b0252524be1592594c00b7895916cb1324"}, + {file = "pandas-3.0.1-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5ae2ab1f166668b41e770650101e7090824fd34d17915dd9cd479f5c5e0065e9"}, + {file = "pandas-3.0.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6bf0603c2e30e2cafac32807b06435f28741135cb8697eae8b28c7d492fc7d76"}, + {file = "pandas-3.0.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6c426422973973cae1f4a23e51d4ae85974f44871b24844e4f7de752dd877098"}, + {file = "pandas-3.0.1-cp313-cp313t-win_amd64.whl", hash = "sha256:b03f91ae8c10a85c1613102c7bef5229b5379f343030a3ccefeca8a33414cf35"}, + {file = "pandas-3.0.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:99d0f92ed92d3083d140bf6b97774f9f13863924cf3f52a70711f4e7588f9d0a"}, + {file = "pandas-3.0.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:3b66857e983208654294bb6477b8a63dee26b37bdd0eb34d010556e91261784f"}, + {file = "pandas-3.0.1-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:56cf59638bf24dc9bdf2154c81e248b3289f9a09a6d04e63608c159022352749"}, + {file = "pandas-3.0.1-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c1a9f55e0f46951874b863d1f3906dcb57df2d9be5c5847ba4dfb55b2c815249"}, + {file = "pandas-3.0.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:1849f0bba9c8a2fb0f691d492b834cc8dadf617e29015c66e989448d58d011ee"}, + {file = "pandas-3.0.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:c3d288439e11b5325b02ae6e9cc83e6805a62c40c5a6220bea9beb899c073b1c"}, + {file = "pandas-3.0.1-cp314-cp314-win_amd64.whl", hash = "sha256:93325b0fe372d192965f4cca88d97667f49557398bbf94abdda3bf1b591dbe66"}, + {file = "pandas-3.0.1-cp314-cp314-win_arm64.whl", hash = "sha256:97ca08674e3287c7148f4858b01136f8bdfe7202ad25ad04fec602dd1d29d132"}, + {file = "pandas-3.0.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:58eeb1b2e0fb322befcf2bbc9ba0af41e616abadb3d3414a6bc7167f6cbfce32"}, + {file = "pandas-3.0.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:cd9af1276b5ca9e298bd79a26bda32fa9cc87ed095b2a9a60978d2ca058eaf87"}, + {file = "pandas-3.0.1-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:94f87a04984d6b63788327cd9f79dda62b7f9043909d2440ceccf709249ca988"}, + {file = "pandas-3.0.1-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:85fe4c4df62e1e20f9db6ebfb88c844b092c22cd5324bdcf94bfa2fc1b391221"}, + {file = "pandas-3.0.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:331ca75a2f8672c365ae25c0b29e46f5ac0c6551fdace8eec4cd65e4fac271ff"}, + {file = "pandas-3.0.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:15860b1fdb1973fffade772fdb931ccf9b2f400a3f5665aef94a00445d7d8dd5"}, + {file = "pandas-3.0.1-cp314-cp314t-win_amd64.whl", hash = "sha256:44f1364411d5670efa692b146c748f4ed013df91ee91e9bec5677fb1fd58b937"}, + {file = "pandas-3.0.1-cp314-cp314t-win_arm64.whl", hash = "sha256:108dd1790337a494aa80e38def654ca3f0968cf4f362c85f44c15e471667102d"}, + {file = "pandas-3.0.1.tar.gz", hash = "sha256:4186a699674af418f655dbd420ed87f50d56b4cd6603784279d9eef6627823c8"}, ] [package.dependencies] @@ -2822,21 +3126,16 @@ xmp = ["defusedxml"] [[package]] name = "platformdirs" -version = "4.5.1" +version = "4.9.2" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false python-versions = ">=3.10" groups = ["docs", "tests"] files = [ - {file = "platformdirs-4.5.1-py3-none-any.whl", hash = "sha256:d03afa3963c806a9bed9d5125c8f4cb2fdaf74a55ab60e5d59b3fde758104d31"}, - {file = "platformdirs-4.5.1.tar.gz", hash = "sha256:61d5cdcc6065745cdd94f0f878977f8de9437be93de97c1c12f853c9c0cdcbda"}, + {file = "platformdirs-4.9.2-py3-none-any.whl", hash = "sha256:9170634f126f8efdae22fb58ae8a0eaa86f38365bc57897a6c4f781d1f5875bd"}, + {file = "platformdirs-4.9.2.tar.gz", hash = "sha256:9a33809944b9db043ad67ca0db94b14bf452cc6aeaac46a88ea55b26e2e9d291"}, ] -[package.extras] -docs = ["furo (>=2025.9.25)", "proselint (>=0.14)", "sphinx (>=8.2.3)", "sphinx-autodoc-typehints (>=3.2)"] -test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.4.2)", "pytest-cov (>=7)", "pytest-mock (>=3.15.1)"] -type = ["mypy (>=1.18.2)"] - [[package]] name = "pluggy" version = "1.6.0" @@ -2967,12 +3266,12 @@ version = "3.0" description = "C parser in Python" optional = false python-versions = ">=3.10" -groups = ["docs"] -markers = "implementation_name == \"pypy\"" +groups = ["docs", "tests"] files = [ {file = "pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992"}, {file = "pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29"}, ] +markers = {docs = "implementation_name == \"pypy\"", tests = "implementation_name != \"PyPy\""} [[package]] name = "pydantic" @@ -3125,6 +3424,30 @@ files = [ [package.extras] windows-terminal = ["colorama (>=0.4.6)"] +[[package]] +name = "pygridsynth" +version = "2.0.0" +description = "Python version gridsynth program computes approximations of Z-rotations over the Clifford+T gate set" +optional = false +python-versions = ">=3.10" +groups = ["tests"] +files = [ + {file = "pygridsynth-2.0.0-py3-none-any.whl", hash = "sha256:30b5b15e9383a8ea8510d54f28e2de0385d102cb54fd4440071abf4525027568"}, + {file = "pygridsynth-2.0.0.tar.gz", hash = "sha256:230cc0c2956f34c568ed0ae97461b04f03cf2499cc1fa3ce34b2bf5aeba3ee7d"}, +] + +[package.dependencies] +cvxpy = "*" +matplotlib = "*" +mpmath = ">=1.3" +numba = "*" +numpy = "*" +scipy = "*" +setuptools = "*" + +[package.extras] +dev = ["black", "flake8", "isort", "mypy", "pytest"] + [[package]] name = "pylint" version = "3.3.9" @@ -3634,7 +3957,7 @@ cuquantum = ["cuquantum-python-cu12 (>=24.1.0,<25.0.0)"] type = "git" url = "https://github.com/qiboteam/qibojit.git" reference = "HEAD" -resolved_reference = "182dc68194efcbc88e0b303db252e050dd1e46d8" +resolved_reference = "4e23bc6e4ca761260eb05f8f9e9a440ee7f692eb" [[package]] name = "qiskit" @@ -4070,6 +4393,56 @@ dev = ["click (<8.3.0)", "cython-lint (>=0.12.2)", "mypy (==1.10.0)", "pycodesty doc = ["intersphinx_registry", "jupyterlite-pyodide-kernel", "jupyterlite-sphinx (>=0.19.1)", "jupytext", "linkify-it-py", "matplotlib (>=3.5)", "myst-nb (>=1.2.0)", "numpydoc", "pooch", "pydata-sphinx-theme (>=0.15.2)", "sphinx (>=5.0.0,<8.2.0)", "sphinx-copybutton", "sphinx-design (>=0.4.0)", "tabulate"] test = ["Cython", "array-api-strict (>=2.3.1)", "asv", "gmpy2", "hypothesis (>=6.30)", "meson", "mpmath", "ninja ; sys_platform != \"emscripten\"", "pooch", "pytest (>=8.0.0)", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"] +[[package]] +name = "scs" +version = "3.2.11" +description = "Splitting conic solver" +optional = false +python-versions = ">=3.9" +groups = ["tests"] +files = [ + {file = "scs-3.2.11-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:928b2fd09d1f4446bd440037d8ca4fb70eb55e411c3259461646ba909ed098f7"}, + {file = "scs-3.2.11-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ace8221013596173de6bdf199d4415f6532b38372e7b68ff22f688b7de2a72bf"}, + {file = "scs-3.2.11-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d0a42a6df9308f7a7dc5e5f6c9cc08a4f556e139e39dc7d7fe1f1c6768d7ff9a"}, + {file = "scs-3.2.11-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c839603fd99d719d27b63918e0eff9e6f1df594506c5fd0dd1529a0df0219243"}, + {file = "scs-3.2.11-cp310-cp310-win_amd64.whl", hash = "sha256:8c56c9739da8d06c10a94f84c5715ff0731bb2efce695a83e07c116eb1c48dcf"}, + {file = "scs-3.2.11-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:698bdf36c67acc43b7a65f1ffa13d11d09b7050f4da6dd5b9c05080e10d198f7"}, + {file = "scs-3.2.11-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6aece172705a6e3b04b54b49558d580ab71be02c2fa8fba12b35012e1f386e9c"}, + {file = "scs-3.2.11-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:67a9bf34da4be7baf28eb50c8ea7d2e29ae5f345e4b04f057ba3dbeca42efbba"}, + {file = "scs-3.2.11-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9810701691de9da18d98e542e4f8900e197ec501a47b3a4c1c76242cba133453"}, + {file = "scs-3.2.11-cp311-cp311-win_amd64.whl", hash = "sha256:4bd13200492b9ea334a3c50c17ccbfc9359b206bf7a4f0b022504ebc34e11cda"}, + {file = "scs-3.2.11-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ad646848375b5cf2d3e45a9ebefd87ccc37a53da9c32f2bf30ea5ad0e84d9e5b"}, + {file = "scs-3.2.11-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f30821521a74f6930924b13e731e9455b6bdcfc964f66d5623d3c8d3fdd98126"}, + {file = "scs-3.2.11-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8a89c71ebacd4790c461d3032a47e59ed4759e11c0f03fa79b5b84086ef9c7bc"}, + {file = "scs-3.2.11-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4e37dc60081dd742bdcd63eeb5b260db116b3803162bcf6084eb203ebedcb080"}, + {file = "scs-3.2.11-cp312-cp312-win_amd64.whl", hash = "sha256:2504266ff8e6a226f7ecb987567c93e6e996534cbf479a60a5a886549446205e"}, + {file = "scs-3.2.11-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a42696b0a26c3e749b8da8d2ffc57a93af4f0f500fc3a83acb50daad92386de4"}, + {file = "scs-3.2.11-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:50d204ae417c014a1756be36e8c0b857ed39c7b64e2c63b6afb1ff64c0a465d0"}, + {file = "scs-3.2.11-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:594c09207395de922e0ff40ced562453e46f4f197dd0128022cb82c096f06615"}, + {file = "scs-3.2.11-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fd672701ed81744e8c300df71d823700b05e7fe3d6a26f8b19b74b0a31fe3c8a"}, + {file = "scs-3.2.11-cp313-cp313-win_amd64.whl", hash = "sha256:2f4ebc0be14783ce3fcda61c616a7e922ac528af033e44a0da952dda0fe98091"}, + {file = "scs-3.2.11-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:fe43181c3822bed600363c25c7566a643b319e0edb0c2af385c5f086a9c826d2"}, + {file = "scs-3.2.11-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b3c59ce43585d3ea0c6771c5ce3df272b6c8239231acbb9567876be5d0a0474d"}, + {file = "scs-3.2.11-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3c46f597892c9f8c5551bb9a3a680dfb86e86a1a6c3bc67b09a5af2e89ba5357"}, + {file = "scs-3.2.11-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:513131af6991fb4983f84c4ba276c756c0a3574003c2790dda891c68d5b6da30"}, + {file = "scs-3.2.11-cp314-cp314-win_amd64.whl", hash = "sha256:7b2c37e87baca0389f005fe19a0ca8209d43c0f1e9136a1a6fde23cae1735db9"}, + {file = "scs-3.2.11-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:29c0a5c233fb5a964ea5f7523ec2b2209f000217c0a24423ab5dcd8b8922f37d"}, + {file = "scs-3.2.11-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7519c2f436e793b004d1eae4aaf98c18857e519f8169219d1167fe88b3b0a568"}, + {file = "scs-3.2.11-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2c166768dc87c389b2d000b5dcd472bb0ba40f96b4cf0e63c0fb603a4a5c80db"}, + {file = "scs-3.2.11-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f51a14a5315974fae4ca4e1b4dc8926f872eca7e66b42e070dbdcfa6904b7860"}, + {file = "scs-3.2.11-cp314-cp314t-win_amd64.whl", hash = "sha256:7fe26e8a0efc96232f4c5b7649817e48dae04a61be911417e925071091b8cbf6"}, + {file = "scs-3.2.11-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a58e2be11a6eeb03463ab57accfac96fbe4a64168b32769ecca0a35962c86231"}, + {file = "scs-3.2.11-cp39-cp39-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9761271e2efd4ae06af7cde4d367c99c82fddb6e6c7542fa6f4d02526d0888ef"}, + {file = "scs-3.2.11-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f6ec937514d613181ec0b27df6d7fc33a06ada7769da419a1a98c846528758b6"}, + {file = "scs-3.2.11-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:4f9e1abcac09bddc6a6d9e5955440e5cd26fb51371759491b3100cffa8ebad2f"}, + {file = "scs-3.2.11-cp39-cp39-win_amd64.whl", hash = "sha256:caf85064e7ee78001ea205205b8a8c59e134f912e8d7491cc702a64af8cc7227"}, + {file = "scs-3.2.11.tar.gz", hash = "sha256:2a5455cf2093d07f84f2f848c199faed52e79cdb3a11fe250b5622b6bbac4913"}, +] + +[package.dependencies] +numpy = "*" +scipy = "*" + [[package]] name = "seaborn" version = "0.13.2" @@ -4092,6 +4465,27 @@ dev = ["flake8", "flit", "mypy", "pandas-stubs", "pre-commit", "pytest", "pytest docs = ["ipykernel", "nbconvert", "numpydoc", "pydata_sphinx_theme (==0.10.0rc2)", "pyyaml", "sphinx (<6.0.0)", "sphinx-copybutton", "sphinx-design", "sphinx-issues"] stats = ["scipy (>=1.7)", "statsmodels (>=0.12)"] +[[package]] +name = "setuptools" +version = "82.0.0" +description = "Easily download, build, install, upgrade, and uninstall Python packages" +optional = false +python-versions = ">=3.9" +groups = ["tests"] +files = [ + {file = "setuptools-82.0.0-py3-none-any.whl", hash = "sha256:70b18734b607bd1da571d097d236cfcfacaf01de45717d59e6e04b96877532e0"}, + {file = "setuptools-82.0.0.tar.gz", hash = "sha256:22e0a2d69474c6ae4feb01951cb69d515ed23728cf96d05513d36e42b62b37cb"}, +] + +[package.extras] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\"", "ruff (>=0.13.0) ; sys_platform != \"cygwin\""] +core = ["importlib_metadata (>=6) ; python_version < \"3.10\"", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1) ; python_version < \"3.11\"", "wheel (>=0.43.0)"] +cover = ["pytest-cov"] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"] +enabler = ["pytest-enabler (>=2.2)"] +test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21) ; python_version >= \"3.9\" and sys_platform != \"cygwin\"", "jaraco.envs (>=2.2)", "jaraco.path (>=3.7.2)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf ; sys_platform != \"cygwin\"", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] +type = ["importlib_metadata (>=7.0.2) ; python_version < \"3.10\"", "jaraco.develop (>=7.21) ; sys_platform != \"cygwin\"", "mypy (==1.18.*)", "pytest-mypy"] + [[package]] name = "six" version = "1.17.0" @@ -4453,14 +4847,14 @@ tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"] [[package]] name = "stevedore" -version = "5.6.0" +version = "5.7.0" description = "Manage dynamic plugins for Python applications" optional = false python-versions = ">=3.10" groups = ["tests"] files = [ - {file = "stevedore-5.6.0-py3-none-any.whl", hash = "sha256:4a36dccefd7aeea0c70135526cecb7766c4c84c473b1af68db23d541b6dc1820"}, - {file = "stevedore-5.6.0.tar.gz", hash = "sha256:f22d15c6ead40c5bbfa9ca54aa7e7b4a07d59b36ae03ed12ced1a54cf0b51945"}, + {file = "stevedore-5.7.0-py3-none-any.whl", hash = "sha256:fd25efbb32f1abb4c9e502f385f0018632baac11f9ee5d1b70f88cc5e22ad4ed"}, + {file = "stevedore-5.7.0.tar.gz", hash = "sha256:31dd6fe6b3cbe921e21dcefabc9a5f1cf848cf538a1f27543721b8ca09948aa3"}, ] [[package]] @@ -4804,4 +5198,4 @@ qulacs = ["qulacs"] [metadata] lock-version = "2.1" python-versions = ">=3.10,<3.14" -content-hash = "aca0e674cb63daff7359d654c3ae7c7fd29b838dc2d8e73f583f6f24db9cf651" +content-hash = "053ba9a6525eb842c38b2fdb4dfa5350ad38cb706553efaf66e60f2bf1518a6a" diff --git a/pyproject.toml b/pyproject.toml index 2e1843660e..57a297d6be 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -70,10 +70,11 @@ pytest-cov = "^4.0.0" pylint = "^3.3.5" matplotlib = "^3.7.0" qibojit = { git = "https://github.com/qiboteam/qibojit.git" } -stim = "^1.12.0" +stim = "^1.15.0" qulacs = { version = "^0.6.4", python = "<3.13" } qiskit = "^2.2.3" qbraid = { version = "^0.10.0", extras = ["cudaq", "qir"] } +pygridsynth = "^2.0.0" [tool.poe.tasks] test = "pytest" diff --git a/src/qibo/backends/__init__.py b/src/qibo/backends/__init__.py index 65c3d4ad6c..d8c429d5a4 100644 --- a/src/qibo/backends/__init__.py +++ b/src/qibo/backends/__init__.py @@ -147,8 +147,8 @@ def _default_transpiler(cls): from qibo.transpiler.router import Sabre from qibo.transpiler.unroller import NativeGates, Unroller - qubits = cls._backend.qubits - natives = cls._backend.natives + qubits = cls.backend().qubits + natives = cls.backend().natives connectivity_edges = cls._backend.connectivity if qubits is not None and natives is not None: connectivity = ( @@ -189,9 +189,11 @@ def create(self, dtype): if dtype in ("complex64", "complex128"): self.Y = self.matrices.Y self.SX = self.matrices.SX + self.SXDG = self.matrices.SXDG self.S = self.matrices.S - self.T = self.matrices.T self.SDG = self.matrices.SDG + self.T = self.matrices.T + self.TDG = self.matrices.TDG self.CY = self.matrices.CY self.CSX = self.matrices.CSX self.CSXDG = self.matrices.CSXDG diff --git a/src/qibo/backends/clifford.py b/src/qibo/backends/clifford.py index e7d19e6fd3..b8bee994a4 100644 --- a/src/qibo/backends/clifford.py +++ b/src/qibo/backends/clifford.py @@ -18,11 +18,15 @@ class CliffordBackend(Backend): - """Backend for the simulation of Clifford circuits following + """Backend for the simulation of Clifford circuits following Ref. [1]. `Aaronson & Gottesman (2004) `_. Args: :class:`qibo.backends.abstract.Backend`: Backend used for the calculation. + + References: + 1. S. Aaronson and D. Gottesman, *Improved Simulation of Stabilizer Circuits*, + `Phys. Rev. A 70, 052328 (2004) `_. """ def __init__(self, platform: Optional[str] = None): diff --git a/src/qibo/gates/abstract.py b/src/qibo/gates/abstract.py index ce069b5f2a..a6fbc6d1ac 100644 --- a/src/qibo/gates/abstract.py +++ b/src/qibo/gates/abstract.py @@ -1,12 +1,13 @@ """Module defines the abstract gate classes Gate, SpecialGate, ParametrizedGate.""" -import collections import json from abc import abstractmethod +from collections.abc import Iterable from math import pi from typing import List, Sequence, Tuple import sympy +from numpy.typing import ArrayLike from qibo import config from qibo.config import raise_error @@ -90,40 +91,178 @@ def __init__(self): self._clifford = False + def apply(self, backend, state: ArrayLike, nqubits: int) -> ArrayLike: + return backend.apply_gate(self, state, nqubits) + + def apply_clifford(self, backend, state: ArrayLike, nqubits: int) -> ArrayLike: + return backend.apply_gate_clifford(self, state, nqubits) + + def basis_rotation(self): + """Transformation required to rotate the basis for measuring the gate.""" + raise_error( + NotImplementedError, + f"Basis rotation is not implemented for {self.__class__.__name__}", + ) + + def check_controls(func): # pylint: disable=E0213 + def wrapper(self, *args): + if self.control_qubits: + raise_error( + RuntimeError, + "Cannot use `controlled_by` method " + + f"on gate {self} because it is already " + + f"controlled by {self.control_qubits}.", + ) + return func(self, *args) # pylint: disable=E1102 + + return wrapper + @property - def clifford(self): + def clifford(self) -> bool: """Return boolean value representing if a Gate is Clifford or not.""" return False - @property - def hamming_weight(self): - """Return boolean value representing if a Gate is Hamming-weight-preserving or not.""" - return False + def commutes(self, gate) -> bool: + """Checks if two gates commute. + + Args: + gate: Gate to check if it commutes with the current gate. + + Returns: + bool: ``True`` if the gates commute, ``False`` otherwise. + """ + if isinstance(gate, SpecialGate): # pragma: no cover + return False + t1 = set(self.target_qubits) + t2 = set(gate.target_qubits) + a = self.__class__ == gate.__class__ and t1 == t2 + b = not (t1 & set(gate.qubits) or t2 & set(self.qubits)) + return a or b @property - def raw(self) -> dict: - """Serialize to dictionary. + def control_qubits(self) -> Tuple[int, ...]: + """Tuple with ids of control qubits sorted in increasing order.""" + return tuple(sorted(self._control_qubits)) - The values used in the serialization should be compatible with a - JSON dump (or any other one supporting a minimal set of scalar - types). Though the specific implementation is up to the specific - gate. + @control_qubits.setter + def control_qubits(self, qubits: Sequence[int]) -> None: + """Sets control qubits set.""" + self._set_control_qubits(qubits) + self._check_control_target_overlap() + + @check_controls + def controlled_by(self, *qubits: int): + """Controls the gate on (arbitrarily many) qubits. + + To see how this method affects the underlying matrix representation of a gate, + please see the documentation of :meth:`qibo.gates.Gate.matrix`. + + .. note:: + Some gate classes default to another gate class depending on the number of controls + present. For instance, an :math:`1`-controlled :class:`qibo.gates.X` gate + will default to a :class:`qibo.gates.CNOT` gate, while a :math:`2`-controlled + :class:`qibo.gates.X` gate defaults to a :class:`qibo.gates.TOFFOLI` gate. + Other gates affected by this method are: :class:`qibo.gates.Y`, :class:`qibo.gates.Z`, + :class:`qibo.gates.RX`, :class:`qibo.gates.RY`, :class:`qibo.gates.RZ`, + :class:`qibo.gates.U1`, :class:`qibo.gates.U2`, and :class:`qibo.gates.U3`. + + Args: + *qubits (int): Ids of the qubits that the gate will be controlled on. + + Returns: + :class:`qibo.gates.Gate`: object in with the corresponding + gate being controlled in the given qubits. """ - encoded = self.__dict__ + if qubits: + self.is_controlled_by = True + self.control_qubits = qubits + return self - encoded_simple = { - key: value for key, value in encoded.items() if key in REQUIRED_FIELDS - } + def dagger(self): + """Returns the dagger (conjugate transpose) of the gate. - encoded_simple["init_kwargs"] = { - key: value - for key, value in encoded_simple["init_kwargs"].items() - if key in REQUIRED_FIELDS_INIT_KWARGS - } + Note that dagger is not persistent for parametrized gates. + For example, applying a dagger to an :class:`qibo.gates.gates.RX` gate + will change the sign of its parameter at the time of application. + However, if the parameter is updated after that, for example using + :meth:`qibo.models.circuit.Circuit.set_parameters`, then the + action of dagger will be lost. - encoded_simple["_class"] = type(self).__name__ + Returns: + :class:`qibo.gates.Gate`: object representing the dagger of the original gate. + """ + new_gate = self._dagger() + new_gate.is_controlled_by = self.is_controlled_by + new_gate.control_qubits = self.control_qubits + if hasattr(self, "_clifford"): + new_gate._clifford = self._clifford - return encoded_simple + return new_gate + + def decompose( + self, *free, use_toffolis: bool = True, method: str = "standard", **kwargs + ): + """Decomposes multi-control gates to gates supported by OpenQASM. + + Decompositions are based on `arXiv:9503016 `_. + If the gate is already controlled, it recursively decomposes the base gate and updates + the control qubits accordingly. + + Args: + free (int): Ids of free qubits to use for the gate decomposition. + use_toffolis: If ``True`` the decomposition contains only ``TOFFOLI`` gates. + If ``False`` a congruent representation is used for ``TOFFOLI`` gates. + See :class:`qibo.gates.TOFFOLI` for more details on this representation. + method (str, optional): Choice of gate set for the decomposition. + If ``"standard"``, decomposes circuit into :class:`qibo.gates.gates.CNOT`, + :class:`qibo.gates.gates.RX`, :class:`qibo.gates.gates.RY`, + :class:`qibo.gates.gates.RZ`, :class:`qibo.gates.gates.U1`, + :class:`qibo.gates.gates.U2`, :class:`qibo.gates.gates.U3`, + and Clifford gates. If ``"clifford_plus_t"``, decomposes the circuit + into :class:`qibo.gates.gates.CNOT`, :class:`qibo.gates.gates.H`, + :class:`qibo.gates.gates.S`, :class:`qibo.gates.gates.X`, + :class:`qibo.gates.gates.Y`, :class:`qibo.gates.gates.Z`, + and :class:`qibo.gates.gates.T`. Defaults to ``"standard"``. + kwargs (dict, optional): Additional arguments. When ``method = "clifford_plus_t"``, + one can set ``epsilon`` (:math:`\\epsilon`) precision for the transpilation + of each gate into the Clifford + :class:`qibo.gates.gates.T` gate set. + This precision defaults to :math:`\\epsilon = 10^{-16}`. + Another possible keyword argument is ``mpmath_dps``, which defines the + number of decimal places used by the ``mpmath`` package. + ``mpmmath_dps`` defaults to :math:`256`. + + Returns: + List[:class:`qibo.gates.abstract.Gate`]: Gates that have the same effect as + applying the original gate. + """ + if self.is_controlled_by: + # Step 1: Error check with all controls/targets + if set(free) & set(self.qubits): # pragma: no cover + raise_error( + ValueError, + "Cannot decompose multi-controlled ``X`` gate if free " + "qubits coincide with target or controls.", + ) + + ncontrols = len(self.control_qubits) + + # Step 2: Decompose base gate without controls + base_gate = self.__class__(*self.init_args, **self.init_kwargs) + decomposed = base_gate._base_decompose( + *free, + use_toffolis=use_toffolis, + ncontrols=ncontrols, + method=method, + **kwargs, + ) + mask = self._control_mask_after_stripping(decomposed) + for bool_value, gate in zip(mask, decomposed): + if bool_value: + gate.is_controlled_by = True + gate.control_qubits += self.control_qubits + return decomposed + + return self._base_decompose(*free, use_toffolis=use_toffolis, method=method) @staticmethod def from_dict(raw: dict): @@ -144,7 +283,7 @@ def from_dict(raw: dict): # gate not found in given module, try next pass else: - raise ValueError(f"Unknown gate {raw['_class']}") + raise_error(ValueError, f"Unknown gate {raw['_class']}") gate = cls(*raw["init_args"], **raw["init_kwargs"]) if raw["_class"] == "M": @@ -162,131 +301,71 @@ def from_dict(raw: dict): return gate - def to_json(self): - """Dump gate to JSON. + @abstractmethod + def generator(self, backend): + """This function returns the gate's generator. - Note: - Consider using :meth:`raw` directly. + Returns: + ArrayLike: generator. """ - return json.dumps(self.raw) - - @property - def target_qubits(self) -> Tuple[int, ...]: - """Tuple with ids of target qubits.""" - return self._target_qubits - - @property - def control_qubits(self) -> Tuple[int, ...]: - """Tuple with ids of control qubits sorted in increasing order.""" - return tuple(sorted(self._control_qubits)) - @property - def qubits(self) -> Tuple[int, ...]: - """Tuple with ids of all qubits (control and target) that the gate acts.""" - return self.control_qubits + self.target_qubits + def generator_eigenvalue(self): + """This function returns the eigenvalues of the gate's generator. - @property - def qasm_label(self) -> str | Tuple[str, str]: - """String corresponding to OpenQASM operation of the gate. - For more exotic gates, both the internal qibo name of the gate - and the custom gate QASM definition are returned as a tuple for - broader compatibility. + Returns: + float: eigenvalue of the generator. """ + raise_error( NotImplementedError, - f"{self.__class__.__name__} is not supported by OpenQASM", + f"Generator eigenvalue is not implemented for {self.__class__.__name__}", ) - def _set_target_qubits(self, qubits: Sequence[int]): - """Helper method for setting target qubits.""" - self._target_qubits = tuple(qubits) - if len(self._target_qubits) != len(set(qubits)): - repeated = self._find_repeated(qubits) - raise_error( - ValueError, - f"Target qubit {repeated} was given twice for gate {self.__class__.__name__}.", - ) + @property + def hamming_weight(self) -> bool: + """Return boolean value representing if a Gate is Hamming-weight-preserving or not.""" + return False - def _set_control_qubits(self, qubits: Sequence[int]): - """Helper method for setting control qubits.""" - if len(set(qubits)) != len(qubits): - repeated = self._find_repeated(qubits) - raise_error( - ValueError, - f"Control qubit {repeated} was given twice for gate {self.__class__.__name__}.", - ) - self._control_qubits = qubits + def matrix(self, backend=None) -> ArrayLike: + """Returns the matrix representation of the gate. - @target_qubits.setter - def target_qubits(self, qubits: Sequence[int]): - """Sets target qubits tuple.""" - self._set_target_qubits(qubits) - self._check_control_target_overlap() + If gate has controlled qubits inserted by :meth:`qibo.gates.Gate.controlled_by`, + then :meth:`qibo.gates.Gate.matrix` returns the matrix of the original gate. - @control_qubits.setter - def control_qubits(self, qubits: Sequence[int]): - """Sets control qubits set.""" - self._set_control_qubits(qubits) - self._check_control_target_overlap() + .. code-block:: python - def _set_targets_and_controls( - self, target_qubits: Sequence[int], control_qubits: Sequence[int] - ): - """Sets target and control qubits simultaneously. + from qibo import gates - This is used for the reduced qubit updates in the distributed - circuits because using the individual setters may raise errors - due to temporary overlap of control and target qubits. - """ - self._set_target_qubits(target_qubits) - self._set_control_qubits(control_qubits) - self._check_control_target_overlap() + gate = gates.SWAP(3, 4).controlled_by(0, 1, 2) + print(gate.matrix()) - @staticmethod - def _find_repeated(qubits: Sequence[int]) -> int: - """Finds the first qubit id that is repeated in a sequence of qubit ids.""" - temp_set = set() - for qubit in qubits: - if qubit in temp_set: - return qubit - temp_set.add(qubit) + To return the full matrix that takes the control qubits into account, + one should use :meth:`qibo.models.Circuit.unitary`, e.g. - def _check_control_target_overlap(self): - """Checks that there are no qubits that are both target and - controls.""" - control_and_target = self._control_qubits + self._target_qubits - common = len(set(control_and_target)) != len(control_and_target) - if common: - raise_error( - ValueError, - f"{set(self._target_qubits) & set(self._control_qubits)}" - + "qubits are both targets and controls " - + f"for gate {self.__class__.__name__}.", - ) + .. code-block:: python - @property - def parameters(self): - """Returns a tuple containing the current value of gate's parameters.""" - return self._parameters + from qibo import Circuit, gates - def commutes(self, gate: "Gate") -> bool: - """Checks if two gates commute. + nqubits = 5 + circuit = Circuit(nqubits) + circuit.add(gates.SWAP(3, 4).controlled_by(0, 1, 2)) + print(circuit.unitary()) Args: - gate: Gate to check if it commutes with the current gate. + backend (:class:`qibo.backends.abstract.Backend`, optional): backend + to be used in the execution. If ``None``, it uses + the current backend. Defaults to ``None``. Returns: - bool: ``True`` if the gates commute, ``False`` otherwise. + ndarray: Matrix representation of gate. """ - if isinstance(gate, SpecialGate): # pragma: no cover - return False - t1 = set(self.target_qubits) - t2 = set(gate.target_qubits) - a = self.__class__ == gate.__class__ and t1 == t2 - b = not (t1 & set(gate.qubits) or t2 & set(self.qubits)) - return a or b + from qibo.backends import _check_backend # pylint: disable=C0415 - def on_qubits(self, qubit_map: dict) -> "Gate": + backend = _check_backend(backend) + + return backend.matrix(self) + + def on_qubits(self, qubit_map: dict): """Creates the same gate targeting different qubits. Args: @@ -339,76 +418,75 @@ def on_qubits(self, qubit_map: dict) -> "Gate": return gate - def _dagger(self) -> "Gate": - """Helper method for :meth:`qibo.gates.Gate.dagger`.""" - # By default the ``_dagger`` method creates an equivalent gate, assuming - # that the gate is Hermitian (true for common gates like H or Paulis). - # If the gate is not Hermitian the ``_dagger`` method should be modified. - return self.__class__(*self.init_args, **self.init_kwargs) + @property + def parameters(self) -> Tuple[float, ...]: + """Returns a tuple containing the current value of gate's parameters.""" + return self._parameters - def dagger(self) -> "Gate": - """Returns the dagger (conjugate transpose) of the gate. + @property + def qasm_label(self) -> str | Tuple[str, str]: + """String corresponding to OpenQASM operation of the gate. + For more exotic gates, both the internal qibo name of the gate + and the custom gate QASM definition are returned as a tuple for + broader compatibility. + """ + raise_error( + NotImplementedError, + f"{self.__class__.__name__} is not supported by OpenQASM", + ) - Note that dagger is not persistent for parametrized gates. - For example, applying a dagger to an :class:`qibo.gates.gates.RX` gate - will change the sign of its parameter at the time of application. - However, if the parameter is updated after that, for example using - :meth:`qibo.models.circuit.Circuit.set_parameters`, then the - action of dagger will be lost. + @property + def qubits(self) -> Tuple[int, ...]: + """Tuple with ids of all qubits (control and target) that the gate acts.""" + return self.control_qubits + self.target_qubits - Returns: - :class:`qibo.gates.Gate`: object representing the dagger of the original gate. - """ - new_gate = self._dagger() - new_gate.is_controlled_by = self.is_controlled_by - new_gate.control_qubits = self.control_qubits - if hasattr(self, "_clifford"): - new_gate._clifford = self._clifford + @property + def raw(self) -> dict: + """Serialize to dictionary. - return new_gate + The values used in the serialization should be compatible with a + JSON dump (or any other one supporting a minimal set of scalar + types). Though the specific implementation is up to the specific + gate. + """ + encoded = self.__dict__ - def check_controls(func): # pylint: disable=E0213 - def wrapper(self, *args): - if self.control_qubits: - raise_error( - RuntimeError, - "Cannot use `controlled_by` method " - + f"on gate {self} because it is already " - + f"controlled by {self.control_qubits}.", - ) - return func(self, *args) # pylint: disable=E1102 + encoded_simple = { + key: value for key, value in encoded.items() if key in REQUIRED_FIELDS + } - return wrapper + encoded_simple["init_kwargs"] = { + key: value + for key, value in encoded_simple["init_kwargs"].items() + if key in REQUIRED_FIELDS_INIT_KWARGS + } - @check_controls - def controlled_by(self, *qubits: int) -> "Gate": - """Controls the gate on (arbitrarily many) qubits. + encoded_simple["_class"] = type(self).__name__ - To see how this method affects the underlying matrix representation of a gate, - please see the documentation of :meth:`qibo.gates.Gate.matrix`. + return encoded_simple - .. note:: - Some gate classes default to another gate class depending on the number of controls - present. For instance, an :math:`1`-controlled :class:`qibo.gates.X` gate - will default to a :class:`qibo.gates.CNOT` gate, while a :math:`2`-controlled - :class:`qibo.gates.X` gate defaults to a :class:`qibo.gates.TOFFOLI` gate. - Other gates affected by this method are: :class:`qibo.gates.Y`, :class:`qibo.gates.Z`, - :class:`qibo.gates.RX`, :class:`qibo.gates.RY`, :class:`qibo.gates.RZ`, - :class:`qibo.gates.U1`, :class:`qibo.gates.U2`, and :class:`qibo.gates.U3`. + @property + def target_qubits(self) -> Tuple[int, ...]: + """Tuple with ids of target qubits.""" + return self._target_qubits - Args: - *qubits (int): Ids of the qubits that the gate will be controlled on. + @target_qubits.setter + def target_qubits(self, qubits: Sequence[int]) -> None: + """Sets target qubits tuple.""" + self._set_target_qubits(qubits) + self._check_control_target_overlap() - Returns: - :class:`qibo.gates.Gate`: object in with the corresponding - gate being controlled in the given qubits. + def to_json(self): + """Dump gate to JSON. + + Note: + Consider using :meth:`raw` directly. """ - if qubits: - self.is_controlled_by = True - self.control_qubits = qubits - return self + return json.dumps(self.raw) - def _base_decompose(self, *free, use_toffolis=True, **kwargs) -> List["Gate"]: + def _base_decompose( + self, *free, use_toffolis: bool = True, method: str = "standard", **kwargs + ): """Base decomposition for gates. Returns a list containing the gate itself. Should be overridden by @@ -419,22 +497,86 @@ def _base_decompose(self, *free, use_toffolis=True, **kwargs) -> List["Gate"]: use_toffolis: If ``True`` the decomposition contains only ``TOFFOLI`` gates. If ``False`` a congruent representation is used for ``TOFFOLI`` gates. See :class:`qibo.gates.TOFFOLI` for more details on this representation. - kwargs: Aditional parameters. + kwargs (dict, optional): Additional arguments. When ``method = "clifford_plus_t"``, + one can set ``epsilon`` (:math:`\\epsilon`) precision for the transpilation + of each gate into the Clifford + :class:`qibo.gates.gates.T` gate set. + This precision defaults to :math:`\\epsilon = 10^{-16}`. + Another possible keyword argument is ``mpmath_dps``, which defines the + number of decimal places used by the ``mpmath`` package. + ``mpmmath_dps`` defaults to :math:`256`. Returns: - list: Synthesis of the original gate in another gate set. + List[:class:`qibo.gates.abstract.Gate`]: Synthesis of the original + gate in another gate set. """ try: - from qibo.transpiler.decompositions import ( # pylint: disable=C0415 - standard_decompositions, - ) + if method == "clifford_plus_t": + from qibo.transpiler.decompositions import ( # pylint: disable=C0415 + clifford_plus_t, + ) + + mpmath_dps = kwargs.get("mpmath_dps", 256) + epsilon = kwargs.get("epsilon", 1e-16) + + func = clifford_plus_t + func._set_precision_cliff_plus_t(epsilon, mpmath_dps) + + else: + from qibo.transpiler.decompositions import ( # pylint: disable=C0415 + standard_decompositions, + ) - return standard_decompositions(self) + func = standard_decompositions + + return func(self) except KeyError: return [self.__class__(*self.init_args, **self.init_kwargs)] + def _check_control_target_overlap(self) -> None: + """Checks that there are no qubits that are both target and + controls.""" + control_and_target = self._control_qubits + self._target_qubits + common = len(set(control_and_target)) != len(control_and_target) + if common: + raise_error( + ValueError, + f"{set(self._target_qubits) & set(self._control_qubits)}" + + "qubits are both targets and controls " + + f"for gate {self.__class__.__name__}.", + ) + + def _control_mask_after_stripping(self, gates) -> List[bool]: + """Returns a mask indicating which gates should be controlled.""" + left = 0 + right = len(gates) - 1 + mask = [True] * len(gates) + while left < right: + g1, g2 = gates[left], gates[right] + if self._gates_cancel(g1, g2): + mask[left] = False + mask[right] = False + left += 1 + right -= 1 + return mask + + def _dagger(self): + """Helper method for :meth:`qibo.gates.Gate.dagger`.""" + # By default the ``_dagger`` method creates an equivalent gate, assuming + # that the gate is Hermitian (true for common gates like H or Paulis). + # If the gate is not Hermitian the ``_dagger`` method should be modified. + return self.__class__(*self.init_args, **self.init_kwargs) + + @staticmethod + def _find_repeated(qubits: Sequence[int]) -> int: + """Finds the first qubit id that is repeated in a sequence of qubit ids.""" + temp_set = set() + for qubit in qubits: + if qubit in temp_set: + return qubit + temp_set.add(qubit) + @staticmethod - def _gates_cancel(g1, g2): + def _gates_cancel(g1, g2) -> bool: """Determines if two gates cancel each other. Two gates are considered to cancel if: @@ -475,148 +617,54 @@ def _gates_cancel(g1, g2): return False - def _control_mask_after_stripping(self, gates: List["Gate"]) -> List[bool]: - """Returns a mask indicating which gates should be controlled.""" - left = 0 - right = len(gates) - 1 - mask = [True] * len(gates) - while left < right: - g1, g2 = gates[left], gates[right] - if self._gates_cancel(g1, g2): - mask[left] = False - mask[right] = False - left += 1 - right -= 1 - return mask - - def decompose(self, *free, use_toffolis: bool = True) -> List["Gate"]: - """Decomposes multi-control gates to gates supported by OpenQASM. - - Decompositions are based on `arXiv:9503016 `_. - If the gate is already controlled, it recursively decomposes the base gate and updates - the control qubits accordingly. - - Args: - free: Ids of free qubits to use for the gate decomposition. - use_toffolis(bool, optional): If ``True``, the decomposition contains only - :class:`qibo.gates.TOFFOLI` gates. If ``False``, a congruent - representation is used for :class:`qibo.gates.TOFFOLI` gates. - See :class:`qibo.gates.TOFFOLI` for more details on this representation. - - Returns: - list: gates that have the same effect as applying the original gate. - """ - if self.is_controlled_by: - # Step 1: Error check with all controls/targets - if set(free) & set(self.qubits): - raise_error( - ValueError, - "Cannot decompose multi-controlled ``X`` gate if free " - "qubits coincide with target or controls.", - ) - - ncontrols = len(self.control_qubits) - - # Step 2: Decompose base gate without controls - base_gate = self.__class__(*self.init_args, **self.init_kwargs) - decomposed = base_gate._base_decompose( - *free, use_toffolis=use_toffolis, ncontrols=ncontrols + def _set_control_qubits(self, qubits: Sequence[int]) -> None: + """Helper method for setting control qubits.""" + if len(set(qubits)) != len(qubits): + repeated = self._find_repeated(qubits) + raise_error( + ValueError, + f"Control qubit {repeated} was given twice for gate {self.__class__.__name__}.", ) - mask = self._control_mask_after_stripping(decomposed) - for bool_value, gate in zip(mask, decomposed): - if bool_value: - gate.is_controlled_by = True - gate.control_qubits += self.control_qubits - return decomposed - return self._base_decompose(*free, use_toffolis=use_toffolis) - - def matrix(self, backend=None): - """Returns the matrix representation of the gate. - - If gate has controlled qubits inserted by :meth:`qibo.gates.Gate.controlled_by`, - then :meth:`qibo.gates.Gate.matrix` returns the matrix of the original gate. - - .. code-block:: python - - from qibo import gates - - gate = gates.SWAP(3, 4).controlled_by(0, 1, 2) - print(gate.matrix()) - - To return the full matrix that takes the control qubits into account, - one should use :meth:`qibo.models.Circuit.unitary`, e.g. - - .. code-block:: python - - from qibo import Circuit, gates - - nqubits = 5 - circuit = Circuit(nqubits) - circuit.add(gates.SWAP(3, 4).controlled_by(0, 1, 2)) - print(circuit.unitary()) - - Args: - backend (:class:`qibo.backends.abstract.Backend`, optional): backend - to be used in the execution. If ``None``, it uses - the current backend. Defaults to ``None``. - - Returns: - ndarray: Matrix representation of gate. - """ - from qibo.backends import _check_backend # pylint: disable=C0415 - - backend = _check_backend(backend) - - return backend.matrix(self) - - def generator_eigenvalue(self): - """This function returns the eigenvalues of the gate's generator. - - Returns: - float: eigenvalue of the generator. - """ + self._control_qubits = qubits - raise_error( - NotImplementedError, - f"Generator eigenvalue is not implemented for {self.__class__.__name__}", - ) + def _set_target_qubits(self, qubits: Sequence[int]) -> None: + """Helper method for setting target qubits.""" + self._target_qubits = tuple(qubits) + if len(self._target_qubits) != len(set(qubits)): + repeated = self._find_repeated(qubits) + raise_error( + ValueError, + f"Target qubit {repeated} was given twice for gate {self.__class__.__name__}.", + ) - @abstractmethod - def generator(self, backend): - """This function returns the gate's generator. + def _set_targets_and_controls( + self, target_qubits: Sequence[int], control_qubits: Sequence[int] + ) -> None: + """Sets target and control qubits simultaneously. - Returns: - array: generator. + This is used for the reduced qubit updates in the distributed + circuits because using the individual setters may raise errors + due to temporary overlap of control and target qubits. """ - - def basis_rotation(self): - """Transformation required to rotate the basis for measuring the gate.""" - raise_error( - NotImplementedError, - f"Basis rotation is not implemented for {self.__class__.__name__}", - ) - - def apply(self, backend, state, nqubits: int): - return backend.apply_gate(self, state, nqubits) - - def apply_clifford(self, backend, state, nqubits): - return backend.apply_gate_clifford(self, state, nqubits) + self._set_target_qubits(target_qubits) + self._set_control_qubits(control_qubits) + self._check_control_target_overlap() class SpecialGate(Gate): """Abstract class for special gates.""" - def commutes(self, gate): + def commutes(self, gate: Gate) -> bool: return False - def on_qubits(self, qubit_map: dict): - raise_error(NotImplementedError, "Cannot use special gates on subroutines.") - def matrix(self, backend=None): # pragma: no cover raise_error( NotImplementedError, "Special gates do not have matrix representation." ) + def on_qubits(self, qubit_map: dict): + raise_error(NotImplementedError, "Cannot use special gates on subroutines.") + class ParametrizedGate(Gate): """Base class for parametrized gates. @@ -624,19 +672,38 @@ class ParametrizedGate(Gate): Implements the basic functionality of parameter setters and getters. """ - def __init__(self, trainable=True): + def __init__(self, trainable: bool = True): super().__init__() self.parameter_names = "theta" self.nparams = 1 self.trainable = trainable + @abstractmethod + def gradient(self, backend=None) -> Gate: + """Returns Unitary with gate's gradient. + + Only gates with a single parameter are currently supported. + """ + + def matrix(self, backend=None) -> ArrayLike: + from qibo.backends import _check_backend # pylint: disable=C0415 + + backend = _check_backend(backend) + + return backend.matrix_parametrized(self) + + def on_qubits(self, qubit_map: dict) -> Gate: + gate = super().on_qubits(qubit_map) + gate.parameters = self.parameters + return gate + @Gate.parameters.setter - def parameters(self, x): + def parameters(self, x: ArrayLike) -> None: """Updates the values of gate's parameters.""" if isinstance(self.parameter_names, str): nparams = 1 names = [self.parameter_names] - if not isinstance(x, collections.abc.Iterable): + if not isinstance(x, Iterable): x = [x] else: # Captures the ``Unitary`` gate case where the given parameter @@ -675,11 +742,6 @@ def parameters(self, x): for gate in self.device_gates: # pragma: no cover gate.parameters = x - def on_qubits(self, qubit_map: dict): - gate = super().on_qubits(qubit_map) - gate.parameters = self.parameters - return gate - def substitute_symbols(self): params = list(self._parameters) for i, param in self.symbolic_parameters.items(): @@ -687,17 +749,3 @@ def substitute_symbols(self): param = symbol.evaluate(param) params[i] = float(param) self.parameters = tuple(params) - - def matrix(self, backend=None): - from qibo.backends import _check_backend # pylint: disable=C0415 - - backend = _check_backend(backend) - - return backend.matrix_parametrized(self) - - @abstractmethod - def gradient(self, backend=None) -> Gate: - """Returns Unitary with gate's gradient. - - Only gates with a single parameter are currently supported. - """ diff --git a/src/qibo/gates/gates.py b/src/qibo/gates/gates.py index ae8142ebf0..68a83add5f 100644 --- a/src/qibo/gates/gates.py +++ b/src/qibo/gates/gates.py @@ -2,6 +2,7 @@ from typing import List, Tuple, Union import numpy as np +from numpy.typing import ArrayLike from qibo.backends import _check_backend from qibo.config import PRECISION_TOL, raise_error @@ -24,7 +25,7 @@ class H(Gate): q (int): the qubit id number. """ - def __init__(self, q): + def __init__(self, q: int): super().__init__() self.name = "h" self.draw_label = "H" @@ -33,11 +34,11 @@ def __init__(self, q): self.unitary = True @property - def clifford(self): + def clifford(self) -> bool: return True @property - def qasm_label(self): + def qasm_label(self) -> str: return "h" @@ -56,7 +57,7 @@ class X(Gate): q (int): the qubit id number. """ - def __init__(self, q): + def __init__(self, q: int): super().__init__() self.name = "x" self.draw_label = "X" @@ -65,15 +66,15 @@ def __init__(self, q): self.unitary = True @property - def clifford(self): + def clifford(self) -> bool: return True @property - def qasm_label(self): + def qasm_label(self) -> str: return "x" @Gate.check_controls - def controlled_by(self, *q): + def controlled_by(self, *q: int) -> Gate: """Fall back to CNOT and Toffoli if there is one or two controls.""" if len(q) == 1: gate = CNOT(q[0], self.target_qubits[0]) @@ -81,20 +82,41 @@ def controlled_by(self, *q): gate = TOFFOLI(q[0], q[1], self.target_qubits[0]) else: gate = super().controlled_by(*q) + return gate - def _base_decompose(self, *free, use_toffolis=True, **kwargs): + def _base_decompose( + self, *free: int, use_toffolis: bool = True, method: str = "standard", **kwargs + ) -> List[Gate]: """Decomposes multi-control ``X`` gate to one-qubit, ``CNOT`` and ``TOFFOLI`` gates. Args: - free: Ids of free qubits to use for the gate decomposition. + free (int): Ids of free qubits to use for the gate decomposition. use_toffolis: If ``True`` the decomposition contains only ``TOFFOLI`` gates. If ``False`` a congruent representation is used for ``TOFFOLI`` gates. See :class:`qibo.gates.TOFFOLI` for more details on this representation. + method (str, optional): Choice of gate set for the decomposition. + If ``"standard"``, decomposes circuit into :class:`qibo.gates.gates.CNOT`, + :class:`qibo.gates.gates.RX`, :class:`qibo.gates.gates.RY`, + :class:`qibo.gates.gates.RZ`, :class:`qibo.gates.gates.U1`, + :class:`qibo.gates.gates.U2`, :class:`qibo.gates.gates.U3`, + and Clifford gates. If ``"clifford_plus_t"``, decomposes the circuit + into :class:`qibo.gates.gates.CNOT`, :class:`qibo.gates.gates.H`, + :class:`qibo.gates.gates.S`, :class:`qibo.gates.gates.X`, + :class:`qibo.gates.gates.Y`, :class:`qibo.gates.gates.Z`, + and :class:`qibo.gates.gates.T`. Defaults to ``"standard"``. + kwargs (dict, optional): Additional arguments. When ``method = "clifford_plus_t"``, + one can set ``epsilon`` (:math:`\\epsilon`) precision for the transpilation + of each gate into the Clifford + :class:`qibo.gates.gates.T` gate set. + This precision defaults to :math:`\\epsilon = 10^{-16}`. + Another possible keyword argument is ``mpmath_dps``, which defines the + number of decimal places used by the ``mpmath`` package. + ``mpmmath_dps`` defaults to :math:`256`. Returns: - list: Set of one-qubit, :class:`qibo.gates.CNOT`, and :class:`qibo.gates.TOFFOLI` - gates that have the same effect as applying the original multi-control gate. + List[:class:`qibo.gates.abstract.Gate`]: Set of one-qubit, :class:`qibo.gates.CNOT`, + and :class:`qibo.gates.TOFFOLI` gates that have the same effect as applying + the original multi-control gate. """ if set(free) & set(self.qubits): raise_error( @@ -155,10 +177,14 @@ def _base_decompose(self, *free, use_toffolis=True, **kwargs): decomp_gates.extend(decomp_gates) return decomp_gates - def decompose(self, *free, use_toffolis: bool = True) -> List["Gate"]: - return self._base_decompose(*free, use_toffolis=use_toffolis) + def decompose( + self, *free: int, use_toffolis: bool = True, method: str = "standard", **kwargs + ) -> List[Gate]: + return self._base_decompose( + *free, use_toffolis=use_toffolis, method=method, **kwargs + ) - def basis_rotation(self): + def basis_rotation(self) -> Gate: return H(self.target_qubits[0]) @@ -177,7 +203,7 @@ class Y(Gate): q (int): the qubit id number. """ - def __init__(self, q): + def __init__(self, q: int): super().__init__() self.name = "y" self.draw_label = "Y" @@ -186,15 +212,15 @@ def __init__(self, q): self.unitary = True @property - def clifford(self): + def clifford(self) -> bool: return True @property - def qasm_label(self): + def qasm_label(self) -> str: return "y" @Gate.check_controls - def controlled_by(self, *q): + def controlled_by(self, *q: int) -> Gate: """Fall back to CY if there is only one control.""" if len(q) == 1: gate = CY(q[0], self.target_qubits[0]) @@ -202,7 +228,7 @@ def controlled_by(self, *q): gate = super().controlled_by(*q) return gate - def basis_rotation(self): + def basis_rotation(self) -> Gate: from qibo import matrices # pylint: disable=C0415 matrix = (matrices.Y + matrices.Z) / math.sqrt(2) @@ -226,7 +252,7 @@ class Z(Gate): q (int): the qubit id number. """ - def __init__(self, q): + def __init__(self, q: int): super().__init__() self.name = "z" self.draw_label = "Z" @@ -235,19 +261,19 @@ def __init__(self, q): self.unitary = True @property - def clifford(self): + def clifford(self) -> bool: return True @property - def hamming_weight(self): + def hamming_weight(self) -> bool: return True @property - def qasm_label(self): + def qasm_label(self) -> str: return "z" @Gate.check_controls - def controlled_by(self, *q): + def controlled_by(self, *q: int) -> Gate: """Fall back to CZ if there is only one control.""" if len(q) == 1: gate = CZ(q[0], self.target_qubits[0]) @@ -257,7 +283,7 @@ def controlled_by(self, *q): gate = super().controlled_by(*q) return gate - def basis_rotation(self): + def basis_rotation(self) -> None: return None @@ -276,7 +302,7 @@ class SX(Gate): q (int): the qubit id number. """ - def __init__(self, q): + def __init__(self, q: int): super().__init__() self.name = "sx" self.draw_label = "SX" @@ -285,14 +311,16 @@ def __init__(self, q): self.unitary = True @property - def clifford(self): + def clifford(self) -> bool: return True @property - def qasm_label(self): + def qasm_label(self) -> str: return "sx" - def decompose(self, *free, use_toffolis=True): + def decompose( + self, *free: int, use_toffolis: bool = True, method: str = "standard", **kwargs + ) -> List[Gate]: """Decomposition of :math:`\\sqrt{X}` up to global phase. A global phase difference exists between the definitions of @@ -300,9 +328,11 @@ def decompose(self, *free, use_toffolis=True): being the :class:`qibo.gates.RX` gate. More precisely, :math:`\\sqrt{X} = e^{i \\pi / 4} \\, \\text{RX}(\\pi / 2)`. """ - return super().decompose(*free, use_toffolis=use_toffolis) + return super().decompose( + *free, use_toffolis=use_toffolis, method=method, **kwargs + ) - def _dagger(self): + def _dagger(self) -> Gate: """""" return SXDG(self.init_args[0]) @@ -322,7 +352,7 @@ class SXDG(Gate): q (int): the qubit id number. """ - def __init__(self, q): + def __init__(self, q: int): super().__init__() self.name = "sxdg" self.draw_label = "SXDG" @@ -331,14 +361,14 @@ def __init__(self, q): self.unitary = True @property - def clifford(self): + def clifford(self) -> bool: return True @property - def qasm_label(self): + def qasm_label(self) -> str: return "sxdg" - def _dagger(self): + def _dagger(self) -> Gate: """""" return SX(self.init_args[0]) @@ -358,7 +388,7 @@ class S(Gate): q (int): the qubit id number. """ - def __init__(self, q): + def __init__(self, q: int): super().__init__() self.name = "s" self.draw_label = "S" @@ -367,18 +397,18 @@ def __init__(self, q): self.unitary = True @property - def clifford(self): + def clifford(self) -> bool: return True @property - def hamming_weight(self): + def hamming_weight(self) -> bool: return True @property - def qasm_label(self): + def qasm_label(self) -> str: return "s" - def _dagger(self): + def _dagger(self) -> Gate: return SDG(*self.init_args) @@ -397,7 +427,7 @@ class SDG(Gate): q (int): the qubit id number. """ - def __init__(self, q): + def __init__(self, q: int): super().__init__() self.name = "sdg" self.draw_label = "SDG" @@ -406,18 +436,18 @@ def __init__(self, q): self.unitary = True @property - def clifford(self): + def clifford(self) -> bool: return True @property - def hamming_weight(self): + def hamming_weight(self) -> bool: return True @property - def qasm_label(self): + def qasm_label(self) -> str: return "sdg" - def _dagger(self): + def _dagger(self) -> Gate: return S(*self.init_args) @@ -436,7 +466,7 @@ class T(Gate): q (int): the qubit id number. """ - def __init__(self, q): + def __init__(self, q: int): super().__init__() self.name = "t" self.draw_label = "T" @@ -445,14 +475,14 @@ def __init__(self, q): self.unitary = True @property - def hamming_weight(self): + def hamming_weight(self) -> bool: return True @property - def qasm_label(self): + def qasm_label(self) -> str: return "t" - def _dagger(self): + def _dagger(self) -> Gate: return TDG(*self.init_args) @@ -471,7 +501,7 @@ class TDG(Gate): q (int): the qubit id number. """ - def __init__(self, q): + def __init__(self, q: int): super().__init__() self.name = "tdg" self.draw_label = "TDG" @@ -480,14 +510,14 @@ def __init__(self, q): self.unitary = True @property - def hamming_weight(self): + def hamming_weight(self) -> bool: return True @property - def qasm_label(self): + def qasm_label(self) -> str: return "tdg" - def _dagger(self): + def _dagger(self) -> Gate: return T(*self.init_args) @@ -498,7 +528,7 @@ class I(Gate): *q (int): the qubit id numbers. """ - def __init__(self, *q): + def __init__(self, *q: int): super().__init__() self.name = "id" self.draw_label = "I" @@ -507,15 +537,15 @@ def __init__(self, *q): self.unitary = True @property - def clifford(self): + def clifford(self) -> bool: return True @property - def hamming_weight(self): + def hamming_weight(self) -> bool: return True @property - def qasm_label(self): + def qasm_label(self) -> str: return "id" @@ -527,11 +557,11 @@ class Align(ParametrizedGate): Args: q (int): The qubit ID. - delay (int, optional): The time (in ns) for which to delay circuit execution on the specified qubits. - Defaults to ``0`` (zero). + delay (int, optional): The time (in ns) for which to delay circuit execution + on the specified qubits. Defaults to :math:`0`. """ - def __init__(self, q, delay=0, trainable=False): + def __init__(self, q: int, delay: int = 0, trainable: bool = False): if not isinstance(delay, int): raise_error( TypeError, f"delay must be type int, but it is type {type(delay)}." @@ -560,7 +590,7 @@ class _Rn_(ParametrizedGate): Defaults to ``True``. """ - def __init__(self, q, theta, trainable=True): + def __init__(self, q: int, theta: float, trainable: bool = True): super().__init__(trainable) self.name = None self._controlled_gate = None @@ -576,17 +606,17 @@ def __init__(self, q, theta, trainable=True): self.init_kwargs = {"theta": theta, "trainable": trainable} @property - def clifford(self): + def clifford(self) -> bool: return _is_clifford_given_angle(self.parameters[0]) - def _dagger(self) -> "Gate": + def _dagger(self) -> Gate: """""" return self.__class__( self.target_qubits[0], -self.parameters[0] ) # pylint: disable=E1130 @Gate.check_controls - def controlled_by(self, *q): + def controlled_by(self, *q: int) -> Gate: """Fall back to CRn if there is only one control.""" if len(q) == 1: gate = self._controlled_gate( # pylint: disable=E1102 @@ -599,7 +629,7 @@ def controlled_by(self, *q): def generator_eigenvalue(self): return 0.5 - def gradient(self, backend=None) -> "Gate": + def gradient(self, backend=None) -> Gate: """Gradient of the Gate.""" backend = _check_backend(backend=backend) return Unitary( @@ -632,21 +662,21 @@ class RX(_Rn_): Defaults to ``True``. """ - def __init__(self, q, theta, trainable=True): + def __init__(self, q: int, theta: float, trainable: bool = True): super().__init__(q, theta, trainable) self.name = "rx" self.draw_label = "RX" self._controlled_gate = CRX @property - def hamming_weight(self): + def hamming_weight(self) -> bool: return _is_hamming_weight_given_angle(self.parameters[0]) @property - def qasm_label(self): + def qasm_label(self) -> str: return "rx" - def generator(self, backend=None): + def generator(self, backend=None) -> ArrayLike: backend = _check_backend(backend) return backend.matrices.X @@ -672,21 +702,21 @@ class RY(_Rn_): Defaults to ``True``. """ - def __init__(self, q, theta, trainable=True): + def __init__(self, q: int, theta: float, trainable: bool = True): super().__init__(q, theta, trainable) self.name = "ry" self.draw_label = "RY" self._controlled_gate = CRY @property - def hamming_weight(self): + def hamming_weight(self) -> bool: return _is_hamming_weight_given_angle(self.parameters[0]) @property - def qasm_label(self): + def qasm_label(self) -> str: return "ry" - def generator(self, backend=None): + def generator(self, backend=None) -> ArrayLike: backend = _check_backend(backend) return backend.matrices.Y @@ -710,21 +740,21 @@ class RZ(_Rn_): Defaults to ``True``. """ - def __init__(self, q, theta, trainable=True): + def __init__(self, q: int, theta: float, trainable: bool = True): super().__init__(q, theta, trainable) self.name = "rz" self.draw_label = "RZ" self._controlled_gate = CRZ @property - def hamming_weight(self): + def hamming_weight(self) -> bool: return True @property - def qasm_label(self): + def qasm_label(self) -> str: return "rz" - def generator(self, backend=None): + def generator(self, backend=None) -> ArrayLike: backend = _check_backend(backend) return backend.matrices.Z @@ -749,7 +779,7 @@ class PRX(ParametrizedGate): Defaults to ``True``. """ - def __init__(self, q, theta, phi, trainable=True): + def __init__(self, q: int, theta: float, phi: float, trainable=True): super().__init__(trainable) self.name = "prx" self.draw_label = "prx" @@ -770,14 +800,14 @@ def __init__(self, q, theta, phi, trainable=True): } @property - def hamming_weight(self): + def hamming_weight(self) -> bool: return _is_hamming_weight_given_angle(self.parameters[0]) @property - def qasm_label(self): + def qasm_label(self) -> str: return "prx" - def _dagger(self) -> "Gate": + def _dagger(self) -> Gate: theta = -self.theta phi = self.phi return self.__class__( @@ -804,7 +834,7 @@ class GPI(ParametrizedGate): Defaults to ``True``. """ - def __init__(self, q, phi, trainable=True): + def __init__(self, q: int, phi: float, trainable: bool = True): super().__init__(trainable) self.name = "gpi" self.draw_label = "GPI" @@ -819,7 +849,7 @@ def __init__(self, q, phi, trainable=True): self.init_kwargs = {"phi": phi, "trainable": trainable} @property - def qasm_label(self): + def qasm_label(self) -> Tuple[str, str]: return "gpi", "gate gpi(phi) q {u3(pi, phi - pi/2, pi/2 - phi) q;}" @@ -842,7 +872,7 @@ class GPI2(ParametrizedGate): Defaults to ``True``. """ - def __init__(self, q, phi, trainable=True): + def __init__(self, q: int, phi: float, trainable: bool = True): super().__init__(trainable) self.name = "gpi2" self.draw_label = "GPI2" @@ -857,14 +887,14 @@ def __init__(self, q, phi, trainable=True): self.init_kwargs = {"phi": phi, "trainable": trainable} @property - def qasm_label(self): + def qasm_label(self) -> Tuple[str, str]: return "gpi2", "gate gpi2(phi) q {u3(pi/2, phi - pi/2, pi/2 - phi) q;}" @property - def clifford(self): + def clifford(self) -> bool: return _is_clifford_given_angle(self.parameters[0]) - def _dagger(self) -> "Gate": + def _dagger(self) -> Gate: """""" return self.__class__(self.target_qubits[0], self.parameters[0] + math.pi) @@ -879,7 +909,7 @@ class _Un_(ParametrizedGate): Defaults to ``True``. """ - def __init__(self, q, trainable=True): + def __init__(self, q: int, trainable: bool = True): super().__init__(trainable) self.name = None self._controlled_gate = None @@ -891,7 +921,7 @@ def __init__(self, q, trainable=True): self.init_kwargs = {"trainable": trainable} @Gate.check_controls - def controlled_by(self, *q): + def controlled_by(self, *q: int) -> Gate: """Fall back to CUn if there is only one control.""" if len(q) == 1: gate = self._controlled_gate( # pylint: disable=E1102 @@ -921,7 +951,7 @@ class U1(_Un_): Defaults to ``True``. """ - def __init__(self, q, theta, trainable=True): + def __init__(self, q: int, theta: float, trainable: bool = True): super().__init__(q, trainable=trainable) self.name = "u1" self.draw_label = "U1" @@ -932,14 +962,14 @@ def __init__(self, q, theta, trainable=True): self.init_kwargs = {"theta": theta, "trainable": trainable} @property - def hamming_weight(self): + def hamming_weight(self) -> bool: return True @property - def qasm_label(self): + def qasm_label(self) -> str: return "u1" - def _dagger(self) -> "Gate": + def _dagger(self) -> Gate: theta = -self.parameters[0] return self.__class__(self.target_qubits[0], theta) # pylint: disable=E1130 @@ -965,7 +995,7 @@ class U2(_Un_): Defaults to ``True``. """ - def __init__(self, q, phi, lam, trainable=True): + def __init__(self, q: int, phi: float, lam: float, trainable: bool = True): super().__init__(q, trainable=trainable) self.name = "u2" self.draw_label = "U2" @@ -977,10 +1007,10 @@ def __init__(self, q, phi, lam, trainable=True): self.parameters = phi, lam @property - def qasm_label(self): + def qasm_label(self) -> str: return "u2" - def _dagger(self) -> "Gate": + def _dagger(self) -> Gate: """""" phi, lam = self.parameters phi, lam = math.pi - lam, -math.pi - phi @@ -1010,7 +1040,9 @@ class U3(_Un_): Defaults to ``True``. """ - def __init__(self, q, theta, phi, lam, trainable=True): + def __init__( + self, q: int, theta: float, phi: float, lam: float, trainable: bool = True + ): super().__init__(q, trainable=trainable) self.name = "u3" self.draw_label = "U3" @@ -1026,20 +1058,9 @@ def __init__(self, q, theta, phi, lam, trainable=True): self.parameter_names = ["theta", "phi", "lam"] self.parameters = theta, phi, lam - @property - def hamming_weight(self): - return _is_hamming_weight_given_angle(self.parameters[0]) - - @property - def qasm_label(self): - return "u3" - - def _dagger(self) -> "Gate": - """""" - theta, lam, phi = tuple(-x for x in self.parameters) # pylint: disable=E1130 - return self.__class__(self.target_qubits[0], theta, phi, lam) - - def decompose(self, *free, use_toffolis=True): + def decompose( + self, *free: int, use_toffolis: bool = True, method: str = "standard", **kwargs + ) -> List[Gate]: """Decomposition of :math:`U_{3}` up to global phase. A global phase difference exists between the definitions of @@ -1053,7 +1074,22 @@ def decompose(self, *free, use_toffolis=True): where :math:`\\text{RZ}` and :math:`\\sqrt{X}` are, respectively, :class:`qibo.gates.RZ` and :class`qibo.gates.SX`. """ - return super().decompose(*free, use_toffolis=use_toffolis) + return super().decompose( + *free, use_toffolis=use_toffolis, method=method, **kwargs + ) + + @property + def hamming_weight(self) -> bool: + return _is_hamming_weight_given_angle(self.parameters[0]) + + @property + def qasm_label(self) -> str: + return "u3" + + def _dagger(self) -> Gate: + """""" + theta, lam, phi = tuple(-x for x in self.parameters) # pylint: disable=E1130 + return self.__class__(self.target_qubits[0], theta, phi, lam) class U1q(_Un_): @@ -1070,8 +1106,8 @@ class U1q(_Un_): \\end{pmatrix} Note that - :math:`U_{1q}(\\theta, \\phi) = U_{3}(\\theta, \\phi - \\frac{\\pi}{2}, \\frac{\\pi}{2} - \\phi)`, - where :math:`U_{3}` is :class:`qibo.gates.U3`. + :math:`U_{1q}(\\theta, \\phi) = U_{3}(\\theta, \\phi - \\frac{\\pi}{2}, + \\frac{\\pi}{2} - \\phi)`, where :math:`U_{3}` is :class:`qibo.gates.U3`. Args: q (int): the qubit id number. @@ -1082,7 +1118,7 @@ class U1q(_Un_): Defaults to ``True``. """ - def __init__(self, q, theta, phi, trainable=True): + def __init__(self, q: int, theta: float, phi: float, trainable: bool = True): super().__init__(q, trainable=trainable) self.name = "u1q" self.draw_label = "U1q" @@ -1093,10 +1129,10 @@ def __init__(self, q, theta, phi, trainable=True): self.parameters = theta, phi @property - def hamming_weight(self): + def hamming_weight(self) -> bool: return _is_hamming_weight_given_angle(self.parameters[0]) - def _dagger(self) -> "Gate": + def _dagger(self) -> Gate: """""" theta, phi = self.init_kwargs["theta"], self.init_kwargs["phi"] return self.__class__(self.init_args[0], -theta, phi) @@ -1120,7 +1156,7 @@ class CNOT(Gate): q1 (int): the target qubit id number. """ - def __init__(self, q0, q1): + def __init__(self, q0: int, q1: int): super().__init__() self.name = "cx" self.draw_label = "X" @@ -1130,11 +1166,11 @@ def __init__(self, q0, q1): self.unitary = True @property - def clifford(self): + def clifford(self) -> bool: return True @property - def qasm_label(self): + def qasm_label(self) -> str: return "cx" @@ -1156,7 +1192,7 @@ class CY(Gate): q1 (int): the target qubit id number. """ - def __init__(self, q0, q1): + def __init__(self, q0: int, q1: int): super().__init__() self.name = "cy" self.draw_label = "Y" @@ -1166,11 +1202,11 @@ def __init__(self, q0, q1): self.unitary = True @property - def clifford(self): + def clifford(self) -> bool: return True @property - def qasm_label(self): + def qasm_label(self) -> str: return "cy" @@ -1192,7 +1228,7 @@ class CZ(Gate): q1 (int): the target qubit id number. """ - def __init__(self, q0, q1): + def __init__(self, q0: int, q1: int): super().__init__() self.name = "cz" self.draw_label = "Z" @@ -1202,15 +1238,15 @@ def __init__(self, q0, q1): self.unitary = True @property - def clifford(self): + def clifford(self) -> bool: return True @property - def hamming_weight(self): + def hamming_weight(self) -> bool: return True @property - def qasm_label(self): + def qasm_label(self) -> str: return "cz" @@ -1232,7 +1268,7 @@ class CSX(Gate): q1 (int): the target qubit id number. """ - def __init__(self, q0, q1): + def __init__(self, q0: int, q1: int): super().__init__() self.name = "csx" self.draw_label = "CSX" @@ -1242,10 +1278,10 @@ def __init__(self, q0, q1): self.unitary = True @property - def qasm_label(self): + def qasm_label(self) -> str: return "csx" - def _dagger(self): + def _dagger(self) -> Gate: """""" return CSXDG(*self.init_args) @@ -1268,7 +1304,7 @@ class CSXDG(Gate): q1 (int): the target qubit id number. """ - def __init__(self, q0, q1): + def __init__(self, q0: int, q1: int): super().__init__() self.name = "csxdg" self.draw_label = "CSXDG" @@ -1278,10 +1314,10 @@ def __init__(self, q0, q1): self.unitary = True @property - def qasm_label(self): + def qasm_label(self) -> str: return "csxdg" - def _dagger(self): + def _dagger(self) -> Gate: """""" return CSX(*self.init_args) @@ -1298,7 +1334,7 @@ class _CRn_(ParametrizedGate): Defaults to ``True``. """ - def __init__(self, q0, q1, theta, trainable=True): + def __init__(self, q0: int, q1: int, theta: float, trainable: bool = True): super().__init__(trainable) self.name = None self.control_qubits = (q0,) @@ -1310,10 +1346,10 @@ def __init__(self, q0, q1, theta, trainable=True): self.init_kwargs = {"theta": theta, "trainable": trainable} @property - def clifford(self): + def clifford(self) -> bool: return _is_clifford_given_angle(self.parameters[0]) - def _dagger(self) -> "Gate": + def _dagger(self) -> Gate: """""" q0 = self.control_qubits[0] q1 = self.target_qubits[0] @@ -1343,17 +1379,17 @@ class CRX(_CRn_): Defaults to ``True``. """ - def __init__(self, q0, q1, theta, trainable=True): + def __init__(self, q0: int, q1: int, theta: float, trainable: bool = True): super().__init__(q0, q1, theta, trainable) self.name = "crx" self.draw_label = "RX" @property - def hamming_weight(self): + def hamming_weight(self) -> bool: return _is_hamming_weight_given_angle(self.parameters[0]) @property - def qasm_label(self): + def qasm_label(self) -> str: return "crx" @@ -1381,17 +1417,17 @@ class CRY(_CRn_): Defaults to ``True``. """ - def __init__(self, q0, q1, theta, trainable=True): + def __init__(self, q0: int, q1: int, theta: int, trainable: bool = True): super().__init__(q0, q1, theta, trainable) self.name = "cry" self.draw_label = "RY" @property - def hamming_weight(self): + def hamming_weight(self) -> bool: return _is_hamming_weight_given_angle(self.parameters[0]) @property - def qasm_label(self): + def qasm_label(self) -> str: return "cry" @@ -1417,17 +1453,17 @@ class CRZ(_CRn_): Defaults to ``True``. """ - def __init__(self, q0, q1, theta, trainable=True): + def __init__(self, q0: int, q1: int, theta: float, trainable: bool = True): super().__init__(q0, q1, theta, trainable) self.name = "crz" self.draw_label = "RZ" @property - def hamming_weight(self): + def hamming_weight(self) -> bool: return True @property - def qasm_label(self): + def qasm_label(self) -> str: return "crz" @@ -1442,7 +1478,7 @@ class _CUn_(ParametrizedGate): Defaults to ``True``. """ - def __init__(self, q0, q1, trainable=True): + def __init__(self, q0: int, q1: int, trainable: bool = True): super().__init__(trainable) self.name = None self.nparams = 0 @@ -1477,7 +1513,7 @@ class CU1(_CUn_): Defaults to ``True``. """ - def __init__(self, q0, q1, theta, trainable=True): + def __init__(self, q0: int, q1: int, theta: float, trainable: bool = True): super().__init__(q0, q1, trainable=trainable) self.name = "cu1" self.draw_label = "U1" @@ -1486,14 +1522,14 @@ def __init__(self, q0, q1, theta, trainable=True): self.init_kwargs = {"theta": theta, "trainable": trainable} @property - def hamming_weight(self): + def hamming_weight(self) -> bool: return True @property - def qasm_label(self): + def qasm_label(self) -> str: return "cu1" - def _dagger(self) -> "Gate": + def _dagger(self) -> Gate: """""" q0 = self.control_qubits[0] q1 = self.target_qubits[0] @@ -1525,7 +1561,9 @@ class CU2(_CUn_): Defaults to ``True``. """ - def __init__(self, q0, q1, phi, lam, trainable=True): + def __init__( + self, q0: int, q1: int, phi: float, lam: float, trainable: bool = True + ): super().__init__(q0, q1, trainable=trainable) self.name = "cu2" self.draw_label = "U2" @@ -1535,7 +1573,7 @@ def __init__(self, q0, q1, phi, lam, trainable=True): self.parameter_names = ["phi", "lam"] self.parameters = phi, lam - def _dagger(self) -> "Gate": + def _dagger(self) -> Gate: """""" q0 = self.control_qubits[0] q1 = self.target_qubits[0] @@ -1570,7 +1608,15 @@ class CU3(_CUn_): Defaults to ``True``. """ - def __init__(self, q0, q1, theta, phi, lam, trainable=True): + def __init__( + self, + q0: int, + q1: int, + theta: float, + phi: float, + lam: float, + trainable: bool = True, + ): super().__init__(q0, q1, trainable=trainable) self.name = "cu3" self.draw_label = "U3" @@ -1586,14 +1632,14 @@ def __init__(self, q0, q1, theta, phi, lam, trainable=True): self.parameters = theta, phi, lam @property - def hamming_weight(self): + def hamming_weight(self) -> bool: return _is_hamming_weight_given_angle(self.parameters[0]) @property - def qasm_label(self): + def qasm_label(self) -> str: return "cu3" - def _dagger(self) -> "Gate": + def _dagger(self) -> Gate: """""" q0 = self.control_qubits[0] q1 = self.target_qubits[0] @@ -1619,7 +1665,7 @@ class SWAP(Gate): q1 (int): the second qubit to be swapped id number. """ - def __init__(self, q0, q1): + def __init__(self, q0: int, q1: int): super().__init__() self.name = "swap" self.draw_label = "x" @@ -1628,15 +1674,15 @@ def __init__(self, q0, q1): self.unitary = True @property - def clifford(self): + def clifford(self) -> bool: return True @property - def hamming_weight(self): + def hamming_weight(self) -> bool: return True @property - def qasm_label(self): + def qasm_label(self) -> str: return "swap" @@ -1658,7 +1704,7 @@ class iSWAP(Gate): q1 (int): the second qubit to be swapped id number. """ - def __init__(self, q0, q1): + def __init__(self, q0: int, q1: int): super().__init__() self.name = "iswap" self.draw_label = "i" @@ -1667,15 +1713,15 @@ def __init__(self, q0, q1): self.unitary = True @property - def clifford(self): + def clifford(self) -> bool: return True @property - def hamming_weight(self): + def hamming_weight(self) -> bool: return True @property - def qasm_label(self): + def qasm_label(self) -> str: return "iswap" @@ -1697,7 +1743,7 @@ class SiSWAP(Gate): q1 (int): the second qubit to be swapped id number. """ - def __init__(self, q0, q1): + def __init__(self, q0: int, q1: int): super().__init__() self.name = "siswap" self.draw_label = "si" @@ -1706,10 +1752,10 @@ def __init__(self, q0, q1): self.unitary = True @property - def hamming_weight(self): + def hamming_weight(self) -> bool: return True - def _dagger(self) -> "Gate": + def _dagger(self) -> Gate: return SiSWAPDG(*self.qubits) @@ -1731,7 +1777,7 @@ class SiSWAPDG(Gate): q1 (int): the second qubit to be swapped id number. """ - def __init__(self, q0, q1): + def __init__(self, q0: int, q1: int): super().__init__() self.name = "siswapdg" self.draw_label = "sidg" @@ -1740,10 +1786,10 @@ def __init__(self, q0, q1): self.unitary = True @property - def hamming_weight(self): + def hamming_weight(self) -> bool: return True - def _dagger(self) -> "Gate": + def _dagger(self) -> Gate: return SiSWAP(*self.qubits) @@ -1765,7 +1811,7 @@ class FSWAP(Gate): q1 (int): the second qubit to be f-swapped id number. """ - def __init__(self, q0, q1): + def __init__(self, q0: int, q1: int): super().__init__() self.name = "fswap" self.draw_label = "fx" @@ -1774,15 +1820,15 @@ def __init__(self, q0, q1): self.unitary = True @property - def clifford(self): + def clifford(self) -> bool: return True @property - def hamming_weight(self): + def hamming_weight(self) -> bool: return True @property - def qasm_label(self): + def qasm_label(self) -> str: return "fswap" @@ -1812,7 +1858,9 @@ class fSim(ParametrizedGate): # TODO: Check how this works with QASM. - def __init__(self, q0, q1, theta, phi, trainable=True): + def __init__( + self, q0: int, q1: int, theta: float, phi: float, trainable: bool = True + ): super().__init__(trainable) self.name = "fsim" self.draw_label = "f" @@ -1827,10 +1875,10 @@ def __init__(self, q0, q1, theta, phi, trainable=True): self.init_kwargs = {"theta": theta, "phi": phi, "trainable": trainable} @property - def hamming_weight(self): + def hamming_weight(self) -> bool: return True - def _dagger(self) -> "Gate": + def _dagger(self) -> Gate: """""" q0, q1 = self.target_qubits params = (-x for x in self.parameters) # pylint: disable=E1130 @@ -1859,7 +1907,7 @@ class SYC(Gate): q1 (int): the second qubit to be swapped id number. """ - def __init__(self, q0, q1): + def __init__(self, q0: int, q1: int): super().__init__() self.name = "syc" self.draw_label = "SYC" @@ -1868,10 +1916,10 @@ def __init__(self, q0, q1): self.unitary = True @property - def hamming_weight(self): + def hamming_weight(self) -> bool: return True - def _dagger(self) -> "Gate": + def _dagger(self) -> Gate: """""" return fSim(*self.target_qubits, -np.pi / 2, -np.pi / 6) @@ -1899,7 +1947,9 @@ class GeneralizedfSim(ParametrizedGate): Defaults to ``True``. """ - def __init__(self, q0, q1, unitary, phi, trainable=True): + def __init__( + self, q0: int, q1: int, unitary: ArrayLike, phi: float, trainable: bool = True + ): super().__init__(trainable) self.name = "generalizedfsim" self.draw_label = "gf" @@ -1914,10 +1964,10 @@ def __init__(self, q0, q1, unitary, phi, trainable=True): self.init_kwargs = {"unitary": unitary, "phi": phi, "trainable": trainable} @property - def hamming_weight(self): + def hamming_weight(self) -> bool: return True - def _dagger(self): + def _dagger(self) -> Gate: q0, q1 = self.target_qubits u, phi = self.parameters init_kwargs = dict(self.init_kwargs) @@ -1926,7 +1976,7 @@ def _dagger(self): return self.__class__(q0, q1, **init_kwargs) @Gate.parameters.setter - def parameters(self, x): + def parameters(self, x: ArrayLike): shape = tuple(x[0].shape) if shape != (2, 2): raise_error( @@ -1948,7 +1998,7 @@ class _Rnn_(ParametrizedGate): Defaults to ``True``. """ - def __init__(self, q0, q1, theta, trainable=True): + def __init__(self, q0: int, q1: int, theta: float, trainable: bool = True): super().__init__(trainable) self.name = None self._controlled_gate = None @@ -1959,7 +2009,7 @@ def __init__(self, q0, q1, theta, trainable=True): self.init_args = [q0, q1] self.init_kwargs = {"theta": theta, "trainable": trainable} - def _dagger(self) -> "Gate": + def _dagger(self) -> Gate: """""" q0, q1 = self.target_qubits return self.__class__(q0, q1, -self.parameters[0]) # pylint: disable=E1130 @@ -1987,17 +2037,17 @@ class RXX(_Rnn_): Defaults to ``True``. """ - def __init__(self, q0, q1, theta, trainable=True): + def __init__(self, q0: int, q1: int, theta: float, trainable: bool = True): super().__init__(q0, q1, theta, trainable) self.name = "rxx" self.draw_label = "RXX" @property - def hamming_weight(self): + def hamming_weight(self) -> bool: return _is_hamming_weight_given_angle(self.parameters[0]) @property - def qasm_label(self): + def qasm_label(self) -> str: return "rxx" @@ -2022,17 +2072,17 @@ class RYY(_Rnn_): Defaults to ``True``. """ - def __init__(self, q0, q1, theta, trainable=True): + def __init__(self, q0: int, q1: int, theta: float, trainable: bool = True): super().__init__(q0, q1, theta, trainable) self.name = "ryy" self.draw_label = "RYY" @property - def hamming_weight(self): + def hamming_weight(self) -> bool: return _is_hamming_weight_given_angle(self.parameters[0]) @property - def qasm_label(self): + def qasm_label(self) -> str: return "ryy" @@ -2058,17 +2108,17 @@ class RZZ(_Rnn_): Defaults to ``True``. """ - def __init__(self, q0, q1, theta, trainable=True): + def __init__(self, q0: int, q1: int, theta: float, trainable: bool = True): super().__init__(q0, q1, theta, trainable) self.name = "rzz" self.draw_label = "RZZ" @property - def hamming_weight(self): + def hamming_weight(self) -> bool: return True @property - def qasm_label(self): + def qasm_label(self) -> str: return "rzz" @@ -2100,13 +2150,13 @@ class RZX(_Rnn_): Defaults to ``True``. """ - def __init__(self, q0, q1, theta, trainable=True): + def __init__(self, q0: int, q1: int, theta: float, trainable: bool = True): super().__init__(q0, q1, theta, trainable) self.name = "rzx" self.draw_label = "RZX" @property - def hamming_weight(self): + def hamming_weight(self) -> bool: return _is_hamming_weight_given_angle(self.parameters[0]) @@ -2134,23 +2184,27 @@ class RXXYY(_Rnn_): Defaults to ``True``. """ - def __init__(self, q0, q1, theta, trainable=True): + def __init__(self, q0: int, q1: int, theta: float, trainable: bool = True): super().__init__(q0, q1, theta, trainable) self.name = "rxxyy" self.draw_label = "RXXYY" @property - def hamming_weight(self): + def hamming_weight(self) -> bool: return True - def decompose(self, *free, use_toffolis=True): + def decompose( + self, *free, use_toffolis=True, method: str = "standard", **kwargs + ) -> List[Gate]: """Decomposition of :math:`\\text{R_{XX-YY}}` up to global phase. This decomposition has a global phase difference with respect to the original gate due to a phase difference in :math:`\\left(\\sqrt{X}\\right)^{\\dagger}`. """ - return super().decompose(*free, use_toffolis=use_toffolis) + return super().decompose( + *free, use_toffolis=use_toffolis, method=method, **kwargs + ) class MS(ParametrizedGate): @@ -2182,7 +2236,15 @@ class MS(ParametrizedGate): # TODO: Check how this works with QASM. - def __init__(self, q0, q1, phi0, phi1, theta: float = math.pi / 2, trainable=True): + def __init__( + self, + q0: int, + q1: int, + phi0: float, + phi1: float, + theta: float = math.pi / 2, + trainable: bool = True, + ): super().__init__(trainable) self.name = "ms" self.draw_label = "MS" @@ -2208,14 +2270,14 @@ def __init__(self, q0, q1, phi0, phi1, theta: float = math.pi / 2, trainable=Tru } @property - def hamming_weight(self): + def hamming_weight(self) -> bool: return _is_hamming_weight_given_angle(self.parameters[2]) @property - def qasm_label(self): + def qasm_label(self) -> str: return "ms" - def _dagger(self) -> "Gate": + def _dagger(self) -> Gate: """""" q0, q1 = self.target_qubits phi0, phi1, theta = self.parameters @@ -2244,7 +2306,7 @@ class GIVENS(ParametrizedGate): Defaults to ``True``. """ - def __init__(self, q0, q1, theta, trainable=True): + def __init__(self, q0: int, q1: int, theta: float, trainable: bool = True): super().__init__(trainable) self.name = "g" self.draw_label = "G" @@ -2259,14 +2321,16 @@ def __init__(self, q0, q1, theta, trainable=True): self.init_kwargs = {"theta": theta, "trainable": trainable} @property - def hamming_weight(self): + def hamming_weight(self) -> bool: return True - def _dagger(self) -> "Gate": + def _dagger(self) -> Gate: """""" return self.__class__(*self.target_qubits, -self.parameters[0]) - def decompose(self, *free, use_toffolis=True): + def decompose( + self, *free: int, use_toffolis: bool = True, method: str = "standard", **kwargs + ) -> List[Gate]: """Decomposition of GIVENS gate according to the decomposition of the RBS gate in Ref. [1]. @@ -2276,7 +2340,9 @@ def decompose(self, *free, use_toffolis=True): (2025) `_. """ - return super().decompose(*free, use_toffolis=use_toffolis) + return super().decompose( + *free, use_toffolis=use_toffolis, method=method, **kwargs + ) class RBS(ParametrizedGate): @@ -2305,7 +2371,7 @@ class RBS(ParametrizedGate): Defaults to ``True``. """ - def __init__(self, q0, q1, theta, trainable=True): + def __init__(self, q0: int, q1: int, theta: float, trainable: bool = True): super().__init__(trainable) self.name = "rbs" self.draw_label = "RBS" @@ -2320,16 +2386,41 @@ def __init__(self, q0, q1, theta, trainable=True): self.init_kwargs = {"theta": theta, "trainable": trainable} @property - def hamming_weight(self): + def hamming_weight(self) -> bool: return True - def _dagger(self) -> "Gate": + def _dagger(self) -> Gate: """""" return self.__class__(*self.target_qubits, -self.parameters[0]) - def _base_decompose(self, *free, use_toffolis: bool = True, **kwargs) -> List[Gate]: + def _base_decompose( + self, *free: int, use_toffolis: bool = True, method: str = "standard", **kwargs + ) -> List[Gate]: """Decomposition of RBS gate as in Ref. [1]. + Args: + free (int): Ids of free qubits to use for the gate decomposition. + use_toffolis: If ``True`` the decomposition contains only ``TOFFOLI`` gates. + If ``False`` a congruent representation is used for ``TOFFOLI`` gates. + See :class:`qibo.gates.TOFFOLI` for more details on this representation. + method (str, optional): Choice of gate set for the decomposition. + If ``"standard"``, decomposes circuit into :class:`qibo.gates.gates.CNOT`, + :class:`qibo.gates.gates.RX`, :class:`qibo.gates.gates.RY`, + :class:`qibo.gates.gates.RZ`, :class:`qibo.gates.gates.U1`, + :class:`qibo.gates.gates.U2`, :class:`qibo.gates.gates.U3`, + and Clifford gates. If ``"clifford_plus_t"``, decomposes the circuit + into :class:`qibo.gates.gates.CNOT`, :class:`qibo.gates.gates.H`, + :class:`qibo.gates.gates.S`, :class:`qibo.gates.gates.X`, + :class:`qibo.gates.gates.Y`, :class:`qibo.gates.gates.Z`, + and :class:`qibo.gates.gates.T`. Defaults to ``"standard"``. + kwargs (dict, optional): Additional arguments. When ``method = "clifford_plus_t"``, + one can set ``epsilon`` (:math:`\\epsilon`) precision for the transpilation + of each gate into the Clifford + :class:`qibo.gates.gates.T` gate set. + This precision defaults to :math:`\\epsilon = 10^{-16}`. + Another possible keyword argument is ``mpmath_dps``, which defines the + number of decimal places used by the ``mpmath`` package. + ``mpmmath_dps`` defaults to :math:`256`. + References: 1. R. M. S. Farias, T. O. Maciel, G. Camilo, R. Lin, S. Ramos-Calderer, and L. Aolita, *Quantum encoder for fixed-Hamming-weight subspaces*, `Phys. Rev. Applied 23, 044014 @@ -2376,7 +2467,7 @@ class ECR(Gate): q1 (int): the second qubit id number. """ - def __init__(self, q0, q1): + def __init__(self, q0: int, q1: int): super().__init__() self.name = "ecr" self.draw_label = "ECR" @@ -2385,10 +2476,12 @@ def __init__(self, q0, q1): self.unitary = True @property - def clifford(self): + def clifford(self) -> bool: return True - def decompose(self, *free, use_toffolis=True): + def decompose( + self, *free: int, use_toffolis: bool = True, method: str = "standard", **kwargs + ) -> List[Gate]: """Decomposition of :math:`\\textup{ECR}` gate up to global phase. A global phase difference exists between the definitions of @@ -2398,7 +2491,9 @@ def decompose(self, *free, use_toffolis=True): \\textup{ECR} = e^{i 7 \\pi / 4} \\, S(q_{0}) \\, \\sqrt{X}(q_{1}) \\, \\textup{CNOT}(q_{0}, q_{1}) \\, X(q_{0}) \\, . """ - return super().decompose(*free, use_toffolis=use_toffolis) + return super().decompose( + *free, use_toffolis=use_toffolis, method=method, **kwargs + ) class TOFFOLI(Gate): @@ -2424,7 +2519,7 @@ class TOFFOLI(Gate): q2 (int): the target qubit id number. """ - def __init__(self, q0, q1, q2): + def __init__(self, q0: int, q1: int, q2: int): super().__init__() self.name = "ccx" self.draw_label = "X" @@ -2434,7 +2529,7 @@ def __init__(self, q0, q1, q2): self.unitary = True @property - def qasm_label(self): + def qasm_label(self) -> str: return "ccx" def congruent(self, use_toffolis: bool = True) -> List[Gate]: @@ -2491,7 +2586,7 @@ class CCZ(Gate): q2 (int): the target qubit id number. """ - def __init__(self, q0, q1, q2): + def __init__(self, q0: int, q1: int, q2: int): super().__init__() self.name = "ccz" self.draw_label = "Z" @@ -2501,11 +2596,11 @@ def __init__(self, q0, q1, q2): self.unitary = True @property - def hamming_weight(self): + def hamming_weight(self) -> bool: return True @property - def qasm_label(self): + def qasm_label(self) -> str: return "ccz" @@ -2532,7 +2627,7 @@ class DEUTSCH(ParametrizedGate): q2 (int): the target qubit id number. """ - def __init__(self, q0, q1, q2, theta, trainable=True): + def __init__(self, q0: int, q1: int, q2: int, theta: float, trainable: bool = True): super().__init__(trainable) self.name = "deutsch" self.draw_label = "DE" @@ -2548,7 +2643,7 @@ def __init__(self, q0, q1, q2, theta, trainable=True): self.init_kwargs = {"theta": theta, "trainable": trainable} @property - def hamming_weight(self): + def hamming_weight(self) -> bool: return _is_hamming_weight_given_angle(self.parameters[0], np.pi) @@ -2565,7 +2660,7 @@ class FanOut(Gate): The first id is considered to be the control qubit. """ - def __init__(self, *q): + def __init__(self, *q: int): if len(q) < 2: raise_error( ValueError, "``FanOut`` gate must be applied to at least two qubits." @@ -2580,7 +2675,7 @@ def __init__(self, *q): self.unitary = True @property - def clifford(self): + def clifford(self) -> bool: return True @@ -2644,10 +2739,10 @@ def __init__( self.init_kwargs = {"theta": theta, "phi": phi, "trainable": trainable} @property - def hamming_weight(self): + def hamming_weight(self) -> bool: return len(self.init_args[0]) == len(self.init_args[1]) - def on_qubits(self, qubit_map: dict): + def on_qubits(self, qubit_map: dict) -> Gate: qubits_in = tuple(qubit_map.get(q) for q in self.init_args[0]) qubits_out = tuple(qubit_map.get(q) for q in self.init_args[1]) gate = self.__class__(qubits_in, qubits_out, **self.init_kwargs) @@ -2676,9 +2771,9 @@ class Unitary(ParametrizedGate): def __init__( self, - unitary, - *q, - trainable=True, + unitary: ArrayLike, + *q: int, + trainable: bool = True, name: str = None, check_unitary: bool = True, ): @@ -2716,7 +2811,7 @@ def __init__( del diagonals, off_diagonals, product @Gate.parameters.setter - def parameters(self, x): + def parameters(self, x: ArrayLike) -> None: shape = self.parameters[0].shape engine = _check_engine(x) # Reshape doesn't accept a tuple if engine is pytorch. @@ -2727,22 +2822,22 @@ def parameters(self, x): gate.parameters = x @property - def clifford(self): + def clifford(self) -> bool: return self._clifford @clifford.setter - def clifford(self, value): + def clifford(self, value) -> None: self._clifford = value @property - def hamming_weight(self): + def hamming_weight(self) -> bool: return self._hamming_weight @hamming_weight.setter - def hamming_weight(self, value): + def hamming_weight(self, value) -> None: self._hamming_weight = value - def on_qubits(self, qubit_map: dict): + def on_qubits(self, qubit_map: dict) -> Gate: args = [self.init_args[0]] args.extend(qubit_map.get(qubit) for qubit in self.target_qubits) gate = self.__class__(*args, **self.init_kwargs) @@ -2752,13 +2847,13 @@ def on_qubits(self, qubit_map: dict): gate.parameters = self.parameters return gate - def _dagger(self): + def _dagger(self) -> Gate: engine = _check_engine(self.parameters[0]) ud = engine.conj(self.parameters[0].T) return self.__class__(ud, *self.target_qubits, **self.init_kwargs) -def _check_engine(array): +def _check_engine(array: ArrayLike): """Check if the array is a numpy or torch tensor and return the corresponding library.""" if (array.__class__.__name__ == "Tensor") or ( isinstance(array, tuple) and array[0].__class__.__name__ == "Tensor" @@ -2770,13 +2865,13 @@ def _check_engine(array): return np -def _is_clifford_given_angle(angle): +def _is_clifford_given_angle(angle: Union[float, int]): """Helper function to update Clifford boolean condition according to the given angle ``angle``.""" return isinstance(angle, (float, int)) and (angle % (np.pi / 2)).is_integer() -def _is_hamming_weight_given_angle(angle, target=2 * np.pi): +def _is_hamming_weight_given_angle(angle: Union[float, int], target: float = 2 * np.pi): """Helper function to update Hamming weight boolean condition according to the given angles ``angle`` and ``target``.""" return isinstance(angle, (float, int)) and (angle % target).is_integer() diff --git a/src/qibo/models/circuit.py b/src/qibo/models/circuit.py index 794f4e03c8..986ba9e045 100644 --- a/src/qibo/models/circuit.py +++ b/src/qibo/models/circuit.py @@ -503,21 +503,32 @@ def _check_noise_map(self, noise_map: NoiseMapType) -> NoiseMapType: return {q: noise_map for q in range(self.nqubits)} - def decompose(self, *free: int): + def decompose(self, *free: int, method: str = "standard", **kwargs): """Decomposes circuit's gates to gates supported by OpenQASM. Args: - free: Ids of free (work) qubits to use for gate decomposition. + free (int): Ids of free (work) qubits to use for gate decomposition. + method (str, optional): Choice of gate set for the decomposition. + If ``"standard"``, decomposes circuit into :class:`qibo.gates.gates.CNOT`, + :class:`qibo.gates.gates.RX`, :class:`qibo.gates.gates.RY`, + :class:`qibo.gates.gates.RZ`, :class:`qibo.gates.gates.U1`, + :class:`qibo.gates.gates.U2`, :class:`qibo.gates.gates.U3`, + and Clifford gates. If ``"clifford_plus_t"``, decomposes the circuit + into :class:`qibo.gates.gates.CNOT`, :class:`qibo.gates.gates.H`, + :class:`qibo.gates.gates.S`, :class:`qibo.gates.gates.X`, + :class:`qibo.gates.gates.Y`, :class:`qibo.gates.gates.Z`, + and :class:`qibo.gates.gates.T`. Defaults to ``"standard"``. Returns: - Circuit that contains only gates that are supported by OpenQASM - and has the same effect as the original circuit. + :class:`qibo.models.circuit.Circuit`: Circuit that contains only + gates that are supported by OpenQASM and has the same effect as + the original circuit. """ # FIXME: This method is not completed until the ``decompose`` is # implemented for all gates not supported by OpenQASM. decomp_circuit = self.__class__(self.nqubits) for gate in self.queue: - decomp_circuit.add(gate.decompose(*free)) + decomp_circuit.add(gate.decompose(*free, method=method, **kwargs)) return decomp_circuit def with_pauli_noise(self, noise_map: NoiseMapType): diff --git a/src/qibo/transpiler/decompositions.py b/src/qibo/transpiler/decompositions.py index 7364c190ad..a8c6fca612 100644 --- a/src/qibo/transpiler/decompositions.py +++ b/src/qibo/transpiler/decompositions.py @@ -1,4 +1,5 @@ -import numpy as np +import cmath +import math from qibo import gates from qibo.transpiler.unitary_decompositions import ( @@ -52,6 +53,38 @@ def __call__(self, gate, backend=None): decomposition = self._check_instance(gate, backend) return [g.on_qubits(dict(enumerate(gate.qubits))) for g in decomposition] + def _set_precision_cliff_plus_t( + self, epsilon: float = 1e-16, mpmath_dps: int = 256 + ): + import mpmath # pylint: disable=C0415 + + mpmath.mp.dps = mpmath_dps + self._epsilon = mpmath.mpmathify(epsilon) + + def _rz_into_cliff_and_t( + self, + theta: float, + qubit: int = 0, + ): + import mpmath # pylint: disable=C0415 + from pygridsynth.gridsynth import gridsynth_gates # pylint: disable=C0415 + + theta = float(theta) + theta = mpmath.mpmathify(theta) + + sequence = gridsynth_gates(theta=theta, epsilon=self._epsilon) + sequence = sequence.split("W") + num_global_phase = len(sequence[1:]) + sequence = sequence[0] + + global_phase = cmath.exp(1j * num_global_phase * math.pi / 4) + + gate_list = [ + getattr(gates, gate_name)(qubit) for gate_name in reversed(sequence) + ] + + return gate_list + def _u3_to_gpi2(t, p, l): """Decompose a :class:`qibo.gates.U3` gate into :class:`qibo.gates.GPI2` gates. @@ -70,39 +103,41 @@ def _u3_to_gpi2(t, p, l): if l != 0.0: decomposition.append(gates.RZ(0, l)) decomposition.append(gates.GPI2(0, 0)) - if t != -np.pi: - decomposition.append(gates.RZ(0, t + np.pi)) + if t != -math.pi: + decomposition.append(gates.RZ(0, t + math.pi)) decomposition.append(gates.GPI2(0, 0)) - if p != -np.pi: - decomposition.append(gates.RZ(0, p + np.pi)) + if p != -math.pi: + decomposition.append(gates.RZ(0, p + math.pi)) return decomposition # Decompose single qubit gates using GPI2 (more efficient on hardware) gpi2_dec = GateDecompositions() -gpi2_dec.add(gates.H, [gates.Z(0), gates.GPI2(0, np.pi / 2)]) -gpi2_dec.add(gates.X, [gates.GPI2(0, np.pi / 2), gates.GPI2(0, np.pi / 2), gates.Z(0)]) +gpi2_dec.add(gates.H, [gates.Z(0), gates.GPI2(0, math.pi / 2)]) +gpi2_dec.add( + gates.X, [gates.GPI2(0, math.pi / 2), gates.GPI2(0, math.pi / 2), gates.Z(0)] +) gpi2_dec.add(gates.Y, [gates.Z(0), gates.GPI2(0, 0), gates.GPI2(0, 0)]) gpi2_dec.add(gates.Z, [gates.Z(0)]) -gpi2_dec.add(gates.S, [gates.RZ(0, np.pi / 2)]) -gpi2_dec.add(gates.SDG, [gates.RZ(0, -np.pi / 2)]) -gpi2_dec.add(gates.T, [gates.RZ(0, np.pi / 4)]) -gpi2_dec.add(gates.TDG, [gates.RZ(0, -np.pi / 4)]) +gpi2_dec.add(gates.S, [gates.RZ(0, math.pi / 2)]) +gpi2_dec.add(gates.SDG, [gates.RZ(0, -math.pi / 2)]) +gpi2_dec.add(gates.T, [gates.RZ(0, math.pi / 4)]) +gpi2_dec.add(gates.TDG, [gates.RZ(0, -math.pi / 4)]) gpi2_dec.add(gates.SX, [gates.GPI2(0, 0)]) gpi2_dec.add( gates.RX, lambda gate: [ gates.Z(0), - gates.GPI2(0, np.pi / 2), - gates.RZ(0, gate.parameters[0] + np.pi), - gates.GPI2(0, np.pi / 2), + gates.GPI2(0, math.pi / 2), + gates.RZ(0, gate.parameters[0] + math.pi), + gates.GPI2(0, math.pi / 2), ], ) gpi2_dec.add( gates.RY, lambda gate: [ gates.GPI2(0, 0), - gates.RZ(0, gate.parameters[0] + np.pi), + gates.RZ(0, gate.parameters[0] + math.pi), gates.GPI2(0, 0), gates.Z(0), ], @@ -112,7 +147,7 @@ def _u3_to_gpi2(t, p, l): gpi2_dec.add(gates.U1, lambda gate: [gates.RZ(0, gate.parameters[0])]) gpi2_dec.add( gates.U2, - lambda gate: _u3_to_gpi2(np.pi / 2, gate.parameters[0], gate.parameters[1]), + lambda gate: _u3_to_gpi2(math.pi / 2, gate.parameters[0], gate.parameters[1]), ) gpi2_dec.add(gates.U3, lambda gate: _u3_to_gpi2(*gate.parameters)) gpi2_dec.add( @@ -126,41 +161,44 @@ def _u3_to_gpi2(t, p, l): # Decompose single qubit gates using U3 u3_dec = GateDecompositions() -u3_dec.add(gates.H, [gates.U3(0, -np.pi / 2, np.pi, 0)]) -u3_dec.add(gates.X, [gates.U3(0, np.pi, 0, np.pi)]) -u3_dec.add(gates.Y, [gates.U3(0, np.pi, 0, 0)]) +u3_dec.add(gates.H, [gates.U3(0, -math.pi / 2, math.pi, 0)]) +u3_dec.add(gates.X, [gates.U3(0, math.pi, 0, math.pi)]) +u3_dec.add(gates.Y, [gates.U3(0, math.pi, 0, 0)]) u3_dec.add(gates.Z, [gates.Z(0)]) -u3_dec.add(gates.S, [gates.RZ(0, np.pi / 2)]) -u3_dec.add(gates.SDG, [gates.RZ(0, -np.pi / 2)]) -u3_dec.add(gates.T, [gates.RZ(0, np.pi / 4)]) -u3_dec.add(gates.TDG, [gates.RZ(0, -np.pi / 4)]) -u3_dec.add(gates.SX, [gates.U3(0, np.pi / 2, -np.pi / 2, np.pi / 2)]) +u3_dec.add(gates.S, [gates.RZ(0, math.pi / 2)]) +u3_dec.add(gates.SDG, [gates.RZ(0, -math.pi / 2)]) +u3_dec.add(gates.T, [gates.RZ(0, math.pi / 4)]) +u3_dec.add(gates.TDG, [gates.RZ(0, -math.pi / 4)]) +u3_dec.add(gates.SX, [gates.U3(0, math.pi / 2, -math.pi / 2, math.pi / 2)]) u3_dec.add( gates.RX, - lambda gate: [gates.U3(0, gate.parameters[0], -np.pi / 2, np.pi / 2)], + lambda gate: [gates.U3(0, gate.parameters[0], -math.pi / 2, math.pi / 2)], ) u3_dec.add(gates.RY, lambda gate: [gates.U3(0, gate.parameters[0], 0, 0)]) u3_dec.add(gates.RZ, lambda gate: [gates.RZ(0, gate.parameters[0])]) u3_dec.add( gates.PRX, lambda gate: [ - gates.RZ(0, gate.parameters[1] - np.pi / 2), + gates.RZ(0, gate.parameters[1] - math.pi / 2), gates.RY(0, -gate.parameters[0]), - gates.RZ(0, gate.parameters[1] + np.pi / 2), + gates.RZ(0, gate.parameters[1] + math.pi / 2), ], ) u3_dec.add( gates.GPI2, lambda gate: [ gates.U3( - 0, np.pi / 2, gate.parameters[0] - np.pi / 2, np.pi / 2 - gate.parameters[0] + 0, + math.pi / 2, + gate.parameters[0] - math.pi / 2, + math.pi / 2 - gate.parameters[0], ), ], ) u3_dec.add(gates.U1, lambda gate: [gates.RZ(0, gate.parameters[0])]) u3_dec.add( gates.U2, - lambda gate: [gates.U3(0, np.pi / 2, gate.parameters[0], gate.parameters[1])], + lambda gate: [gates.U3(0, math.pi / 2, gate.parameters[0], gate.parameters[1])], ) u3_dec.add( gates.U3, @@ -184,40 +222,40 @@ def _u3_to_gpi2(t, p, l): iswap_dec.add( gates.CNOT, [ - gates.U3(0, 3 * np.pi / 2, np.pi, 0), - gates.U3(1, np.pi / 2, np.pi, np.pi), + gates.U3(0, 3 * math.pi / 2, math.pi, 0), + gates.U3(1, math.pi / 2, math.pi, math.pi), gates.iSWAP(0, 1), - gates.U3(0, np.pi, 0, np.pi), - gates.U3(1, np.pi / 2, np.pi, np.pi), + gates.U3(0, math.pi, 0, math.pi), + gates.U3(1, math.pi / 2, math.pi, math.pi), gates.iSWAP(0, 1), - gates.U3(0, np.pi / 2, np.pi / 2, np.pi), - gates.U3(1, np.pi / 2, np.pi, -np.pi / 2), + gates.U3(0, math.pi / 2, math.pi / 2, math.pi), + gates.U3(1, math.pi / 2, math.pi, -math.pi / 2), ], ) iswap_dec.add( gates.CZ, [ - gates.U3(0, -np.pi / 2, np.pi, 0), - gates.U3(1, -np.pi / 2, np.pi, 0), - gates.U3(1, np.pi / 2, np.pi, np.pi), + gates.U3(0, -math.pi / 2, math.pi, 0), + gates.U3(1, -math.pi / 2, math.pi, 0), + gates.U3(1, math.pi / 2, math.pi, math.pi), gates.iSWAP(0, 1), - gates.U3(0, np.pi, 0, np.pi), - gates.U3(1, np.pi / 2, np.pi, np.pi), + gates.U3(0, math.pi, 0, math.pi), + gates.U3(1, math.pi / 2, math.pi, math.pi), gates.iSWAP(0, 1), - gates.U3(0, np.pi / 2, np.pi / 2, np.pi), - gates.U3(1, np.pi / 2, np.pi, -np.pi / 2), - gates.U3(1, -np.pi / 2, np.pi, 0), + gates.U3(0, math.pi / 2, math.pi / 2, math.pi), + gates.U3(1, math.pi / 2, math.pi, -math.pi / 2), + gates.U3(1, -math.pi / 2, math.pi, 0), ], ) iswap_dec.add( gates.SWAP, [ gates.iSWAP(0, 1), - gates.U3(1, np.pi / 2, -np.pi / 2, np.pi / 2), + gates.U3(1, math.pi / 2, -math.pi / 2, math.pi / 2), gates.iSWAP(0, 1), - gates.U3(0, np.pi / 2, -np.pi / 2, np.pi / 2), + gates.U3(0, math.pi / 2, -math.pi / 2, math.pi / 2), gates.iSWAP(0, 1), - gates.U3(1, np.pi / 2, -np.pi / 2, np.pi / 2), + gates.U3(1, math.pi / 2, -math.pi / 2, math.pi / 2), ], ) iswap_dec.add(gates.iSWAP, [gates.iSWAP(0, 1)]) @@ -243,8 +281,8 @@ def _u3_to_gpi2(t, p, l): cz_dec.add( gates.iSWAP, [ - gates.U3(0, np.pi / 2.0, 0, -np.pi / 2.0), - gates.U3(1, np.pi / 2.0, 0, -np.pi / 2.0), + gates.U3(0, math.pi / 2.0, 0, -math.pi / 2.0), + gates.U3(1, math.pi / 2.0, 0, -math.pi / 2.0), gates.CZ(0, 1), gates.H(0), gates.H(1), @@ -301,11 +339,11 @@ def _u3_to_gpi2(t, p, l): gates.H(1), gates.CZ(0, 1), gates.H(1), - gates.U3(1, -np.pi / 4, 0, -(gate.parameters[1] + gate.parameters[0]) / 2.0), + gates.U3(1, -math.pi / 4, 0, -(gate.parameters[1] + gate.parameters[0]) / 2.0), gates.H(1), gates.CZ(0, 1), gates.H(1), - gates.U3(1, np.pi / 4, gate.parameters[0], 0), + gates.U3(1, math.pi / 4, gate.parameters[0], 0), ], ) cz_dec.add( @@ -330,14 +368,14 @@ def _u3_to_gpi2(t, p, l): cz_dec.add( gates.FSWAP, [ - gates.U3(0, np.pi / 2, -np.pi / 2, np.pi), - gates.U3(1, np.pi / 2, np.pi / 2, np.pi / 2), + gates.U3(0, math.pi / 2, -math.pi / 2, math.pi), + gates.U3(1, math.pi / 2, math.pi / 2, math.pi / 2), gates.CZ(0, 1), - gates.U3(0, np.pi / 2, 0, -np.pi / 2), - gates.U3(1, np.pi / 2, 0, np.pi / 2), + gates.U3(0, math.pi / 2, 0, -math.pi / 2), + gates.U3(1, math.pi / 2, 0, math.pi / 2), gates.CZ(0, 1), - gates.U3(0, np.pi / 2, np.pi / 2, np.pi), - gates.U3(1, np.pi / 2, 0, np.pi), + gates.U3(0, math.pi / 2, math.pi / 2, math.pi), + gates.U3(1, math.pi / 2, 0, math.pi), ], ) cz_dec.add( @@ -353,13 +391,13 @@ def _u3_to_gpi2(t, p, l): cz_dec.add( gates.RYY, lambda gate: [ - gates.RX(0, np.pi / 2), - gates.U3(1, np.pi / 2, np.pi / 2, np.pi), + gates.RX(0, math.pi / 2), + gates.U3(1, math.pi / 2, math.pi / 2, math.pi), gates.CZ(0, 1), gates.RX(1, gate.parameters[0]), gates.CZ(0, 1), - gates.RX(0, -np.pi / 2), - gates.U3(1, np.pi / 2, 0, np.pi / 2), + gates.RX(0, -math.pi / 2), + gates.U3(1, math.pi / 2, 0, math.pi / 2), ], ) cz_dec.add( @@ -376,18 +414,18 @@ def _u3_to_gpi2(t, p, l): gates.TOFFOLI, [ gates.CZ(1, 2), - gates.RX(2, -np.pi / 4), + gates.RX(2, -math.pi / 4), gates.CZ(0, 2), - gates.RX(2, np.pi / 4), + gates.RX(2, math.pi / 4), gates.CZ(1, 2), - gates.RX(2, -np.pi / 4), + gates.RX(2, -math.pi / 4), gates.CZ(0, 2), - gates.RX(2, np.pi / 4), - gates.RZ(1, np.pi / 4), + gates.RX(2, math.pi / 4), + gates.RZ(1, math.pi / 4), gates.H(1), gates.CZ(0, 1), - gates.RZ(0, np.pi / 4), - gates.RX(1, -np.pi / 4), + gates.RZ(0, math.pi / 4), + gates.RX(1, -math.pi / 4), gates.CZ(0, 1), gates.H(1), ], @@ -485,14 +523,14 @@ def _decomposition_generalized_RBS(gate): # standard gate decompositions used by :meth:`qibo.gates.gates.Gate.decompose` standard_decompositions = GateDecompositions() -standard_decompositions.add(gates.SX, [gates.RX(0, np.pi / 2, trainable=False)]) -standard_decompositions.add(gates.SXDG, [gates.RX(0, -np.pi / 2, trainable=False)]) +standard_decompositions.add(gates.SX, [gates.RX(0, math.pi / 2, trainable=False)]) +standard_decompositions.add(gates.SXDG, [gates.RX(0, -math.pi / 2, trainable=False)]) standard_decompositions.add( gates.PRX, lambda gate: [ - gates.RZ(0, -gate.parameters[1] - np.pi / 2), + gates.RZ(0, -gate.parameters[1] - math.pi / 2), gates.RY(0, -gate.parameters[0]), - gates.RZ(0, gate.parameters[1] + np.pi / 2), + gates.RZ(0, gate.parameters[1] + math.pi / 2), ], ) standard_decompositions.add( @@ -500,18 +538,18 @@ def _decomposition_generalized_RBS(gate): lambda gate: [ gates.RZ(0, gate.parameters[2]), gates.SX(0), - gates.RZ(0, gate.parameters[0] + np.pi), + gates.RZ(0, gate.parameters[0] + math.pi), gates.SX(0), - gates.RZ(0, gate.parameters[1] + np.pi), + gates.RZ(0, gate.parameters[1] + math.pi), ], ) standard_decompositions.add(gates.CY, [gates.SDG(1), gates.CNOT(0, 1), gates.S(1)]) standard_decompositions.add(gates.CZ, [gates.H(1), gates.CNOT(0, 1), gates.H(1)]) standard_decompositions.add( - gates.CSX, [gates.H(1), gates.CU1(0, 1, np.pi / 2), gates.H(1)] + gates.CSX, [gates.H(1), gates.CU1(0, 1, math.pi / 2), gates.H(1)] ) standard_decompositions.add( - gates.CSXDG, [gates.H(1), gates.CU1(0, 1, -np.pi / 2), gates.H(1)] + gates.CSXDG, [gates.H(1), gates.CU1(0, 1, -math.pi / 2), gates.H(1)] ) standard_decompositions.add( gates.CRX, @@ -558,9 +596,9 @@ def _decomposition_generalized_RBS(gate): lambda gate: [ gates.RZ(1, (gate.parameters[1] - gate.parameters[0]) / 2.0), gates.CNOT(0, 1), - gates.U3(1, -np.pi / 4, 0, -(gate.parameters[1] + gate.parameters[0]) / 2.0), + gates.U3(1, -math.pi / 4, 0, -(gate.parameters[1] + gate.parameters[0]) / 2.0), gates.CNOT(0, 1), - gates.U3(1, np.pi / 4, gate.parameters[0], 0), + gates.U3(1, math.pi / 4, gate.parameters[0], 0), ], ) standard_decompositions.add( @@ -597,14 +635,14 @@ def _decomposition_generalized_RBS(gate): [ gates.SX(0), gates.SX(1), - gates.RZ(0, np.pi / 2), + gates.RZ(0, math.pi / 2), gates.CNOT(0, 1), gates.SX(0), - gates.RZ(1, -np.pi / 4), - gates.RZ(0, -np.pi / 4), + gates.RZ(1, -math.pi / 4), + gates.RZ(0, -math.pi / 4), gates.SX(1), gates.SX(0), - gates.RZ(0, np.pi / 2), + gates.RZ(0, math.pi / 2), gates.CNOT(0, 1), gates.SX(0), ], @@ -624,17 +662,16 @@ def _decomposition_generalized_RBS(gate): gates.H(0), ], ) - standard_decompositions.add( gates.RYY, lambda gate: [ - gates.RX(0, np.pi / 2), - gates.RX(1, np.pi / 2), + gates.RX(0, math.pi / 2), + gates.RX(1, math.pi / 2), gates.CNOT(0, 1), gates.RZ(1, gate.parameters[0]), gates.CNOT(0, 1), - gates.RX(1, -np.pi / 2), - gates.RX(0, -np.pi / 2), + gates.RX(1, -math.pi / 2), + gates.RX(0, -math.pi / 2), ], ) standard_decompositions.add( @@ -658,25 +695,26 @@ def _decomposition_generalized_RBS(gate): standard_decompositions.add( gates.RXXYY, lambda gate: [ - gates.RZ(1, -np.pi / 2), + gates.RZ(1, -math.pi / 2), gates.S(0), gates.SX(1), - gates.RZ(1, np.pi / 2), + gates.RZ(1, math.pi / 2), gates.CNOT(1, 0), gates.RY(0, -gate.parameters[0] / 2), gates.RY(1, -gate.parameters[0] / 2), gates.CNOT(1, 0), gates.SDG(0), - gates.RZ(1, -np.pi / 2), - gates.SX(1).dagger(), - gates.RZ(1, np.pi / 2), + gates.RZ(1, -math.pi / 2), + gates.SXDG(1), + gates.RZ(1, math.pi / 2), ], ) standard_decompositions.add( gates.GIVENS, lambda gate: gates.RBS(0, 1, -gate.parameters[0]).decompose() ) standard_decompositions.add( - gates.FSWAP, [gates.X(1)] + gates.GIVENS(0, 1, np.pi / 2).decompose() + [gates.X(0)] + gates.FSWAP, + [gates.X(1)] + gates.GIVENS(0, 1, math.pi / 2).decompose() + [gates.X(0)], ) standard_decompositions.add( gates.ECR, [gates.S(0), gates.SX(1), gates.CNOT(0, 1), gates.X(0)] @@ -735,3 +773,245 @@ def _decomposition_generalized_RBS(gate): standard_decompositions.add( gates.GeneralizedRBS, lambda gate: _decomposition_generalized_RBS(gate) ) + +method = "clifford_plus_t" +clifford_plus_t = GateDecompositions() +clifford_plus_t._set_precision_cliff_plus_t() +clifford_plus_t.add(gates.SDG, [gates.Y(0), gates.S(0), gates.Y(0)]) +clifford_plus_t.add(gates.TDG, [gates.T(0), gates.Y(0), gates.S(0), gates.Y(0)]) +clifford_plus_t.add( + gates.RX, + lambda gate: [gates.H(0)] + + clifford_plus_t._rz_into_cliff_and_t(gate.parameters[0]) + + [gates.H(0)], +) +clifford_plus_t.add( + gates.RY, + lambda gate: [gates.SDG(0), gates.H(0)] + + clifford_plus_t._rz_into_cliff_and_t(gate.parameters[0]) + + [gates.H(0), gates.S(0)], +) +clifford_plus_t.add( + gates.RZ, lambda gate: clifford_plus_t._rz_into_cliff_and_t(gate.parameters[0]) +) +clifford_plus_t.add( + gates.PRX, + lambda gate: clifford_plus_t._rz_into_cliff_and_t(-gate.parameters[1] - math.pi / 2) + + gates.RY(0, -gate.parameters[0]).decompose(method=method) + + clifford_plus_t._rz_into_cliff_and_t(gate.parameters[1] + math.pi / 2), +) +clifford_plus_t.add( + gates.U1, lambda gate: clifford_plus_t._rz_into_cliff_and_t(gate.parameters[0]) +) +clifford_plus_t.add( + gates.U2, + lambda gate: clifford_plus_t._rz_into_cliff_and_t(gate.parameters[1] - math.pi) + + [gates.SX(0)] + + clifford_plus_t._rz_into_cliff_and_t(gate.parameters[0] + math.pi), +) +clifford_plus_t.add( + gates.U3, + lambda gate: clifford_plus_t._rz_into_cliff_and_t(gate.parameters[2]) + + [gates.SX(0)] + + clifford_plus_t._rz_into_cliff_and_t(gate.parameters[0] + math.pi) + + [gates.SX(0)] + + clifford_plus_t._rz_into_cliff_and_t(gate.parameters[1] + math.pi), +) +clifford_plus_t.add( + gates.PRX, + lambda gate: clifford_plus_t._rz_into_cliff_and_t(-gate.parameters[1] - math.pi / 2) + + gates.RY(0, -gate.parameters[0]).decompose(method=method) + + clifford_plus_t._rz_into_cliff_and_t(gate.parameters[1] + math.pi / 2), +) +clifford_plus_t.add(gates.CY, [gates.SDG(1), gates.CNOT(0, 1), gates.S(1)]) +clifford_plus_t.add(gates.CZ, [gates.H(1), gates.CNOT(0, 1), gates.H(1)]) +clifford_plus_t.add( + gates.CRX, + lambda gate: gates.RX(1, gate.parameters[0] / 2.0).decompose(method=method) + + [gates.H(1), gates.CNOT(0, 1)] + + gates.RZ(1, -gate.parameters[0] / 2.0).decompose(method=method) + + [gates.CNOT(0, 1), gates.H(1)], +) +clifford_plus_t.add( + gates.CRY, + lambda gate: gates.RY(1, gate.parameters[0] / 4).decompose(method=method) + + [gates.CNOT(0, 1)] + + gates.RY(1, -gate.parameters[0] / 2).decompose(method=method) + + [gates.CNOT(0, 1)] + + gates.RY(1, gate.parameters[0] / 4).decompose(method=method), +) +clifford_plus_t.add( + gates.CRZ, + lambda gate: gates.RZ(1, gate.parameters[0] / 2.0).decompose(method=method) + + [gates.CNOT(0, 1)] + + gates.RZ(1, -gate.parameters[0] / 2.0).decompose(method=method) + + [gates.CNOT(0, 1)], +) +clifford_plus_t.add( + gates.CU1, + lambda gate: gates.RZ(0, gate.parameters[0] / 2.0).decompose(method=method) + + [gates.CNOT(0, 1)] + + gates.RZ(1, -gate.parameters[0] / 2.0).decompose(method=method) + + [gates.CNOT(0, 1)] + + gates.RZ(1, gate.parameters[0] / 2.0).decompose(method=method), +) +clifford_plus_t.add( + gates.CU2, + lambda gate: gates.RZ(1, (gate.parameters[1] - gate.parameters[0]) / 2.0).decompose( + method=method + ) + + [gates.CNOT(0, 1)] + + gates.U3( + 1, -math.pi / 4, 0, -(gate.parameters[1] + gate.parameters[0]) / 2.0 + ).decompose(method=method) + + [gates.CNOT(0, 1)] + + gates.U3(1, math.pi / 4, gate.parameters[0], 0).decompose(method=method), +) +clifford_plus_t.add( + gates.CU3, + lambda gate: gates.RZ(1, (gate.parameters[2] - gate.parameters[1]) / 2.0).decompose( + method=method + ) + + [gates.CNOT(0, 1)] + + gates.U3( + 1, + -gate.parameters[0] / 2.0, + 0, + -(gate.parameters[2] + gate.parameters[1]) / 2.0, + ).decompose(method=method) + + [gates.CNOT(0, 1)] + + gates.U3(1, gate.parameters[0] / 2.0, gate.parameters[1], 0).decompose( + method=method + ), +) +clifford_plus_t.add( + gates.CSX, + [gates.H(1)] + gates.CU1(0, 1, math.pi / 2).decompose(method=method) + [gates.H(1)], +) +clifford_plus_t.add( + gates.CSXDG, + [gates.H(1)] + + gates.CU1(0, 1, -math.pi / 2).decompose(method=method) + + [gates.H(1)], +) +clifford_plus_t.add(gates.SWAP, [gates.CNOT(0, 1), gates.CNOT(1, 0), gates.CNOT(0, 1)]) +clifford_plus_t.add( + gates.iSWAP, + [ + gates.S(0), + gates.S(1), + gates.H(0), + gates.CNOT(0, 1), + gates.CNOT(1, 0), + gates.H(1), + ], +) +clifford_plus_t.add( + gates.SiSWAP, + [gates.SX(0), gates.SX(1)] + + gates.RZ(0, math.pi / 2).decompose(method=method) + + [gates.CNOT(0, 1), gates.SX(0)] + + gates.RZ(1, -math.pi / 4).decompose(method=method) + + gates.RZ(0, -math.pi / 4).decompose(method=method) + + [gates.SX(1), gates.SX(0)] + + gates.RZ(0, math.pi / 2).decompose(method=method) + + [gates.CNOT(0, 1), gates.SX(0)], +) +clifford_plus_t.add( + gates.SiSWAPDG, + [gate.dagger() for gate in reversed(gates.SiSWAP(0, 1).decompose(method=method))], +) +clifford_plus_t.add( + gates.RXX, + lambda gate: [gates.H(0), gates.H(1), gates.CNOT(0, 1)] + + gates.RZ(1, gate.parameters[0]).decompose(method=method) + + [gates.CNOT(0, 1), gates.H(1), gates.H(0)], +) +clifford_plus_t.add( + gates.RYY, + lambda gate: gates.RX(0, math.pi / 2).decompose(method=method) + + gates.RX(1, math.pi / 2).decompose(method=method) + + [gates.CNOT(0, 1)] + + gates.RZ(1, gate.parameters[0]).decompose(method=method) + + [gates.CNOT(0, 1)] + + gates.RX(1, -math.pi / 2).decompose(method=method) + + gates.RX(0, -math.pi / 2).decompose(method=method), +) +clifford_plus_t.add( + gates.RZZ, + lambda gate: [gates.CNOT(0, 1)] + + gates.RZ(1, gate.parameters[0]).decompose(method=method) + + [gates.CNOT(0, 1)], +) +clifford_plus_t.add( + gates.RZX, + lambda gate: [gates.H(1), gates.CNOT(0, 1)] + + gates.RZ(1, gate.parameters[0]).decompose(method=method) + + [gates.CNOT(0, 1), gates.H(1)], +) +clifford_plus_t.add( + gates.RXXYY, + lambda gate: gates.RZ(1, -math.pi / 2).decompose(method=method) + + [gates.S(0), gates.SX(1)] + + gates.RZ(1, math.pi / 2).decompose(method=method) + + [gates.CNOT(1, 0)] + + gates.RY(0, -gate.parameters[0] / 2).decompose(method=method) + + gates.RY(1, -gate.parameters[0] / 2).decompose(method=method) + + [gates.CNOT(1, 0), gates.SDG(0)] + + gates.RZ(1, -math.pi / 2).decompose(method=method) + + [gates.SXDG(1)] + + gates.RZ(1, math.pi / 2).decompose(method=method), +) +clifford_plus_t.add( + gates.GIVENS, + lambda gate: gates.RBS(0, 1, -gate.parameters[0]).decompose(method=method), +) +clifford_plus_t.add( + gates.FSWAP, + [gates.X(1)] + + gates.GIVENS(0, 1, math.pi / 2).decompose(method=method) + + [gates.X(0)], +) +clifford_plus_t.add(gates.ECR, [gates.S(0), gates.SX(1), gates.CNOT(0, 1), gates.X(0)]) +clifford_plus_t.add( + gates.CCZ, + [ + gates.CNOT(1, 2), + gates.TDG(2), + gates.CNOT(0, 2), + gates.T(2), + gates.CNOT(1, 2), + gates.T(1), + gates.TDG(2), + gates.CNOT(0, 2), + gates.CNOT(0, 1), + gates.T(2), + gates.T(0), + gates.TDG(1), + gates.CNOT(0, 1), + ], +) +clifford_plus_t.add( + gates.TOFFOLI, + [ + gates.H(2), + gates.CNOT(1, 2), + gates.TDG(2), + gates.CNOT(0, 2), + gates.T(2), + gates.CNOT(1, 2), + gates.T(1), + gates.TDG(2), + gates.CNOT(0, 2), + gates.CNOT(0, 1), + gates.T(2), + gates.T(0), + gates.TDG(1), + gates.H(2), + gates.CNOT(0, 1), + ], +) +clifford_plus_t.add( + gates.FanOut, + lambda gate: [gates.CNOT(0, qub) for qub in range(1, len(gate.qubits))], +)