diff --git a/examples/falqon/README.md b/examples/falqon/README.md index feca37acba..af2c0157f0 100644 --- a/examples/falqon/README.md +++ b/examples/falqon/README.md @@ -31,7 +31,7 @@ The `FALQON` class behaves similarly to the `QAOA` one. It admits the following - `accelerators`: Dictionary of devices to use for distributed execution. See `qibo.core.distcircuit.DistributedCircuit` for more details. This option is available only when ``hamiltonian`` - is a `qibo.abstractions.hamiltonians.TrotterHamiltonian`. + is a `qibo.abstractions.hamiltonians.SymbolicHamiltonian`. - `memory_device`: Name of device where the full state will be saved. Relevant only for distributed execution (when ``accelerators`` is given). diff --git a/poetry.lock b/poetry.lock index 981db7210e..f1f5a2a83e 100644 --- a/poetry.lock +++ b/poetry.lock @@ -171,20 +171,20 @@ dev = ["backports.zoneinfo", "freezegun (>=1.0,<2.0)", "jinja2 (>=3.0)", "pytest [[package]] name = "beautifulsoup4" -version = "4.13.0" +version = "4.13.3" description = "Screen-scraping library" optional = false -python-versions = ">=3.6.0" +python-versions = ">=3.7.0" groups = ["docs", "tests"] markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ - {file = "beautifulsoup4-4.13.0-py3-none-any.whl", hash = "sha256:9c4c3dfa67aba55f6cd03769c441b21e6a369797fd6766e4b4c6b3399aae2735"}, - {file = "beautifulsoup4-4.13.0.tar.gz", hash = "sha256:b6e5afb3a2b1472c8db751a92eabf7834e5c7099f990c5e4b35f1f16b60bae64"}, + {file = "beautifulsoup4-4.13.3-py3-none-any.whl", hash = "sha256:99045d7d3f08f91f0d656bc9b7efbae189426cd913d830294a15eefa0ea4df16"}, + {file = "beautifulsoup4-4.13.3.tar.gz", hash = "sha256:1bd32405dacc920b42b83ba01644747ed77456a65760e285fbc47633ceddaf8b"}, ] [package.dependencies] soupsieve = ">1.2" -typing-extensions = "*" +typing-extensions = ">=4.0.0" [package.extras] cchardet = ["cchardet"] @@ -788,75 +788,76 @@ test = ["altair", "baytune", "chocolate", "cmaes", "dask", "distributed", "kahyp [[package]] name = "coverage" -version = "7.6.10" +version = "7.6.12" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.9" groups = ["tests"] markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ - {file = "coverage-7.6.10-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5c912978f7fbf47ef99cec50c4401340436d200d41d714c7a4766f377c5b7b78"}, - {file = "coverage-7.6.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a01ec4af7dfeb96ff0078ad9a48810bb0cc8abcb0115180c6013a6b26237626c"}, - {file = "coverage-7.6.10-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3b204c11e2b2d883946fe1d97f89403aa1811df28ce0447439178cc7463448a"}, - {file = "coverage-7.6.10-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:32ee6d8491fcfc82652a37109f69dee9a830e9379166cb73c16d8dc5c2915165"}, - {file = "coverage-7.6.10-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:675cefc4c06e3b4c876b85bfb7c59c5e2218167bbd4da5075cbe3b5790a28988"}, - {file = "coverage-7.6.10-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f4f620668dbc6f5e909a0946a877310fb3d57aea8198bde792aae369ee1c23b5"}, - {file = "coverage-7.6.10-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:4eea95ef275de7abaef630c9b2c002ffbc01918b726a39f5a4353916ec72d2f3"}, - {file = "coverage-7.6.10-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e2f0280519e42b0a17550072861e0bc8a80a0870de260f9796157d3fca2733c5"}, - {file = "coverage-7.6.10-cp310-cp310-win32.whl", hash = "sha256:bc67deb76bc3717f22e765ab3e07ee9c7a5e26b9019ca19a3b063d9f4b874244"}, - {file = "coverage-7.6.10-cp310-cp310-win_amd64.whl", hash = "sha256:0f460286cb94036455e703c66988851d970fdfd8acc2a1122ab7f4f904e4029e"}, - {file = "coverage-7.6.10-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ea3c8f04b3e4af80e17bab607c386a830ffc2fb88a5484e1df756478cf70d1d3"}, - {file = "coverage-7.6.10-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:507a20fc863cae1d5720797761b42d2d87a04b3e5aeb682ef3b7332e90598f43"}, - {file = "coverage-7.6.10-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d37a84878285b903c0fe21ac8794c6dab58150e9359f1aaebbeddd6412d53132"}, - {file = "coverage-7.6.10-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a534738b47b0de1995f85f582d983d94031dffb48ab86c95bdf88dc62212142f"}, - {file = "coverage-7.6.10-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d7a2bf79378d8fb8afaa994f91bfd8215134f8631d27eba3e0e2c13546ce994"}, - {file = "coverage-7.6.10-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6713ba4b4ebc330f3def51df1d5d38fad60b66720948112f114968feb52d3f99"}, - {file = "coverage-7.6.10-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ab32947f481f7e8c763fa2c92fd9f44eeb143e7610c4ca9ecd6a36adab4081bd"}, - {file = "coverage-7.6.10-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7bbd8c8f1b115b892e34ba66a097b915d3871db7ce0e6b9901f462ff3a975377"}, - {file = "coverage-7.6.10-cp311-cp311-win32.whl", hash = "sha256:299e91b274c5c9cdb64cbdf1b3e4a8fe538a7a86acdd08fae52301b28ba297f8"}, - {file = "coverage-7.6.10-cp311-cp311-win_amd64.whl", hash = "sha256:489a01f94aa581dbd961f306e37d75d4ba16104bbfa2b0edb21d29b73be83609"}, - {file = "coverage-7.6.10-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:27c6e64726b307782fa5cbe531e7647aee385a29b2107cd87ba7c0105a5d3853"}, - {file = "coverage-7.6.10-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c56e097019e72c373bae32d946ecf9858fda841e48d82df7e81c63ac25554078"}, - {file = "coverage-7.6.10-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7827a5bc7bdb197b9e066cdf650b2887597ad124dd99777332776f7b7c7d0d0"}, - {file = "coverage-7.6.10-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:204a8238afe787323a8b47d8be4df89772d5c1e4651b9ffa808552bdf20e1d50"}, - {file = "coverage-7.6.10-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e67926f51821b8e9deb6426ff3164870976fe414d033ad90ea75e7ed0c2e5022"}, - {file = "coverage-7.6.10-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e78b270eadb5702938c3dbe9367f878249b5ef9a2fcc5360ac7bff694310d17b"}, - {file = "coverage-7.6.10-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:714f942b9c15c3a7a5fe6876ce30af831c2ad4ce902410b7466b662358c852c0"}, - {file = "coverage-7.6.10-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:abb02e2f5a3187b2ac4cd46b8ced85a0858230b577ccb2c62c81482ca7d18852"}, - {file = "coverage-7.6.10-cp312-cp312-win32.whl", hash = "sha256:55b201b97286cf61f5e76063f9e2a1d8d2972fc2fcfd2c1272530172fd28c359"}, - {file = "coverage-7.6.10-cp312-cp312-win_amd64.whl", hash = "sha256:e4ae5ac5e0d1e4edfc9b4b57b4cbecd5bc266a6915c500f358817a8496739247"}, - {file = "coverage-7.6.10-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:05fca8ba6a87aabdd2d30d0b6c838b50510b56cdcfc604d40760dae7153b73d9"}, - {file = "coverage-7.6.10-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9e80eba8801c386f72e0712a0453431259c45c3249f0009aff537a517b52942b"}, - {file = "coverage-7.6.10-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a372c89c939d57abe09e08c0578c1d212e7a678135d53aa16eec4430adc5e690"}, - {file = "coverage-7.6.10-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ec22b5e7fe7a0fa8509181c4aac1db48f3dd4d3a566131b313d1efc102892c18"}, - {file = "coverage-7.6.10-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26bcf5c4df41cad1b19c84af71c22cbc9ea9a547fc973f1f2cc9a290002c8b3c"}, - {file = "coverage-7.6.10-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4e4630c26b6084c9b3cb53b15bd488f30ceb50b73c35c5ad7871b869cb7365fd"}, - {file = "coverage-7.6.10-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2396e8116db77789f819d2bc8a7e200232b7a282c66e0ae2d2cd84581a89757e"}, - {file = "coverage-7.6.10-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:79109c70cc0882e4d2d002fe69a24aa504dec0cc17169b3c7f41a1d341a73694"}, - {file = "coverage-7.6.10-cp313-cp313-win32.whl", hash = "sha256:9e1747bab246d6ff2c4f28b4d186b205adced9f7bd9dc362051cc37c4a0c7bd6"}, - {file = "coverage-7.6.10-cp313-cp313-win_amd64.whl", hash = "sha256:254f1a3b1eef5f7ed23ef265eaa89c65c8c5b6b257327c149db1ca9d4a35f25e"}, - {file = "coverage-7.6.10-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2ccf240eb719789cedbb9fd1338055de2761088202a9a0b73032857e53f612fe"}, - {file = "coverage-7.6.10-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:0c807ca74d5a5e64427c8805de15b9ca140bba13572d6d74e262f46f50b13273"}, - {file = "coverage-7.6.10-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2bcfa46d7709b5a7ffe089075799b902020b62e7ee56ebaed2f4bdac04c508d8"}, - {file = "coverage-7.6.10-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4e0de1e902669dccbf80b0415fb6b43d27edca2fbd48c74da378923b05316098"}, - {file = "coverage-7.6.10-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f7b444c42bbc533aaae6b5a2166fd1a797cdb5eb58ee51a92bee1eb94a1e1cb"}, - {file = "coverage-7.6.10-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b330368cb99ef72fcd2dc3ed260adf67b31499584dc8a20225e85bfe6f6cfed0"}, - {file = "coverage-7.6.10-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:9a7cfb50515f87f7ed30bc882f68812fd98bc2852957df69f3003d22a2aa0abf"}, - {file = "coverage-7.6.10-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6f93531882a5f68c28090f901b1d135de61b56331bba82028489bc51bdd818d2"}, - {file = "coverage-7.6.10-cp313-cp313t-win32.whl", hash = "sha256:89d76815a26197c858f53c7f6a656686ec392b25991f9e409bcef020cd532312"}, - {file = "coverage-7.6.10-cp313-cp313t-win_amd64.whl", hash = "sha256:54a5f0f43950a36312155dae55c505a76cd7f2b12d26abeebbe7a0b36dbc868d"}, - {file = "coverage-7.6.10-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:656c82b8a0ead8bba147de9a89bda95064874c91a3ed43a00e687f23cc19d53a"}, - {file = "coverage-7.6.10-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ccc2b70a7ed475c68ceb548bf69cec1e27305c1c2606a5eb7c3afff56a1b3b27"}, - {file = "coverage-7.6.10-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5e37dc41d57ceba70956fa2fc5b63c26dba863c946ace9705f8eca99daecdc4"}, - {file = "coverage-7.6.10-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0aa9692b4fdd83a4647eeb7db46410ea1322b5ed94cd1715ef09d1d5922ba87f"}, - {file = "coverage-7.6.10-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa744da1820678b475e4ba3dfd994c321c5b13381d1041fe9c608620e6676e25"}, - {file = "coverage-7.6.10-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:c0b1818063dc9e9d838c09e3a473c1422f517889436dd980f5d721899e66f315"}, - {file = "coverage-7.6.10-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:59af35558ba08b758aec4d56182b222976330ef8d2feacbb93964f576a7e7a90"}, - {file = "coverage-7.6.10-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7ed2f37cfce1ce101e6dffdfd1c99e729dd2ffc291d02d3e2d0af8b53d13840d"}, - {file = "coverage-7.6.10-cp39-cp39-win32.whl", hash = "sha256:4bcc276261505d82f0ad426870c3b12cb177752834a633e737ec5ee79bbdff18"}, - {file = "coverage-7.6.10-cp39-cp39-win_amd64.whl", hash = "sha256:457574f4599d2b00f7f637a0700a6422243b3565509457b2dbd3f50703e11f59"}, - {file = "coverage-7.6.10-pp39.pp310-none-any.whl", hash = "sha256:fd34e7b3405f0cc7ab03d54a334c17a9e802897580d964bd8c2001f4b9fd488f"}, - {file = "coverage-7.6.10.tar.gz", hash = "sha256:7fb105327c8f8f0682e29843e2ff96af9dcbe5bab8eeb4b398c6a33a16d80a23"}, + {file = "coverage-7.6.12-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:704c8c8c6ce6569286ae9622e534b4f5b9759b6f2cd643f1c1a61f666d534fe8"}, + {file = "coverage-7.6.12-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ad7525bf0241e5502168ae9c643a2f6c219fa0a283001cee4cf23a9b7da75879"}, + {file = "coverage-7.6.12-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:06097c7abfa611c91edb9e6920264e5be1d6ceb374efb4986f38b09eed4cb2fe"}, + {file = "coverage-7.6.12-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:220fa6c0ad7d9caef57f2c8771918324563ef0d8272c94974717c3909664e674"}, + {file = "coverage-7.6.12-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3688b99604a24492bcfe1c106278c45586eb819bf66a654d8a9a1433022fb2eb"}, + {file = "coverage-7.6.12-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d1a987778b9c71da2fc8948e6f2656da6ef68f59298b7e9786849634c35d2c3c"}, + {file = "coverage-7.6.12-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:cec6b9ce3bd2b7853d4a4563801292bfee40b030c05a3d29555fd2a8ee9bd68c"}, + {file = "coverage-7.6.12-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ace9048de91293e467b44bce0f0381345078389814ff6e18dbac8fdbf896360e"}, + {file = "coverage-7.6.12-cp310-cp310-win32.whl", hash = "sha256:ea31689f05043d520113e0552f039603c4dd71fa4c287b64cb3606140c66f425"}, + {file = "coverage-7.6.12-cp310-cp310-win_amd64.whl", hash = "sha256:676f92141e3c5492d2a1596d52287d0d963df21bf5e55c8b03075a60e1ddf8aa"}, + {file = "coverage-7.6.12-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e18aafdfb3e9ec0d261c942d35bd7c28d031c5855dadb491d2723ba54f4c3015"}, + {file = "coverage-7.6.12-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:66fe626fd7aa5982cdebad23e49e78ef7dbb3e3c2a5960a2b53632f1f703ea45"}, + {file = "coverage-7.6.12-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ef01d70198431719af0b1f5dcbefc557d44a190e749004042927b2a3fed0702"}, + {file = "coverage-7.6.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07e92ae5a289a4bc4c0aae710c0948d3c7892e20fd3588224ebe242039573bf0"}, + {file = "coverage-7.6.12-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e695df2c58ce526eeab11a2e915448d3eb76f75dffe338ea613c1201b33bab2f"}, + {file = "coverage-7.6.12-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d74c08e9aaef995f8c4ef6d202dbd219c318450fe2a76da624f2ebb9c8ec5d9f"}, + {file = "coverage-7.6.12-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e995b3b76ccedc27fe4f477b349b7d64597e53a43fc2961db9d3fbace085d69d"}, + {file = "coverage-7.6.12-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b1f097878d74fe51e1ddd1be62d8e3682748875b461232cf4b52ddc6e6db0bba"}, + {file = "coverage-7.6.12-cp311-cp311-win32.whl", hash = "sha256:1f7ffa05da41754e20512202c866d0ebfc440bba3b0ed15133070e20bf5aeb5f"}, + {file = "coverage-7.6.12-cp311-cp311-win_amd64.whl", hash = "sha256:e216c5c45f89ef8971373fd1c5d8d1164b81f7f5f06bbf23c37e7908d19e8558"}, + {file = "coverage-7.6.12-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b172f8e030e8ef247b3104902cc671e20df80163b60a203653150d2fc204d1ad"}, + {file = "coverage-7.6.12-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:641dfe0ab73deb7069fb972d4d9725bf11c239c309ce694dd50b1473c0f641c3"}, + {file = "coverage-7.6.12-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e549f54ac5f301e8e04c569dfdb907f7be71b06b88b5063ce9d6953d2d58574"}, + {file = "coverage-7.6.12-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:959244a17184515f8c52dcb65fb662808767c0bd233c1d8a166e7cf74c9ea985"}, + {file = "coverage-7.6.12-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bda1c5f347550c359f841d6614fb8ca42ae5cb0b74d39f8a1e204815ebe25750"}, + {file = "coverage-7.6.12-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1ceeb90c3eda1f2d8c4c578c14167dbd8c674ecd7d38e45647543f19839dd6ea"}, + {file = "coverage-7.6.12-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f16f44025c06792e0fb09571ae454bcc7a3ec75eeb3c36b025eccf501b1a4c3"}, + {file = "coverage-7.6.12-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b076e625396e787448d27a411aefff867db2bffac8ed04e8f7056b07024eed5a"}, + {file = "coverage-7.6.12-cp312-cp312-win32.whl", hash = "sha256:00b2086892cf06c7c2d74983c9595dc511acca00665480b3ddff749ec4fb2a95"}, + {file = "coverage-7.6.12-cp312-cp312-win_amd64.whl", hash = "sha256:7ae6eabf519bc7871ce117fb18bf14e0e343eeb96c377667e3e5dd12095e0288"}, + {file = "coverage-7.6.12-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:488c27b3db0ebee97a830e6b5a3ea930c4a6e2c07f27a5e67e1b3532e76b9ef1"}, + {file = "coverage-7.6.12-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5d1095bbee1851269f79fd8e0c9b5544e4c00c0c24965e66d8cba2eb5bb535fd"}, + {file = "coverage-7.6.12-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0533adc29adf6a69c1baa88c3d7dbcaadcffa21afbed3ca7a225a440e4744bf9"}, + {file = "coverage-7.6.12-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:53c56358d470fa507a2b6e67a68fd002364d23c83741dbc4c2e0680d80ca227e"}, + {file = "coverage-7.6.12-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64cbb1a3027c79ca6310bf101014614f6e6e18c226474606cf725238cf5bc2d4"}, + {file = "coverage-7.6.12-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:79cac3390bfa9836bb795be377395f28410811c9066bc4eefd8015258a7578c6"}, + {file = "coverage-7.6.12-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:9b148068e881faa26d878ff63e79650e208e95cf1c22bd3f77c3ca7b1d9821a3"}, + {file = "coverage-7.6.12-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8bec2ac5da793c2685ce5319ca9bcf4eee683b8a1679051f8e6ec04c4f2fd7dc"}, + {file = "coverage-7.6.12-cp313-cp313-win32.whl", hash = "sha256:200e10beb6ddd7c3ded322a4186313d5ca9e63e33d8fab4faa67ef46d3460af3"}, + {file = "coverage-7.6.12-cp313-cp313-win_amd64.whl", hash = "sha256:2b996819ced9f7dbb812c701485d58f261bef08f9b85304d41219b1496b591ef"}, + {file = "coverage-7.6.12-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:299cf973a7abff87a30609879c10df0b3bfc33d021e1adabc29138a48888841e"}, + {file = "coverage-7.6.12-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:4b467a8c56974bf06e543e69ad803c6865249d7a5ccf6980457ed2bc50312703"}, + {file = "coverage-7.6.12-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2458f275944db8129f95d91aee32c828a408481ecde3b30af31d552c2ce284a0"}, + {file = "coverage-7.6.12-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a9d8be07fb0832636a0f72b80d2a652fe665e80e720301fb22b191c3434d924"}, + {file = "coverage-7.6.12-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14d47376a4f445e9743f6c83291e60adb1b127607a3618e3185bbc8091f0467b"}, + {file = "coverage-7.6.12-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b95574d06aa9d2bd6e5cc35a5bbe35696342c96760b69dc4287dbd5abd4ad51d"}, + {file = "coverage-7.6.12-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:ecea0c38c9079570163d663c0433a9af4094a60aafdca491c6a3d248c7432827"}, + {file = "coverage-7.6.12-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:2251fabcfee0a55a8578a9d29cecfee5f2de02f11530e7d5c5a05859aa85aee9"}, + {file = "coverage-7.6.12-cp313-cp313t-win32.whl", hash = "sha256:eb5507795caabd9b2ae3f1adc95f67b1104971c22c624bb354232d65c4fc90b3"}, + {file = "coverage-7.6.12-cp313-cp313t-win_amd64.whl", hash = "sha256:f60a297c3987c6c02ffb29effc70eadcbb412fe76947d394a1091a3615948e2f"}, + {file = "coverage-7.6.12-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e7575ab65ca8399c8c4f9a7d61bbd2d204c8b8e447aab9d355682205c9dd948d"}, + {file = "coverage-7.6.12-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8161d9fbc7e9fe2326de89cd0abb9f3599bccc1287db0aba285cb68d204ce929"}, + {file = "coverage-7.6.12-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a1e465f398c713f1b212400b4e79a09829cd42aebd360362cd89c5bdc44eb87"}, + {file = "coverage-7.6.12-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f25d8b92a4e31ff1bd873654ec367ae811b3a943583e05432ea29264782dc32c"}, + {file = "coverage-7.6.12-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a936309a65cc5ca80fa9f20a442ff9e2d06927ec9a4f54bcba9c14c066323f2"}, + {file = "coverage-7.6.12-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:aa6f302a3a0b5f240ee201297fff0bbfe2fa0d415a94aeb257d8b461032389bd"}, + {file = "coverage-7.6.12-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:f973643ef532d4f9be71dd88cf7588936685fdb576d93a79fe9f65bc337d9d73"}, + {file = "coverage-7.6.12-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:78f5243bb6b1060aed6213d5107744c19f9571ec76d54c99cc15938eb69e0e86"}, + {file = "coverage-7.6.12-cp39-cp39-win32.whl", hash = "sha256:69e62c5034291c845fc4df7f8155e8544178b6c774f97a99e2734b05eb5bed31"}, + {file = "coverage-7.6.12-cp39-cp39-win_amd64.whl", hash = "sha256:b01a840ecc25dce235ae4c1b6a0daefb2a203dba0e6e980637ee9c2f6ee0df57"}, + {file = "coverage-7.6.12-pp39.pp310-none-any.whl", hash = "sha256:7e39e845c4d764208e7b8f6a21c541ade741e2c41afabdfa1caa28687a3c98cf"}, + {file = "coverage-7.6.12-py3-none-any.whl", hash = "sha256:eb8668cfbc279a536c633137deeb9435d2962caec279c3f8cf8b91fff6ff8953"}, + {file = "coverage-7.6.12.tar.gz", hash = "sha256:48cfc4641d95d34766ad41d9573cc0f22a48aa88d22657a1fe01dca0dbae4de2"}, ] [package.dependencies] @@ -1487,63 +1488,63 @@ typing = ["typing-extensions (>=4.12.2)"] [[package]] name = "fonttools" -version = "4.55.8" +version = "4.56.0" description = "Tools to manipulate font files" optional = false python-versions = ">=3.8" groups = ["cuda11", "cuda12", "docs", "tests"] markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ - {file = "fonttools-4.55.8-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d11600f5343092697d7434f3bf77a393c7ae74be206fe30e577b9a195fd53165"}, - {file = "fonttools-4.55.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c96f2506ce1a0beeaa9595f9a8b7446477eb133f40c0e41fc078744c28149f80"}, - {file = "fonttools-4.55.8-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9b5f05ef72e846e9f49ccdd74b9da4309901a4248434c63c1ee9321adcb51d65"}, - {file = "fonttools-4.55.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba45b637da80a262b55b7657aec68da2ac54b8ae7891cd977a5dbe5fd26db429"}, - {file = "fonttools-4.55.8-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:edcffaeadba9a334c1c3866e275d7dd495465e7dbd296f688901bdbd71758113"}, - {file = "fonttools-4.55.8-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b9f9fce3c9b2196e162182ec5db8af8eb3acd0d76c2eafe9fdba5f370044e556"}, - {file = "fonttools-4.55.8-cp310-cp310-win32.whl", hash = "sha256:f089e8da0990cfe2d67e81d9cf581ff372b48dc5acf2782701844211cd1f0eb3"}, - {file = "fonttools-4.55.8-cp310-cp310-win_amd64.whl", hash = "sha256:01ea3901b0802fc5f9e854f5aeb5bc27770dd9dd24c28df8f74ba90f8b3f5915"}, - {file = "fonttools-4.55.8-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:95f5a1d4432b3cea6571f5ce4f4e9b25bf36efbd61c32f4f90130a690925d6ee"}, - {file = "fonttools-4.55.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3d20f152de7625a0008ba1513f126daaaa0de3b4b9030aa72dd5c27294992260"}, - {file = "fonttools-4.55.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5a3ff5bb95fd5a3962b2754f8435e6d930c84fc9e9921c51e802dddf40acd56"}, - {file = "fonttools-4.55.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b99d4fd2b6d0a00c7336c8363fccc7a11eccef4b17393af75ca6e77cf93ff413"}, - {file = "fonttools-4.55.8-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d637e4d33e46619c79d1a6c725f74d71b574cd15fb5bbb9b6f3eba8f28363573"}, - {file = "fonttools-4.55.8-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0f38bfb6b7a39c4162c3eb0820a0bdf8e3bdd125cd54e10ba242397d15e32439"}, - {file = "fonttools-4.55.8-cp311-cp311-win32.whl", hash = "sha256:acfec948de41cd5e640d5c15d0200e8b8e7c5c6bb82afe1ca095cbc4af1188ee"}, - {file = "fonttools-4.55.8-cp311-cp311-win_amd64.whl", hash = "sha256:604c805b41241b4880e2dc86cf2d4754c06777371c8299799ac88d836cb18c3b"}, - {file = "fonttools-4.55.8-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:63403ee0f2fa4e1de28e539f8c24f2bdca1d8ecb503fa9ea2d231d9f1e729809"}, - {file = "fonttools-4.55.8-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:302e1003a760b222f711d5ba6d1ad7fd5f7f713eb872cd6a3eb44390bc9770af"}, - {file = "fonttools-4.55.8-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e72a7816ff8a759be9ca36ca46934f8ccf4383711ef597d9240306fe1878cb8d"}, - {file = "fonttools-4.55.8-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:03c2b50b54e6e8b3564b232e57e8f58be217cf441cf0155745d9e44a76f9c30f"}, - {file = "fonttools-4.55.8-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a7230f7590f9570d26ee903b6a4540274494e200fae978df0d9325b7b9144529"}, - {file = "fonttools-4.55.8-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:466a78984f0572305c3c48377f4e3f7f4e909f1209f45ef8e7041d5c8a744a56"}, - {file = "fonttools-4.55.8-cp312-cp312-win32.whl", hash = "sha256:243cbfc0b7cb1c307af40e321f8343a48d0a080bc1f9466cf2b5468f776ef108"}, - {file = "fonttools-4.55.8-cp312-cp312-win_amd64.whl", hash = "sha256:a19059aa892676822c1f05cb5a67296ecdfeb267fe7c47d4758f3e8e942c2b2a"}, - {file = "fonttools-4.55.8-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:332883b6280b9d90d2ba7e9e81be77cf2ace696161e60cdcf40cfcd2b3ed06fa"}, - {file = "fonttools-4.55.8-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:6b8d7c149d47b47de7ec81763396c8266e5ebe2e0b14aa9c3ccf29e52260ab2f"}, - {file = "fonttools-4.55.8-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4dfae7c94987149bdaa0388e6c937566aa398fa0eec973b17952350a069cff4e"}, - {file = "fonttools-4.55.8-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0fe12f06169af2fdc642d26a8df53e40adc3beedbd6ffedb19f1c5397b63afd"}, - {file = "fonttools-4.55.8-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f971aa5f50c22dc4b63a891503624ae2c77330429b34ead32f23c2260c5618cd"}, - {file = "fonttools-4.55.8-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:708cb17b2590b7f6c6854999df0039ff1140dda9e6f56d67c3599ba6f968fab5"}, - {file = "fonttools-4.55.8-cp313-cp313-win32.whl", hash = "sha256:cfe9cf30f391a0f2875247a3e5e44d8dcb61596e5cf89b360cdffec8a80e9961"}, - {file = "fonttools-4.55.8-cp313-cp313-win_amd64.whl", hash = "sha256:1e10efc8ee10d6f1fe2931d41bccc90cd4b872f2ee4ff21f2231a2c293b2dbf8"}, - {file = "fonttools-4.55.8-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:9b6fcff4dc755b32faff955d989ee26394ddad3a90ea7d558db17a4633c8390c"}, - {file = "fonttools-4.55.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:02c41322e5bdcb484b61b776fcea150215c83619b39c96aa0b44d4fd87bb5574"}, - {file = "fonttools-4.55.8-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9164f44add0acec0f12fce682824c040dc52e483bfe3838c37142897150c8364"}, - {file = "fonttools-4.55.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2248ebfbcea0d0b3cb459d76a9f67f2eadc10ec0d07e9cadab8777d3f016bf2"}, - {file = "fonttools-4.55.8-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:3461347016c94cb42b36caa907e11565878c4c2c375604f3651d11dc06d1ab3e"}, - {file = "fonttools-4.55.8-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:67df1c3935838fb9e56f227d7f506c9043b149a4a3b667bef17929c7a1114d19"}, - {file = "fonttools-4.55.8-cp38-cp38-win32.whl", hash = "sha256:cb121d6dd34625cece32234a5fa0359475bb118838b6b4295ffdb13b935edb04"}, - {file = "fonttools-4.55.8-cp38-cp38-win_amd64.whl", hash = "sha256:285c1ac10c160fbdff6d05358230e66c4f98cbbf271f3ec7eb34e967771543e8"}, - {file = "fonttools-4.55.8-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8abd135e427d88e461a4833c03cf96cfb9028c78c15d58123291f22398e25492"}, - {file = "fonttools-4.55.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:65cb8f97eed7906dcf19bc2736b70c6239e9d7e77aad7c6110ba7239ae082e81"}, - {file = "fonttools-4.55.8-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:450c354c04a6e12a3db968e915fe05730f79ff3d39560947ef8ee6eaa2ab2212"}, - {file = "fonttools-4.55.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2232012a1502b2b8ab4c6bc1d3524bfe90238c0c1a50ac94a0a2085aa87a58a5"}, - {file = "fonttools-4.55.8-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:d39f0c977639be0f9f5505d4c7c478236737f960c567a35f058649c056e41434"}, - {file = "fonttools-4.55.8-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:de78d6d0dbe32561ce059265437021f4746e56073c4799f0f1095828ae7232bd"}, - {file = "fonttools-4.55.8-cp39-cp39-win32.whl", hash = "sha256:bf4b5b3496ddfdd4e57112e77ec51f1ab388d35ac17322c1248addb2eb0d429a"}, - {file = "fonttools-4.55.8-cp39-cp39-win_amd64.whl", hash = "sha256:ccf8ae02918f431953d338db4d0a675a395faf82bab3a76025582cf32a2f3b7b"}, - {file = "fonttools-4.55.8-py3-none-any.whl", hash = "sha256:07636dae94f7fe88561f9da7a46b13d8e3f529f87fdb221b11d85f91eabceeb7"}, - {file = "fonttools-4.55.8.tar.gz", hash = "sha256:54d481d456dcd59af25d4a9c56b2c4c3f20e9620b261b84144e5950f33e8df17"}, + {file = "fonttools-4.56.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:331954d002dbf5e704c7f3756028e21db07097c19722569983ba4d74df014000"}, + {file = "fonttools-4.56.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8d1613abd5af2f93c05867b3a3759a56e8bf97eb79b1da76b2bc10892f96ff16"}, + {file = "fonttools-4.56.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:705837eae384fe21cee5e5746fd4f4b2f06f87544fa60f60740007e0aa600311"}, + {file = "fonttools-4.56.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc871904a53a9d4d908673c6faa15689874af1c7c5ac403a8e12d967ebd0c0dc"}, + {file = "fonttools-4.56.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:38b947de71748bab150259ee05a775e8a0635891568e9fdb3cdd7d0e0004e62f"}, + {file = "fonttools-4.56.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:86b2a1013ef7a64d2e94606632683f07712045ed86d937c11ef4dde97319c086"}, + {file = "fonttools-4.56.0-cp310-cp310-win32.whl", hash = "sha256:133bedb9a5c6376ad43e6518b7e2cd2f866a05b1998f14842631d5feb36b5786"}, + {file = "fonttools-4.56.0-cp310-cp310-win_amd64.whl", hash = "sha256:17f39313b649037f6c800209984a11fc256a6137cbe5487091c6c7187cae4685"}, + {file = "fonttools-4.56.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:7ef04bc7827adb7532be3d14462390dd71287644516af3f1e67f1e6ff9c6d6df"}, + {file = "fonttools-4.56.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ffda9b8cd9cb8b301cae2602ec62375b59e2e2108a117746f12215145e3f786c"}, + {file = "fonttools-4.56.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2e993e8db36306cc3f1734edc8ea67906c55f98683d6fd34c3fc5593fdbba4c"}, + {file = "fonttools-4.56.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:003548eadd674175510773f73fb2060bb46adb77c94854af3e0cc5bc70260049"}, + {file = "fonttools-4.56.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:bd9825822e7bb243f285013e653f6741954d8147427aaa0324a862cdbf4cbf62"}, + {file = "fonttools-4.56.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b23d30a2c0b992fb1c4f8ac9bfde44b5586d23457759b6cf9a787f1a35179ee0"}, + {file = "fonttools-4.56.0-cp311-cp311-win32.whl", hash = "sha256:47b5e4680002ae1756d3ae3b6114e20aaee6cc5c69d1e5911f5ffffd3ee46c6b"}, + {file = "fonttools-4.56.0-cp311-cp311-win_amd64.whl", hash = "sha256:14a3e3e6b211660db54ca1ef7006401e4a694e53ffd4553ab9bc87ead01d0f05"}, + {file = "fonttools-4.56.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d6f195c14c01bd057bc9b4f70756b510e009c83c5ea67b25ced3e2c38e6ee6e9"}, + {file = "fonttools-4.56.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:fa760e5fe8b50cbc2d71884a1eff2ed2b95a005f02dda2fa431560db0ddd927f"}, + {file = "fonttools-4.56.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d54a45d30251f1d729e69e5b675f9a08b7da413391a1227781e2a297fa37f6d2"}, + {file = "fonttools-4.56.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:661a8995d11e6e4914a44ca7d52d1286e2d9b154f685a4d1f69add8418961563"}, + {file = "fonttools-4.56.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9d94449ad0a5f2a8bf5d2f8d71d65088aee48adbe45f3c5f8e00e3ad861ed81a"}, + {file = "fonttools-4.56.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f59746f7953f69cc3290ce2f971ab01056e55ddd0fb8b792c31a8acd7fee2d28"}, + {file = "fonttools-4.56.0-cp312-cp312-win32.whl", hash = "sha256:bce60f9a977c9d3d51de475af3f3581d9b36952e1f8fc19a1f2254f1dda7ce9c"}, + {file = "fonttools-4.56.0-cp312-cp312-win_amd64.whl", hash = "sha256:300c310bb725b2bdb4f5fc7e148e190bd69f01925c7ab437b9c0ca3e1c7cd9ba"}, + {file = "fonttools-4.56.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:f20e2c0dfab82983a90f3d00703ac0960412036153e5023eed2b4641d7d5e692"}, + {file = "fonttools-4.56.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f36a0868f47b7566237640c026c65a86d09a3d9ca5df1cd039e30a1da73098a0"}, + {file = "fonttools-4.56.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62b4c6802fa28e14dba010e75190e0e6228513573f1eeae57b11aa1a39b7e5b1"}, + {file = "fonttools-4.56.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a05d1f07eb0a7d755fbe01fee1fd255c3a4d3730130cf1bfefb682d18fd2fcea"}, + {file = "fonttools-4.56.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0073b62c3438cf0058488c002ea90489e8801d3a7af5ce5f7c05c105bee815c3"}, + {file = "fonttools-4.56.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e2cad98c94833465bcf28f51c248aaf07ca022efc6a3eba750ad9c1e0256d278"}, + {file = "fonttools-4.56.0-cp313-cp313-win32.whl", hash = "sha256:d0cb73ccf7f6d7ca8d0bc7ea8ac0a5b84969a41c56ac3ac3422a24df2680546f"}, + {file = "fonttools-4.56.0-cp313-cp313-win_amd64.whl", hash = "sha256:62cc1253827d1e500fde9dbe981219fea4eb000fd63402283472d38e7d8aa1c6"}, + {file = "fonttools-4.56.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:3fd3fccb7b9adaaecfa79ad51b759f2123e1aba97f857936ce044d4f029abd71"}, + {file = "fonttools-4.56.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:193b86e9f769320bc98ffdb42accafb5d0c8c49bd62884f1c0702bc598b3f0a2"}, + {file = "fonttools-4.56.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6e81c1cc80c1d8bf071356cc3e0e25071fbba1c75afc48d41b26048980b3c771"}, + {file = "fonttools-4.56.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9270505a19361e81eecdbc2c251ad1e1a9a9c2ad75fa022ccdee533f55535dc"}, + {file = "fonttools-4.56.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:53f5e9767978a4daf46f28e09dbeb7d010319924ae622f7b56174b777258e5ba"}, + {file = "fonttools-4.56.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:9da650cb29bc098b8cfd15ef09009c914b35c7986c8fa9f08b51108b7bc393b4"}, + {file = "fonttools-4.56.0-cp38-cp38-win32.whl", hash = "sha256:965d0209e6dbdb9416100123b6709cb13f5232e2d52d17ed37f9df0cc31e2b35"}, + {file = "fonttools-4.56.0-cp38-cp38-win_amd64.whl", hash = "sha256:654ac4583e2d7c62aebc6fc6a4c6736f078f50300e18aa105d87ce8925cfac31"}, + {file = "fonttools-4.56.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:ca7962e8e5fc047cc4e59389959843aafbf7445b6c08c20d883e60ced46370a5"}, + {file = "fonttools-4.56.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a1af375734018951c31c0737d04a9d5fd0a353a0253db5fbed2ccd44eac62d8c"}, + {file = "fonttools-4.56.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:442ad4122468d0e47d83bc59d0e91b474593a8c813839e1872e47c7a0cb53b10"}, + {file = "fonttools-4.56.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3cf4f8d2a30b454ac682e12c61831dcb174950c406011418e739de592bbf8f76"}, + {file = "fonttools-4.56.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:96a4271f63a615bcb902b9f56de00ea225d6896052c49f20d0c91e9f43529a29"}, + {file = "fonttools-4.56.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:6c1d38642ca2dddc7ae992ef5d026e5061a84f10ff2b906be5680ab089f55bb8"}, + {file = "fonttools-4.56.0-cp39-cp39-win32.whl", hash = "sha256:2d351275f73ebdd81dd5b09a8b8dac7a30f29a279d41e1c1192aedf1b6dced40"}, + {file = "fonttools-4.56.0-cp39-cp39-win_amd64.whl", hash = "sha256:d6ca96d1b61a707ba01a43318c9c40aaf11a5a568d1e61146fafa6ab20890793"}, + {file = "fonttools-4.56.0-py3-none-any.whl", hash = "sha256:1088182f68c303b50ca4dc0c82d42083d176cba37af1937e1a976a31149d4d14"}, + {file = "fonttools-4.56.0.tar.gz", hash = "sha256:a114d1567e1a1586b7e9e7fc2ff686ca542a82769a296cef131e4c4af51e58f4"}, ] [package.extras] @@ -2580,15 +2581,15 @@ files = [ [[package]] name = "mako" -version = "1.3.8" +version = "1.3.9" description = "A super-fast templating language that borrows the best ideas from the existing templating languages." optional = false python-versions = ">=3.8" groups = ["main"] markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ - {file = "Mako-1.3.8-py3-none-any.whl", hash = "sha256:42f48953c7eb91332040ff567eb7eea69b22e7a4affbc5ba8e845e8f730f6627"}, - {file = "mako-1.3.8.tar.gz", hash = "sha256:577b97e414580d3e088d47c2dbbe9594aa7a5146ed2875d4dfa9075af2dd3cc8"}, + {file = "Mako-1.3.9-py3-none-any.whl", hash = "sha256:95920acccb578427a9aa38e37a186b1e43156c87260d7ba18ca63aa4c7cbd3a1"}, + {file = "mako-1.3.9.tar.gz", hash = "sha256:b5d65ff3462870feec922dbccf38f6efb44e5714d7b593a656be86663d8600ac"}, ] [package.dependencies] @@ -3390,15 +3391,15 @@ files = [ [[package]] name = "optuna" -version = "4.2.0" +version = "4.2.1" description = "A hyperparameter optimization framework" optional = false python-versions = ">=3.8" groups = ["main"] markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ - {file = "optuna-4.2.0-py3-none-any.whl", hash = "sha256:539a47fda44104eb2b879c883d4640704b482df416ae99d0f24505f6e2280c28"}, - {file = "optuna-4.2.0.tar.gz", hash = "sha256:6ce226483317cf73df133d9ddf300091f946c0ad0dbdbc50b28891049b8400f2"}, + {file = "optuna-4.2.1-py3-none-any.whl", hash = "sha256:6d38199013441d3f70fac27136e05c0188c5f4ec3848db708ac311cbdeb30dbf"}, + {file = "optuna-4.2.1.tar.gz", hash = "sha256:2ecd74cdc8aaf5dda1f2b9e267999bab21def9a33e0a4f415ecae0c468c401e0"}, ] [package.dependencies] @@ -4586,7 +4587,7 @@ scipy = "^1.10.1" type = "git" url = "https://github.com/qiboteam/qibojit.git" reference = "HEAD" -resolved_reference = "cb89902d0378cf2d75861a5c9998d395411f598b" +resolved_reference = "6f9f63ad8259d7bddc14d280deb61a463d618b25" [[package]] name = "qiboml" @@ -4633,7 +4634,7 @@ cuda = ["cupy-cuda11x (>=11.6.0,<12.0.0)", "cuquantum-python-cu11 (>=23.3.0,<24. type = "git" url = "https://github.com/qiboteam/qibotn.git" reference = "HEAD" -resolved_reference = "820ddbdff509a8296f52dcb7b103eb6a391ab021" +resolved_reference = "5f9df4591ccd97911ee6123d94ca2664be370158" [[package]] name = "quimb" @@ -4866,7 +4867,6 @@ files = [ {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f66efbc1caa63c088dead1c4170d148eabc9b80d95fb75b6c92ac0aad2437d76"}, {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:22353049ba4181685023b25b5b51a574bce33e7f51c759371a7422dcae5402a6"}, {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:932205970b9f9991b34f55136be327501903f7c66830e9760a8ffb15b07f05cd"}, - {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a52d48f4e7bf9005e8f0a89209bf9a73f7190ddf0489eee5eb51377385f59f2a"}, {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-win32.whl", hash = "sha256:3eac5a91891ceb88138c113f9db04f3cebdae277f5d44eaa3651a4f573e6a5da"}, {file = "ruamel.yaml.clib-0.2.12-cp310-cp310-win_amd64.whl", hash = "sha256:ab007f2f5a87bd08ab1499bdf96f3d5c6ad4dcfa364884cb4549aa0154b13a28"}, {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:4a6679521a58256a90b0d89e03992c15144c5f3858f40d7c18886023d7943db6"}, @@ -4875,7 +4875,6 @@ files = [ {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:811ea1594b8a0fb466172c384267a4e5e367298af6b228931f273b111f17ef52"}, {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:cf12567a7b565cbf65d438dec6cfbe2917d3c1bdddfce84a9930b7d35ea59642"}, {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7dd5adc8b930b12c8fc5b99e2d535a09889941aa0d0bd06f4749e9a9397c71d2"}, - {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1492a6051dab8d912fc2adeef0e8c72216b24d57bd896ea607cb90bb0c4981d3"}, {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-win32.whl", hash = "sha256:bd0a08f0bab19093c54e18a14a10b4322e1eacc5217056f3c063bd2f59853ce4"}, {file = "ruamel.yaml.clib-0.2.12-cp311-cp311-win_amd64.whl", hash = "sha256:a274fb2cb086c7a3dea4322ec27f4cb5cc4b6298adb583ab0e211a4682f241eb"}, {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:20b0f8dc160ba83b6dcc0e256846e1a02d044e13f7ea74a3d1d56ede4e48c632"}, @@ -4884,7 +4883,6 @@ files = [ {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:749c16fcc4a2b09f28843cda5a193e0283e47454b63ec4b81eaa2242f50e4ccd"}, {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bf165fef1f223beae7333275156ab2022cffe255dcc51c27f066b4370da81e31"}, {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:32621c177bbf782ca5a18ba4d7af0f1082a3f6e517ac2a18b3974d4edf349680"}, - {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b82a7c94a498853aa0b272fd5bc67f29008da798d4f93a2f9f289feb8426a58d"}, {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-win32.whl", hash = "sha256:e8c4ebfcfd57177b572e2040777b8abc537cdef58a2120e830124946aa9b42c5"}, {file = "ruamel.yaml.clib-0.2.12-cp312-cp312-win_amd64.whl", hash = "sha256:0467c5965282c62203273b838ae77c0d29d7638c8a4e3a1c8bdd3602c10904e4"}, {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:4c8c5d82f50bb53986a5e02d1b3092b03622c02c2eb78e29bec33fd9593bae1a"}, @@ -4893,7 +4891,6 @@ files = [ {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:96777d473c05ee3e5e3c3e999f5d23c6f4ec5b0c38c098b3a5229085f74236c6"}, {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:3bc2a80e6420ca8b7d3590791e2dfc709c88ab9152c00eeb511c9875ce5778bf"}, {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:e188d2699864c11c36cdfdada94d781fd5d6b0071cd9c427bceb08ad3d7c70e1"}, - {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4f6f3eac23941b32afccc23081e1f50612bdbe4e982012ef4f5797986828cd01"}, {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-win32.whl", hash = "sha256:6442cb36270b3afb1b4951f060eccca1ce49f3d087ca1ca4563a6eb479cb3de6"}, {file = "ruamel.yaml.clib-0.2.12-cp313-cp313-win_amd64.whl", hash = "sha256:e5b8daf27af0b90da7bb903a876477a9e6d7270be6146906b276605997c7e9a3"}, {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:fc4b630cd3fa2cf7fce38afa91d7cfe844a9f75d7f0f36393fa98815e911d987"}, @@ -4902,7 +4899,6 @@ files = [ {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e2f1c3765db32be59d18ab3953f43ab62a761327aafc1594a2a1fbe038b8b8a7"}, {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d85252669dc32f98ebcd5d36768f5d4faeaeaa2d655ac0473be490ecdae3c285"}, {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e143ada795c341b56de9418c58d028989093ee611aa27ffb9b7f609c00d813ed"}, - {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2c59aa6170b990d8d2719323e628aaf36f3bfbc1c26279c0eeeb24d05d2d11c7"}, {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-win32.whl", hash = "sha256:beffaed67936fbbeffd10966a4eb53c402fafd3d6833770516bf7314bc6ffa12"}, {file = "ruamel.yaml.clib-0.2.12-cp39-cp39-win_amd64.whl", hash = "sha256:040ae85536960525ea62868b642bdb0c2cc6021c9f9d507810c0c604e66f5a7b"}, {file = "ruamel.yaml.clib-0.2.12.tar.gz", hash = "sha256:6c8fbb13ec503f99a91901ab46e0b07ae7941cd527393187039aec586fdfd36f"}, @@ -5316,70 +5312,70 @@ test = ["pytest"] [[package]] name = "sqlalchemy" -version = "2.0.37" +version = "2.0.38" description = "Database Abstraction Library" optional = false python-versions = ">=3.7" groups = ["main"] markers = "python_version <= \"3.11\" or python_version >= \"3.12\"" files = [ - {file = "SQLAlchemy-2.0.37-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:da36c3b0e891808a7542c5c89f224520b9a16c7f5e4d6a1156955605e54aef0e"}, - {file = "SQLAlchemy-2.0.37-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e7402ff96e2b073a98ef6d6142796426d705addd27b9d26c3b32dbaa06d7d069"}, - {file = "SQLAlchemy-2.0.37-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6f5d254a22394847245f411a2956976401e84da4288aa70cbcd5190744062c1"}, - {file = "SQLAlchemy-2.0.37-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:41296bbcaa55ef5fdd32389a35c710133b097f7b2609d8218c0eabded43a1d84"}, - {file = "SQLAlchemy-2.0.37-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:bedee60385c1c0411378cbd4dc486362f5ee88deceea50002772912d798bb00f"}, - {file = "SQLAlchemy-2.0.37-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:6c67415258f9f3c69867ec02fea1bf6508153709ecbd731a982442a590f2b7e4"}, - {file = "SQLAlchemy-2.0.37-cp310-cp310-win32.whl", hash = "sha256:650dcb70739957a492ad8acff65d099a9586b9b8920e3507ca61ec3ce650bb72"}, - {file = "SQLAlchemy-2.0.37-cp310-cp310-win_amd64.whl", hash = "sha256:93d1543cd8359040c02b6614421c8e10cd7a788c40047dbc507ed46c29ae5636"}, - {file = "SQLAlchemy-2.0.37-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:78361be6dc9073ed17ab380985d1e45e48a642313ab68ab6afa2457354ff692c"}, - {file = "SQLAlchemy-2.0.37-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b661b49d0cb0ab311a189b31e25576b7ac3e20783beb1e1817d72d9d02508bf5"}, - {file = "SQLAlchemy-2.0.37-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d57bafbab289e147d064ffbd5cca2d7b1394b63417c0636cea1f2e93d16eb9e8"}, - {file = "SQLAlchemy-2.0.37-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fa2c0913f02341d25fb858e4fb2031e6b0813494cca1ba07d417674128ce11b"}, - {file = "SQLAlchemy-2.0.37-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:9df21b8d9e5c136ea6cde1c50d2b1c29a2b5ff2b1d610165c23ff250e0704087"}, - {file = "SQLAlchemy-2.0.37-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:db18ff6b8c0f1917f8b20f8eca35c28bbccb9f83afa94743e03d40203ed83de9"}, - {file = "SQLAlchemy-2.0.37-cp311-cp311-win32.whl", hash = "sha256:46954173612617a99a64aee103bcd3f078901b9a8dcfc6ae80cbf34ba23df989"}, - {file = "SQLAlchemy-2.0.37-cp311-cp311-win_amd64.whl", hash = "sha256:7b7e772dc4bc507fdec4ee20182f15bd60d2a84f1e087a8accf5b5b7a0dcf2ba"}, - {file = "SQLAlchemy-2.0.37-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:2952748ecd67ed3b56773c185e85fc084f6bdcdec10e5032a7c25a6bc7d682ef"}, - {file = "SQLAlchemy-2.0.37-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3151822aa1db0eb5afd65ccfafebe0ef5cda3a7701a279c8d0bf17781a793bb4"}, - {file = "SQLAlchemy-2.0.37-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eaa8039b6d20137a4e02603aba37d12cd2dde7887500b8855356682fc33933f4"}, - {file = "SQLAlchemy-2.0.37-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1cdba1f73b64530c47b27118b7053b8447e6d6f3c8104e3ac59f3d40c33aa9fd"}, - {file = "SQLAlchemy-2.0.37-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1b2690456528a87234a75d1a1644cdb330a6926f455403c8e4f6cad6921f9098"}, - {file = "SQLAlchemy-2.0.37-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:cf5ae8a9dcf657fd72144a7fd01f243236ea39e7344e579a121c4205aedf07bb"}, - {file = "SQLAlchemy-2.0.37-cp312-cp312-win32.whl", hash = "sha256:ea308cec940905ba008291d93619d92edaf83232ec85fbd514dcb329f3192761"}, - {file = "SQLAlchemy-2.0.37-cp312-cp312-win_amd64.whl", hash = "sha256:635d8a21577341dfe4f7fa59ec394b346da12420b86624a69e466d446de16aff"}, - {file = "SQLAlchemy-2.0.37-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8c4096727193762e72ce9437e2a86a110cf081241919ce3fab8e89c02f6b6658"}, - {file = "SQLAlchemy-2.0.37-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e4fb5ac86d8fe8151966814f6720996430462e633d225497566b3996966b9bdb"}, - {file = "SQLAlchemy-2.0.37-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e56a139bfe136a22c438478a86f8204c1eb5eed36f4e15c4224e4b9db01cb3e4"}, - {file = "SQLAlchemy-2.0.37-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2f95fc8e3f34b5f6b3effb49d10ac97c569ec8e32f985612d9b25dd12d0d2e94"}, - {file = "SQLAlchemy-2.0.37-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c505edd429abdfe3643fa3b2e83efb3445a34a9dc49d5f692dd087be966020e0"}, - {file = "SQLAlchemy-2.0.37-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:12b0f1ec623cccf058cf21cb544f0e74656618165b083d78145cafde156ea7b6"}, - {file = "SQLAlchemy-2.0.37-cp313-cp313-win32.whl", hash = "sha256:293f9ade06b2e68dd03cfb14d49202fac47b7bb94bffcff174568c951fbc7af2"}, - {file = "SQLAlchemy-2.0.37-cp313-cp313-win_amd64.whl", hash = "sha256:d70f53a0646cc418ca4853da57cf3ddddbccb8c98406791f24426f2dd77fd0e2"}, - {file = "SQLAlchemy-2.0.37-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:44f569d0b1eb82301b92b72085583277316e7367e038d97c3a1a899d9a05e342"}, - {file = "SQLAlchemy-2.0.37-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2eae3423e538c10d93ae3e87788c6a84658c3ed6db62e6a61bb9495b0ad16bb"}, - {file = "SQLAlchemy-2.0.37-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dfff7be361048244c3aa0f60b5e63221c5e0f0e509f4e47b8910e22b57d10ae7"}, - {file = "SQLAlchemy-2.0.37-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:5bc3339db84c5fb9130ac0e2f20347ee77b5dd2596ba327ce0d399752f4fce39"}, - {file = "SQLAlchemy-2.0.37-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:84b9f23b0fa98a6a4b99d73989350a94e4a4ec476b9a7dfe9b79ba5939f5e80b"}, - {file = "SQLAlchemy-2.0.37-cp37-cp37m-win32.whl", hash = "sha256:51bc9cfef83e0ac84f86bf2b10eaccb27c5a3e66a1212bef676f5bee6ef33ebb"}, - {file = "SQLAlchemy-2.0.37-cp37-cp37m-win_amd64.whl", hash = "sha256:8e47f1af09444f87c67b4f1bb6231e12ba6d4d9f03050d7fc88df6d075231a49"}, - {file = "SQLAlchemy-2.0.37-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6b788f14c5bb91db7f468dcf76f8b64423660a05e57fe277d3f4fad7b9dcb7ce"}, - {file = "SQLAlchemy-2.0.37-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:521ef85c04c33009166777c77e76c8a676e2d8528dc83a57836b63ca9c69dcd1"}, - {file = "SQLAlchemy-2.0.37-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:75311559f5c9881a9808eadbeb20ed8d8ba3f7225bef3afed2000c2a9f4d49b9"}, - {file = "SQLAlchemy-2.0.37-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cce918ada64c956b62ca2c2af59b125767097ec1dca89650a6221e887521bfd7"}, - {file = "SQLAlchemy-2.0.37-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:9d087663b7e1feabea8c578d6887d59bb00388158e8bff3a76be11aa3f748ca2"}, - {file = "SQLAlchemy-2.0.37-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:cf95a60b36997dad99692314c4713f141b61c5b0b4cc5c3426faad570b31ca01"}, - {file = "SQLAlchemy-2.0.37-cp38-cp38-win32.whl", hash = "sha256:d75ead7dd4d255068ea0f21492ee67937bd7c90964c8f3c2bea83c7b7f81b95f"}, - {file = "SQLAlchemy-2.0.37-cp38-cp38-win_amd64.whl", hash = "sha256:74bbd1d0a9bacf34266a7907d43260c8d65d31d691bb2356f41b17c2dca5b1d0"}, - {file = "SQLAlchemy-2.0.37-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:648ec5acf95ad59255452ef759054f2176849662af4521db6cb245263ae4aa33"}, - {file = "SQLAlchemy-2.0.37-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:35bd2df269de082065d4b23ae08502a47255832cc3f17619a5cea92ce478b02b"}, - {file = "SQLAlchemy-2.0.37-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4f581d365af9373a738c49e0c51e8b18e08d8a6b1b15cc556773bcd8a192fa8b"}, - {file = "SQLAlchemy-2.0.37-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:82df02816c14f8dc9f4d74aea4cb84a92f4b0620235daa76dde002409a3fbb5a"}, - {file = "SQLAlchemy-2.0.37-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:94b564e38b344d3e67d2e224f0aec6ba09a77e4582ced41e7bfd0f757d926ec9"}, - {file = "SQLAlchemy-2.0.37-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:955a2a765aa1bd81aafa69ffda179d4fe3e2a3ad462a736ae5b6f387f78bfeb8"}, - {file = "SQLAlchemy-2.0.37-cp39-cp39-win32.whl", hash = "sha256:03f0528c53ca0b67094c4764523c1451ea15959bbf0a8a8a3096900014db0278"}, - {file = "SQLAlchemy-2.0.37-cp39-cp39-win_amd64.whl", hash = "sha256:4b12885dc85a2ab2b7d00995bac6d967bffa8594123b02ed21e8eb2205a7584b"}, - {file = "SQLAlchemy-2.0.37-py3-none-any.whl", hash = "sha256:a8998bf9f8658bd3839cbc44ddbe982955641863da0c1efe5b00c1ab4f5c16b1"}, - {file = "sqlalchemy-2.0.37.tar.gz", hash = "sha256:12b28d99a9c14eaf4055810df1001557176716de0167b91026e648e65229bffb"}, + {file = "SQLAlchemy-2.0.38-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5e1d9e429028ce04f187a9f522818386c8b076723cdbe9345708384f49ebcec6"}, + {file = "SQLAlchemy-2.0.38-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b87a90f14c68c925817423b0424381f0e16d80fc9a1a1046ef202ab25b19a444"}, + {file = "SQLAlchemy-2.0.38-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:402c2316d95ed90d3d3c25ad0390afa52f4d2c56b348f212aa9c8d072a40eee5"}, + {file = "SQLAlchemy-2.0.38-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6493bc0eacdbb2c0f0d260d8988e943fee06089cd239bd7f3d0c45d1657a70e2"}, + {file = "SQLAlchemy-2.0.38-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0561832b04c6071bac3aad45b0d3bb6d2c4f46a8409f0a7a9c9fa6673b41bc03"}, + {file = "SQLAlchemy-2.0.38-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:49aa2cdd1e88adb1617c672a09bf4ebf2f05c9448c6dbeba096a3aeeb9d4d443"}, + {file = "SQLAlchemy-2.0.38-cp310-cp310-win32.whl", hash = "sha256:64aa8934200e222f72fcfd82ee71c0130a9c07d5725af6fe6e919017d095b297"}, + {file = "SQLAlchemy-2.0.38-cp310-cp310-win_amd64.whl", hash = "sha256:c57b8e0841f3fce7b703530ed70c7c36269c6d180ea2e02e36b34cb7288c50c7"}, + {file = "SQLAlchemy-2.0.38-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:bf89e0e4a30714b357f5d46b6f20e0099d38b30d45fa68ea48589faf5f12f62d"}, + {file = "SQLAlchemy-2.0.38-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8455aa60da49cb112df62b4721bd8ad3654a3a02b9452c783e651637a1f21fa2"}, + {file = "SQLAlchemy-2.0.38-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f53c0d6a859b2db58332e0e6a921582a02c1677cc93d4cbb36fdf49709b327b2"}, + {file = "SQLAlchemy-2.0.38-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3c4817dff8cef5697f5afe5fec6bc1783994d55a68391be24cb7d80d2dbc3a6"}, + {file = "SQLAlchemy-2.0.38-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c9cea5b756173bb86e2235f2f871b406a9b9d722417ae31e5391ccaef5348f2c"}, + {file = "SQLAlchemy-2.0.38-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:40e9cdbd18c1f84631312b64993f7d755d85a3930252f6276a77432a2b25a2f3"}, + {file = "SQLAlchemy-2.0.38-cp311-cp311-win32.whl", hash = "sha256:cb39ed598aaf102251483f3e4675c5dd6b289c8142210ef76ba24aae0a8f8aba"}, + {file = "SQLAlchemy-2.0.38-cp311-cp311-win_amd64.whl", hash = "sha256:f9d57f1b3061b3e21476b0ad5f0397b112b94ace21d1f439f2db472e568178ae"}, + {file = "SQLAlchemy-2.0.38-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:12d5b06a1f3aeccf295a5843c86835033797fea292c60e72b07bcb5d820e6dd3"}, + {file = "SQLAlchemy-2.0.38-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:e036549ad14f2b414c725349cce0772ea34a7ab008e9cd67f9084e4f371d1f32"}, + {file = "SQLAlchemy-2.0.38-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee3bee874cb1fadee2ff2b79fc9fc808aa638670f28b2145074538d4a6a5028e"}, + {file = "SQLAlchemy-2.0.38-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e185ea07a99ce8b8edfc788c586c538c4b1351007e614ceb708fd01b095ef33e"}, + {file = "SQLAlchemy-2.0.38-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b79ee64d01d05a5476d5cceb3c27b5535e6bb84ee0f872ba60d9a8cd4d0e6579"}, + {file = "SQLAlchemy-2.0.38-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:afd776cf1ebfc7f9aa42a09cf19feadb40a26366802d86c1fba080d8e5e74bdd"}, + {file = "SQLAlchemy-2.0.38-cp312-cp312-win32.whl", hash = "sha256:a5645cd45f56895cfe3ca3459aed9ff2d3f9aaa29ff7edf557fa7a23515a3725"}, + {file = "SQLAlchemy-2.0.38-cp312-cp312-win_amd64.whl", hash = "sha256:1052723e6cd95312f6a6eff9a279fd41bbae67633415373fdac3c430eca3425d"}, + {file = "SQLAlchemy-2.0.38-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ecef029b69843b82048c5b347d8e6049356aa24ed644006c9a9d7098c3bd3bfd"}, + {file = "SQLAlchemy-2.0.38-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9c8bcad7fc12f0cc5896d8e10fdf703c45bd487294a986903fe032c72201596b"}, + {file = "SQLAlchemy-2.0.38-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a0ef3f98175d77180ffdc623d38e9f1736e8d86b6ba70bff182a7e68bed7727"}, + {file = "SQLAlchemy-2.0.38-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b0ac78898c50e2574e9f938d2e5caa8fe187d7a5b69b65faa1ea4648925b096"}, + {file = "SQLAlchemy-2.0.38-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9eb4fa13c8c7a2404b6a8e3772c17a55b1ba18bc711e25e4d6c0c9f5f541b02a"}, + {file = "SQLAlchemy-2.0.38-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5dba1cdb8f319084f5b00d41207b2079822aa8d6a4667c0f369fce85e34b0c86"}, + {file = "SQLAlchemy-2.0.38-cp313-cp313-win32.whl", hash = "sha256:eae27ad7580529a427cfdd52c87abb2dfb15ce2b7a3e0fc29fbb63e2ed6f8120"}, + {file = "SQLAlchemy-2.0.38-cp313-cp313-win_amd64.whl", hash = "sha256:b335a7c958bc945e10c522c069cd6e5804f4ff20f9a744dd38e748eb602cbbda"}, + {file = "SQLAlchemy-2.0.38-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:40310db77a55512a18827488e592965d3dec6a3f1e3d8af3f8243134029daca3"}, + {file = "SQLAlchemy-2.0.38-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d3043375dd5bbcb2282894cbb12e6c559654c67b5fffb462fda815a55bf93f7"}, + {file = "SQLAlchemy-2.0.38-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70065dfabf023b155a9c2a18f573e47e6ca709b9e8619b2e04c54d5bcf193178"}, + {file = "SQLAlchemy-2.0.38-cp37-cp37m-musllinux_1_2_aarch64.whl", hash = "sha256:c058b84c3b24812c859300f3b5abf300daa34df20d4d4f42e9652a4d1c48c8a4"}, + {file = "SQLAlchemy-2.0.38-cp37-cp37m-musllinux_1_2_x86_64.whl", hash = "sha256:0398361acebb42975deb747a824b5188817d32b5c8f8aba767d51ad0cc7bb08d"}, + {file = "SQLAlchemy-2.0.38-cp37-cp37m-win32.whl", hash = "sha256:a2bc4e49e8329f3283d99840c136ff2cd1a29e49b5624a46a290f04dff48e079"}, + {file = "SQLAlchemy-2.0.38-cp37-cp37m-win_amd64.whl", hash = "sha256:9cd136184dd5f58892f24001cdce986f5d7e96059d004118d5410671579834a4"}, + {file = "SQLAlchemy-2.0.38-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:665255e7aae5f38237b3a6eae49d2358d83a59f39ac21036413fab5d1e810578"}, + {file = "SQLAlchemy-2.0.38-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:92f99f2623ff16bd4aaf786ccde759c1f676d39c7bf2855eb0b540e1ac4530c8"}, + {file = "SQLAlchemy-2.0.38-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aa498d1392216fae47eaf10c593e06c34476ced9549657fca713d0d1ba5f7248"}, + {file = "SQLAlchemy-2.0.38-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a9afbc3909d0274d6ac8ec891e30210563b2c8bdd52ebbda14146354e7a69373"}, + {file = "SQLAlchemy-2.0.38-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:57dd41ba32430cbcc812041d4de8d2ca4651aeefad2626921ae2a23deb8cd6ff"}, + {file = "SQLAlchemy-2.0.38-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:3e35d5565b35b66905b79ca4ae85840a8d40d31e0b3e2990f2e7692071b179ca"}, + {file = "SQLAlchemy-2.0.38-cp38-cp38-win32.whl", hash = "sha256:f0d3de936b192980209d7b5149e3c98977c3810d401482d05fb6d668d53c1c63"}, + {file = "SQLAlchemy-2.0.38-cp38-cp38-win_amd64.whl", hash = "sha256:3868acb639c136d98107c9096303d2d8e5da2880f7706f9f8c06a7f961961149"}, + {file = "SQLAlchemy-2.0.38-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:07258341402a718f166618470cde0c34e4cec85a39767dce4e24f61ba5e667ea"}, + {file = "SQLAlchemy-2.0.38-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0a826f21848632add58bef4f755a33d45105d25656a0c849f2dc2df1c71f6f50"}, + {file = "SQLAlchemy-2.0.38-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:386b7d136919bb66ced64d2228b92d66140de5fefb3c7df6bd79069a269a7b06"}, + {file = "SQLAlchemy-2.0.38-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2f2951dc4b4f990a4b394d6b382accb33141d4d3bd3ef4e2b27287135d6bdd68"}, + {file = "SQLAlchemy-2.0.38-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:8bf312ed8ac096d674c6aa9131b249093c1b37c35db6a967daa4c84746bc1bc9"}, + {file = "SQLAlchemy-2.0.38-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:6db316d6e340f862ec059dc12e395d71f39746a20503b124edc255973977b728"}, + {file = "SQLAlchemy-2.0.38-cp39-cp39-win32.whl", hash = "sha256:c09a6ea87658695e527104cf857c70f79f14e9484605e205217aae0ec27b45fc"}, + {file = "SQLAlchemy-2.0.38-cp39-cp39-win_amd64.whl", hash = "sha256:12f5c9ed53334c3ce719155424dc5407aaa4f6cadeb09c5b627e06abb93933a1"}, + {file = "SQLAlchemy-2.0.38-py3-none-any.whl", hash = "sha256:63178c675d4c80def39f1febd625a6333f44c0ba269edd8a468b156394b27753"}, + {file = "sqlalchemy-2.0.38.tar.gz", hash = "sha256:e5a4d82bdb4bf1ac1285a68eab02d253ab73355d9f0fe725a97e1e0fa689decb"}, ] [package.dependencies] diff --git a/pyproject.toml b/pyproject.toml index e4af7fc956..79e7335ffa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -56,7 +56,7 @@ ipython = "^8.10.0" qulacs = { version = "^0.6.4", markers = "(sys_platform == 'darwin' and python_version > '3.9') or sys_platform != 'darwin'" } seaborn = "^0.13.2" ipykernel = "^6.29.4" -qibojit = { git = "https://github.com/qiboteam/qibojit.git"} +qibojit = { git = "https://github.com/qiboteam/qibojit.git" } [tool.poetry.group.tests] optional = true @@ -70,7 +70,7 @@ pytest-cov = "^4.0.0" pylint = "3.1.0" matplotlib = "^3.7.0" torch = "^2.1.1,<2.4" -qibojit = { git = "https://github.com/qiboteam/qibojit.git"} +qibojit = { git = "https://github.com/qiboteam/qibojit.git" } qibotn = { git = "https://github.com/qiboteam/qibotn.git" } qiboml = { git = "https://github.com/qiboteam/qiboml.git" } stim = "^1.12.0" @@ -101,7 +101,7 @@ optional = true [tool.poetry.group.cuda12.dependencies] cupy-cuda12x = "^13.1.0" cuquantum-python-cu12 = "^23.3.0" -qibojit = { git = "https://github.com/qiboteam/qibojit.git"} +qibojit = { git = "https://github.com/qiboteam/qibojit.git" } qibotn = { git = "https://github.com/qiboteam/qibotn.git" } [tool.poetry.extras] diff --git a/src/qibo/hamiltonians/__init__.py b/src/qibo/hamiltonians/__init__.py index 35c2673e32..f91e1e8bc0 100644 --- a/src/qibo/hamiltonians/__init__.py +++ b/src/qibo/hamiltonians/__init__.py @@ -1,6 +1,2 @@ -from qibo.hamiltonians.hamiltonians import ( - Hamiltonian, - SymbolicHamiltonian, - TrotterHamiltonian, -) +from qibo.hamiltonians.hamiltonians import Hamiltonian, SymbolicHamiltonian from qibo.hamiltonians.models import TFIM, XXX, XXZ, Heisenberg, MaxCut, X, Y, Z diff --git a/src/qibo/hamiltonians/hamiltonians.py b/src/qibo/hamiltonians/hamiltonians.py index 5bc78f5d30..7eaa0a9472 100644 --- a/src/qibo/hamiltonians/hamiltonians.py +++ b/src/qibo/hamiltonians/hamiltonians.py @@ -1,5 +1,7 @@ """Module defining Hamiltonian classes.""" +import operator +from functools import cache, cached_property, reduce from itertools import chain from math import prod from typing import Optional @@ -7,9 +9,11 @@ import numpy as np import sympy -from qibo.config import EINSUM_CHARS, log, raise_error +from qibo.backends import Backend, _check_backend +from qibo.config import log, raise_error from qibo.hamiltonians.abstract import AbstractHamiltonian -from qibo.symbols import Z +from qibo.hamiltonians.terms import SymbolicTerm +from qibo.symbols import Symbol, Z class Hamiltonian(AbstractHamiltonian): @@ -68,34 +72,6 @@ def matrix(self, mat): ) self._matrix = mat - @classmethod - def from_symbolic(cls, symbolic_hamiltonian, symbol_map, backend=None): - """Creates a :class:`qibo.hamiltonian.Hamiltonian` from a symbolic Hamiltonian. - - We refer to :ref:`How to define custom Hamiltonians using symbols? ` - for more details. - - Args: - symbolic_hamiltonian (sympy.Expr): full Hamiltonian written with ``sympy`` symbols. - symbol_map (dict): Dictionary that maps each symbol that appears in - the Hamiltonian to a pair ``(target, matrix)``. - 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: - :class:`qibo.hamiltonians.SymbolicHamiltonian`: object that implements the - Hamiltonian represented by the given symbolic expression. - """ - log.warning( - "`Hamiltonian.from_symbolic` and the use of symbol maps is " - "deprecated. Please use `SymbolicHamiltonian` and Qibo symbols " - "to construct Hamiltonians using symbols." - ) - return SymbolicHamiltonian( - symbolic_hamiltonian, symbol_map=symbol_map, backend=backend - ) - def eigenvalues(self, k=6): if self._eigenvalues is None: self._eigenvalues = self.backend.calculate_eigenvalues(self.matrix, k) @@ -198,98 +174,118 @@ def energy_fluctuation(self, state): average_h2 = self.backend.calculate_expectation_state(h2, state, normalize=True) return self.backend.np.sqrt(self.backend.np.abs(average_h2 - energy**2)) - def __add__(self, o): - if isinstance(o, self.__class__): - if self.nqubits != o.nqubits: + def __add__(self, other): + if isinstance(other, self.__class__): + if self.nqubits != other.nqubits: raise_error( RuntimeError, "Only hamiltonians with the same number of qubits can be added.", ) - new_matrix = self.matrix + o.matrix - elif isinstance(o, self.backend.numeric_types): - new_matrix = self.matrix + o * self.eye() + new_matrix = self.matrix + other.matrix + elif isinstance(other, self.backend.numeric_types) or isinstance( + other, self.backend.tensor_types + ): + new_matrix = self.matrix + other * self.eye() else: raise_error( NotImplementedError, - f"Hamiltonian addition to {type(o)} not implemented.", + f"Hamiltonian addition to {type(other)} not implemented.", ) return self.__class__(self.nqubits, new_matrix, backend=self.backend) - def __sub__(self, o): - if isinstance(o, self.__class__): - if self.nqubits != o.nqubits: + def __sub__(self, other): + if isinstance(other, self.__class__): + if self.nqubits != other.nqubits: raise_error( RuntimeError, "Only hamiltonians with the same number of qubits can be subtracted.", ) - new_matrix = self.matrix - o.matrix - elif isinstance(o, self.backend.numeric_types): - new_matrix = self.matrix - o * self.eye() + new_matrix = self.matrix - other.matrix + elif isinstance(other, self.backend.numeric_types): + new_matrix = self.matrix - other * self.eye() else: raise_error( NotImplementedError, - f"Hamiltonian subtraction to {type(o)} not implemented.", + f"Hamiltonian subtraction to {type(other)} not implemented.", ) return self.__class__(self.nqubits, new_matrix, backend=self.backend) - def __rsub__(self, o): - if isinstance(o, self.__class__): # pragma: no cover + def __rsub__(self, other): + if isinstance(other, self.__class__): # pragma: no cover # impractical case because it will be handled by `__sub__` - if self.nqubits != o.nqubits: + if self.nqubits != other.nqubits: raise_error( RuntimeError, "Only hamiltonians with the same number of qubits can be added.", ) - new_matrix = o.matrix - self.matrix - elif isinstance(o, self.backend.numeric_types): - new_matrix = o * self.eye() - self.matrix + new_matrix = other.matrix - self.matrix + elif isinstance(other, self.backend.numeric_types): + new_matrix = other * self.eye() - self.matrix else: raise_error( NotImplementedError, - f"Hamiltonian subtraction to {type(o)} not implemented.", + f"Hamiltonian subtraction to {type(other)} not implemented.", ) return self.__class__(self.nqubits, new_matrix, backend=self.backend) - def __mul__(self, o): - if isinstance(o, self.backend.tensor_types): - o = complex(o) - elif not isinstance(o, self.backend.numeric_types): + def __mul__(self, other): + if isinstance(other, self.backend.tensor_types): + other = complex(other) + elif not isinstance(other, self.backend.numeric_types): raise_error( NotImplementedError, - f"Hamiltonian multiplication to {type(o)} not implemented.", + f"Hamiltonian multiplication to {type(other)} not implemented.", ) - new_matrix = self.matrix * o + new_matrix = self.matrix * other r = self.__class__(self.nqubits, new_matrix, backend=self.backend) - o = self.backend.cast(o) + other = self.backend.cast(other) if self._eigenvalues is not None: - if self.backend.np.real(o) >= 0: # TODO: check for side effects K.qnp - r._eigenvalues = o * self._eigenvalues + if self.backend.np.real(other) >= 0: # TODO: check for side effects K.qnp + r._eigenvalues = other * self._eigenvalues elif not self.backend.is_sparse(self.matrix): axis = (0,) if (self.backend.platform == "pytorch") else 0 - r._eigenvalues = o * self.backend.np.flip(self._eigenvalues, axis) + r._eigenvalues = other * self.backend.np.flip(self._eigenvalues, axis) if self._eigenvectors is not None: - if self.backend.np.real(o) > 0: # TODO: see above + if self.backend.np.real(other) > 0: # TODO: see above r._eigenvectors = self._eigenvectors - elif o == 0: + elif other == 0: r._eigenvectors = self.eye(int(self._eigenvectors.shape[0])) return r - def __matmul__(self, o): - if isinstance(o, self.__class__): + def __matmul__(self, other): + if isinstance(other, self.__class__): matrix = self.backend.calculate_hamiltonian_matrix_product( - self.matrix, o.matrix + self.matrix, other.matrix ) return self.__class__(self.nqubits, matrix, backend=self.backend) - if isinstance(o, self.backend.tensor_types): - return self.backend.calculate_hamiltonian_state_product(self.matrix, o) + if isinstance(other, self.backend.tensor_types): + return self.backend.calculate_hamiltonian_state_product(self.matrix, other) raise_error( NotImplementedError, - f"Hamiltonian matmul to {type(o)} not implemented.", + f"Hamiltonian matmul to {type(other)} not implemented.", ) +def _calculate_nqubits_from_form(form): + """Calculate number of qubits in the system described by the given + Hamiltonian formula + """ + nqubits = 0 + for symbol in form.free_symbols: + if isinstance(symbol, Symbol): + q = symbol.target_qubit + else: + raise_error( + RuntimeError, + f"Symbol {symbol} is not a ``qibo.symbols.Symbol``, you can define a custom symbol for {symbol} by subclassing ``qibo.symbols.Symbol``.", + ) + if q > nqubits: + nqubits = q + return nqubits + 1 + + class SymbolicHamiltonian(AbstractHamiltonian): """Hamiltonian based on a symbolic representation. @@ -309,60 +305,36 @@ class SymbolicHamiltonian(AbstractHamiltonian): Hamiltonian should be written using Qibo symbols. See :ref:`How to define custom Hamiltonians using symbols? ` example for more details. - symbol_map (dict): Dictionary that maps each ``sympy.Symbol`` to a tuple - of (target qubit, matrix representation). This feature is kept for - compatibility with older versions where Qibo symbols were not available - and may be deprecated in the future. - It is not required if the Hamiltonian is constructed using Qibo symbols. - The symbol_map can also be used to pass non-quantum operator arguments - to the symbolic Hamiltonian, such as the parameters in the - :meth:`qibo.hamiltonians.models.MaxCut` Hamiltonian. backend (:class:`qibo.backends.abstract.Backend`, optional): backend to be used in the execution. If ``None``, it uses the current backend. Defaults to ``None``. """ - def __init__(self, form=None, nqubits=None, symbol_map={}, backend=None): + def __init__( + self, + form: sympy.Expr, + nqubits: Optional[int] = None, + backend: Optional[Backend] = None, + ): super().__init__() - self._form = None - self._terms = None + if not isinstance(form, sympy.Expr): + raise_error( + TypeError, + f"The ``form`` of a ``SymbolicHamiltonian`` has to be a ``sympy.Expr``, but a ``{type(form)}`` was passed.", + ) + self._form = form self.constant = 0 # used only when we perform calculations using ``_terms`` - self._dense = None - self.symbol_map = symbol_map - # if a symbol in the given form is not a Qibo symbol it must be - # included in the ``symbol_map`` - - from qibo.symbols import Symbol # pylint: disable=import-outside-toplevel - - self._qiboSymbol = Symbol # also used in ``self._get_symbol_matrix`` - - from qibo.backends import _check_backend self.backend = _check_backend(backend) - if form is not None: - self.form = form - if nqubits is not None: - self.nqubits = nqubits + self.nqubits = ( + _calculate_nqubits_from_form(form) if nqubits is None else nqubits + ) - @property + @cached_property def dense(self) -> "MatrixHamiltonian": """Creates the equivalent Hamiltonian matrix.""" - if self._dense is None: - log.warning( - "Calculating the dense form of a symbolic Hamiltonian. " - "This operation is memory inefficient." - ) - self.dense = self.calculate_dense() - return self._dense - - @dense.setter - def dense(self, hamiltonian): - assert isinstance(hamiltonian, Hamiltonian) - self._dense = hamiltonian - self._eigenvalues = hamiltonian._eigenvalues - self._eigenvectors = hamiltonian._eigenvectors - self._exp = hamiltonian._exp + return self.calculate_dense() @property def form(self): @@ -376,53 +348,28 @@ def form(self, form): TypeError, f"Symbolic Hamiltonian should be a ``sympy`` expression but is {type(form)}.", ) - # Calculate number of qubits in the system described by the given - # Hamiltonian formula - nqubits = 0 - for symbol in form.free_symbols: - if isinstance(symbol, self._qiboSymbol): - q = symbol.target_qubit - elif isinstance(symbol, sympy.Expr): - if symbol not in self.symbol_map: - raise_error(ValueError, f"Symbol {symbol} is not in symbol map.") - q, matrix = self.symbol_map.get(symbol) - if not isinstance(matrix, self.backend.tensor_types): - # ignore symbols that do not correspond to quantum operators - # for example parameters in the MaxCut Hamiltonian - q = 0 - if q > nqubits: - nqubits = q - self._form = form - self.nqubits = nqubits + 1 + self.nqubits = _calculate_nqubits_from_form(form) - @property + @cached_property def terms(self): """List of terms of which the Hamiltonian is a sum of. Terms will be objects of type :class:`qibo.core.terms.HamiltonianTerm`. """ - if self._terms is None: - # Calculate terms based on ``self.form`` - from qibo.hamiltonians.terms import ( # pylint: disable=import-outside-toplevel - SymbolicTerm, - ) + # Calculate terms based on ``self.form`` - form = sympy.expand(self.form) - terms = [] - for f, c in form.as_coefficients_dict().items(): - term = SymbolicTerm(c, f, self.symbol_map) - if term.target_qubits: - terms.append(term) - else: - self.constant += term.coefficient - self._terms = terms - return self._terms - - @terms.setter - def terms(self, terms): - self._terms = terms - self.nqubits = max(q for term in self._terms for q in term.target_qubits) + 1 + self.constant = 0.0 + + form = sympy.expand(self.form) + terms = [] + for f, c in form.as_coefficients_dict().items(): + term = SymbolicTerm(c, f, backend=self.backend) + if term.target_qubits: + terms.append(term) + else: + self.constant += term.coefficient + return terms @property def matrix(self): @@ -444,6 +391,7 @@ def ground_state(self): def exp(self, a): return self.dense.exp(a) + @cache def _get_symbol_matrix(self, term): """Calculates numerical matrix corresponding to symbolic expression. @@ -472,42 +420,34 @@ def _get_symbol_matrix(self, term): # note that we need to use matrix multiplication even though # we use scalar symbols for convenience factors = term.as_ordered_factors() - result = self._get_symbol_matrix(factors[0]) - for subterm in factors[1:]: - result = result @ self._get_symbol_matrix(subterm) + result = reduce( + self.backend.np.matmul, + (self._get_symbol_matrix(subterm) for subterm in factors), + ) elif isinstance(term, sympy.Pow): # symbolic op for power base, exponent = term.as_base_exp() matrix = self._get_symbol_matrix(base) - # multiply ``base`` matrix ``exponent`` times to itself - result = matrix - for _ in range(exponent - 1): - result = result @ matrix - - elif isinstance(term, sympy.Symbol): - # if the term is a ``Symbol`` then it corresponds to a quantum - # operator for which we can construct the full matrix directly - if isinstance(term, self._qiboSymbol): - # if we have a Qibo symbol the matrix construction is - # implemented in :meth:`qibo.core.terms.SymbolicTerm.full_matrix`. - result = term.full_matrix(self.nqubits) - else: - q, matrix = self.symbol_map.get(term) - if not isinstance(matrix, self.backend.tensor_types): - # symbols that do not correspond to quantum operators - # for example parameters in the MaxCut Hamiltonian - result = complex(matrix) * np.eye(2**self.nqubits) - else: - # if we do not have a Qibo symbol we construct one and use - # :meth:`qibo.core.terms.SymbolicTerm.full_matrix`. - result = self._qiboSymbol(q, matrix).full_matrix(self.nqubits) + matrix_power = ( + np.linalg.matrix_power + if self.backend.name == "tensorflow" + else self.backend.np.linalg.matrix_power + ) + result = matrix_power(matrix, int(exponent)) + + elif isinstance(term, Symbol): + # if we have a Qibo symbol the matrix construction is + # implemented in :meth:`qibo.core.terms.SymbolicTerm.full_matrix`. + # I have to force the symbol's backend + term.backend = self.backend + result = term.full_matrix(self.nqubits) elif term.is_number: # if the term is number we should return in the form of identity # matrix because in expressions like `1 + Z`, `1` is not correspond # to the float 1 but the identity operator (matrix) - result = complex(term) * np.eye(2**self.nqubits) + result = complex(term) * self.backend.matrices.I(2**self.nqubits) else: raise_error( @@ -525,32 +465,14 @@ def _calculate_dense_from_form(self) -> Hamiltonian: matrix = self._get_symbol_matrix(self.form) return Hamiltonian(self.nqubits, matrix, backend=self.backend) - def _calculate_dense_from_terms(self) -> Hamiltonian: - """Calculates equivalent Hamiltonian using the term representation.""" - if 2 * self.nqubits > len(EINSUM_CHARS): # pragma: no cover - # case not tested because it only happens in large examples - raise_error(NotImplementedError, "Not enough einsum characters.") - - matrix = 0 - chars = EINSUM_CHARS[: 2 * self.nqubits] - for term in self.terms: - ntargets = len(term.target_qubits) - tmat = np.reshape(term.matrix, 2 * ntargets * (2,)) - n = self.nqubits - ntargets - emat = np.reshape(np.eye(2**n, dtype=tmat.dtype), 2 * n * (2,)) - gen = lambda x: (chars[i + x] for i in term.target_qubits) - tc = "".join(chain(gen(0), gen(self.nqubits))) - ec = "".join(c for c in chars if c not in tc) - matrix += np.einsum(f"{tc},{ec}->{chars}", tmat, emat) - matrix = np.reshape(matrix, 2 * (2**self.nqubits,)) - return Hamiltonian(self.nqubits, matrix, backend=self.backend) + self.constant - - def calculate_dense(self): - if self._terms is None: - # calculate dense matrix directly using the form to avoid the - # costly ``sympy.expand`` call - return self._calculate_dense_from_form() - return self._calculate_dense_from_terms() + def calculate_dense(self) -> Hamiltonian: + log.warning( + "Calculating the dense form of a symbolic Hamiltonian. " + "This operation is memory inefficient." + ) + # calculate dense matrix directly using the form to avoid the + # costly ``sympy.expand`` call + return self._calculate_dense_from_form() def expectation(self, state, normalize=False): return Hamiltonian.expectation(self, state, normalize) @@ -663,120 +585,42 @@ def expectation_from_samples(self, freq: dict, qubit_map: list = None) -> float: ) return self.backend.np.sum(expvals @ counts.T) + self.constant.real - def __add__(self, o): - if isinstance(o, self.__class__): - if self.nqubits != o.nqubits: - raise_error( - RuntimeError, - "Only hamiltonians with the same number of qubits can be added.", - ) - new_ham = self.__class__( - symbol_map=dict(self.symbol_map), backend=self.backend - ) - if self._form is not None and o._form is not None: - new_ham.form = self.form + o.form - new_ham.symbol_map.update(o.symbol_map) - if self._terms is not None and o._terms is not None: - new_ham.terms = self.terms + o.terms - new_ham.constant = self.constant + o.constant - if self._dense is not None and o._dense is not None: - new_ham.dense = self.dense + o.dense - - elif isinstance(o, self.backend.numeric_types): - new_ham = self.__class__( - symbol_map=dict(self.symbol_map), backend=self.backend - ) - if self._form is not None: - new_ham.form = self.form + o - if self._terms is not None: - new_ham.terms = self.terms - new_ham.constant = self.constant + o - if self._dense is not None: - new_ham.dense = self.dense + o - - else: - raise_error( - NotImplementedError, - f"SymbolicHamiltonian addition to {type(o)} not implemented.", - ) - return new_ham + def _compose(self, other, operator): + form = self._form - def __sub__(self, o): - if isinstance(o, self.__class__): - if self.nqubits != o.nqubits: + if isinstance(other, self.__class__): + if self.nqubits != other.nqubits: raise_error( RuntimeError, - "Only hamiltonians with the same number of qubits can be subtracted.", + "Only hamiltonians with the same number of qubits can be composed.", ) - new_ham = self.__class__( - symbol_map=dict(self.symbol_map), backend=self.backend - ) - if self._form is not None and o._form is not None: - new_ham.form = self.form - o.form - new_ham.symbol_map.update(o.symbol_map) - if self._terms is not None and o._terms is not None: - new_ham.terms = self.terms + [-1 * x for x in o.terms] - new_ham.constant = self.constant - o.constant - if self._dense is not None and o._dense is not None: - new_ham.dense = self.dense - o.dense - - elif isinstance(o, self.backend.numeric_types): - new_ham = self.__class__( - symbol_map=dict(self.symbol_map), backend=self.backend - ) - if self._form is not None: - new_ham.form = self.form - o - if self._terms is not None: - new_ham.terms = self.terms - new_ham.constant = self.constant - o - if self._dense is not None: - new_ham.dense = self.dense - o - else: - raise_error( - NotImplementedError, - f"Hamiltonian subtraction to {type(o)} " "not implemented.", - ) - return new_ham + if other._form is not None: + form = operator(form, other._form) if form is not None else other._form - def __rsub__(self, o): - if isinstance(o, self.backend.numeric_types): - new_ham = self.__class__( - symbol_map=dict(self.symbol_map), backend=self.backend + elif isinstance(other, (self.backend.numeric_types, self.backend.tensor_types)): + form = ( + operator(form, complex(other)) if form is not None else complex(other) ) - if self._form is not None: - new_ham.form = o - self.form - if self._terms is not None: - new_ham.terms = [-1 * x for x in self.terms] - new_ham.constant = o - self.constant - if self._dense is not None: - new_ham.dense = o - self.dense else: raise_error( NotImplementedError, - f"Hamiltonian subtraction to {type(o)} not implemented.", + f"SymbolicHamiltonian composition to {type(other)} not implemented.", ) - return new_ham - def __mul__(self, o): - if not isinstance(o, (self.backend.numeric_types, self.backend.tensor_types)): - raise_error( - NotImplementedError, - f"Hamiltonian multiplication to {type(o)} not implemented.", - ) - o = complex(o) - new_ham = self.__class__(symbol_map=dict(self.symbol_map), backend=self.backend) - if self._form is not None: - new_ham.form = o * self.form - if self._terms is not None: - new_ham.terms = [o * x for x in self.terms] - new_ham.constant = self.constant * o - if self._dense is not None: - new_ham.dense = o * self._dense + return self.__class__(form=form, nqubits=self.nqubits, backend=self.backend) + + def __add__(self, other): + return self._compose(other, operator.add) + + def __sub__(self, other): + return self._compose(other, operator.sub) - new_ham.nqubits = self.nqubits + def __rsub__(self, other): + return self._compose(other, lambda x, y: y - x) - return new_ham + def __mul__(self, other): + return self._compose(other, lambda x, y: y * x) def apply_gates(self, state, density_matrix=False): """Applies gates corresponding to the Hamiltonian terms. @@ -797,33 +641,19 @@ def apply_gates(self, state, density_matrix=False): total += self.constant * state return total - def __matmul__(self, o): + def __matmul__(self, other): """Matrix multiplication with other Hamiltonians or state vectors.""" - if isinstance(o, self.__class__): - if self._form is None or o._form is None: - raise_error( - NotImplementedError, - "Multiplication of symbolic Hamiltonians " - "without symbolic form is not implemented.", - ) - new_form = self.form * o.form - new_symbol_map = dict(self.symbol_map) - new_symbol_map.update(o.symbol_map) - new_ham = self.__class__( - new_form, symbol_map=new_symbol_map, backend=self.backend - ) - if self._dense is not None and o._dense is not None: - new_ham.dense = self.dense @ o.dense - return new_ham + if isinstance(other, self.__class__): + return other * self - if isinstance(o, self.backend.tensor_types): - rank = len(tuple(o.shape)) + if isinstance(other, self.backend.tensor_types): + rank = len(tuple(other.shape)) if rank not in (1, 2): raise_error( NotImplementedError, f"Cannot multiply Hamiltonian with rank-{rank} tensor.", ) - state_qubits = int(np.log2(int(o.shape[0]))) + state_qubits = int(np.log2(int(other.shape[0]))) if state_qubits != self.nqubits: raise_error( ValueError, @@ -831,13 +661,13 @@ def __matmul__(self, o): + f"state of {state_qubits} qubits.", ) if rank == 1: # state vector - return self.apply_gates(o) + return self.apply_gates(other) - return self.apply_gates(o, density_matrix=True) + return self.apply_gates(other, density_matrix=True) raise_error( NotImplementedError, - f"Hamiltonian matmul to {type(o)} not implemented.", + f"Hamiltonian matmul to {type(other)} not implemented.", ) def circuit(self, dt, accelerators=None): @@ -860,19 +690,3 @@ def circuit(self, dt, accelerators=None): ) return circuit - - -class TrotterHamiltonian: - """""" - - def __init__(self, *parts): - raise_error( - NotImplementedError, - "`TrotterHamiltonian` is substituted by `SymbolicHamiltonian` " - + "and is no longer supported. Please check the documentation " - + "of `SymbolicHamiltonian` for more details.", - ) - - @classmethod - def from_symbolic(cls, symbolic_hamiltonian, symbol_map): - return cls() diff --git a/src/qibo/hamiltonians/models.py b/src/qibo/hamiltonians/models.py index 61fa918021..2cf7251e45 100644 --- a/src/qibo/hamiltonians/models.py +++ b/src/qibo/hamiltonians/models.py @@ -1,9 +1,10 @@ from functools import reduce -from typing import Union +from typing import Optional, Union import numpy as np -from qibo.backends import _check_backend, matrices +from qibo import symbols +from qibo.backends import Backend, _check_backend, matrices from qibo.config import raise_error from qibo.hamiltonians.hamiltonians import Hamiltonian, SymbolicHamiltonian from qibo.hamiltonians.terms import HamiltonianTerm @@ -25,7 +26,7 @@ def X(nqubits, dense: bool = True, backend=None): in the execution. If ``None``, it uses the current backend. Defaults to ``None``. """ - return _OneBodyPauli(nqubits, matrices.X, dense, backend=backend) + return _OneBodyPauli(nqubits, symbols.X, dense, backend=backend) def Y(nqubits, dense: bool = True, backend=None): @@ -43,7 +44,7 @@ def Y(nqubits, dense: bool = True, backend=None): in the execution. If ``None``, it uses the current backend. Defaults to ``None``. """ - return _OneBodyPauli(nqubits, matrices.Y, dense, backend=backend) + return _OneBodyPauli(nqubits, symbols.Y, dense, backend=backend) def Z(nqubits, dense: bool = True, backend=None): @@ -61,7 +62,7 @@ def Z(nqubits, dense: bool = True, backend=None): in the execution. If ``None``, it uses the current backend. Defaults to ``None``. """ - return _OneBodyPauli(nqubits, matrices.Z, dense, backend=backend) + return _OneBodyPauli(nqubits, symbols.Z, dense, backend=backend) def TFIM(nqubits, h: float = 0.0, dense: bool = True, backend=None): @@ -80,25 +81,31 @@ def TFIM(nqubits, h: float = 0.0, dense: bool = True, backend=None): """ if nqubits < 2: raise_error(ValueError, "Number of qubits must be larger than one.") + backend = _check_backend(backend) if dense: condition = lambda i, j: i in {j % nqubits, (j + 1) % nqubits} - ham = -_build_spin_model(nqubits, matrices.Z, condition) + ham = -_build_spin_model(nqubits, backend.matrices.Z, condition, backend) if h != 0: condition = lambda i, j: i == j % nqubits - ham -= h * _build_spin_model(nqubits, matrices.X, condition) + ham -= h * _build_spin_model( + nqubits, backend.matrices.X, condition, backend + ) return Hamiltonian(nqubits, ham, backend=backend) - matrix = -( - _multikron([matrices.Z, matrices.Z]) + h * _multikron([matrices.X, matrices.I]) - ) - terms = [HamiltonianTerm(matrix, i, i + 1) for i in range(nqubits - 1)] - terms.append(HamiltonianTerm(matrix, nqubits - 1, 0)) - ham = SymbolicHamiltonian(backend=backend) - ham.terms = terms + term = lambda q1, q2: symbols.Z(q1, backend=backend) * symbols.Z( + q2, backend=backend + ) + h * symbols.X(q1, backend=backend) + form = -1 * sum(term(i, i + 1) for i in range(nqubits - 1)) - term(nqubits - 1, 0) + ham = SymbolicHamiltonian(form=form, nqubits=nqubits, backend=backend) return ham -def MaxCut(nqubits, dense: bool = True, backend=None): +def MaxCut( + nqubits, + dense: bool = True, + adj_matrix: Optional[Union[list[list[float]], np.ndarray]] = None, + backend: Optional[Backend] = None, +): """Max Cut Hamiltonian. .. math:: @@ -109,26 +116,29 @@ def MaxCut(nqubits, dense: bool = True, backend=None): dense (bool): If ``True`` it creates the Hamiltonian as a :class:`qibo.core.hamiltonians.Hamiltonian`, otherwise it creates a :class:`qibo.core.hamiltonians.SymbolicHamiltonian`. + adj_matrix (list[list[float]] | np.ndarray): Adjecency matrix of the graph. Defaults to a + homogeneous fully connected graph with all edges having an equal 1.0 weight. backend (:class:`qibo.backends.abstract.Backend`, optional): backend to be used in the execution. If ``None``, it uses the current backend. Defaults to ``None``. """ - import sympy as sp + if adj_matrix is None: + adj_matrix = np.ones((nqubits, nqubits)) + elif len(adj_matrix) != nqubits: + raise_error( + RuntimeError, + f"Expected an adjacency matrix of shape ({nqubits},{nqubits}) for a {nqubits}-qubits system.", + ) - Z = sp.symbols(f"Z:{nqubits}") - V = sp.symbols(f"V:{nqubits**2}") - sham = -sum( - V[i * nqubits + j] * (1 - Z[i] * Z[j]) + form = -sum( + adj_matrix[i][j] + * (1 - symbols.Z(i, backend=backend) * symbols.Z(j, backend=backend)) for i in range(nqubits) for j in range(nqubits) ) - sham /= 2 - - v = np.ones(nqubits**2) - smap = {s: (i, matrices.Z) for i, s in enumerate(Z)} - smap.update({s: (i, v[i]) for i, s in enumerate(V)}) + form /= 2 - ham = SymbolicHamiltonian(sham, symbol_map=smap, backend=backend) + ham = SymbolicHamiltonian(form, nqubits=nqubits, backend=backend) if dense: return ham.dense return ham @@ -203,14 +213,16 @@ def Heisenberg( backend = _check_backend(backend) - paulis = [matrices.X, matrices.Y, matrices.Z] + paulis = (symbols.X, symbols.Y, symbols.Z) if dense: condition = lambda i, j: i in {j % nqubits, (j + 1) % nqubits} matrix = np.zeros((2**nqubits, 2**nqubits), dtype=complex) matrix = backend.cast(matrix, dtype=matrix.dtype) for ind, pauli in enumerate(paulis): - double_term = _build_spin_model(nqubits, pauli, condition) + double_term = _build_spin_model( + nqubits, pauli(0, backend=backend).matrix, condition, backend + ) double_term = backend.cast(double_term, dtype=double_term.dtype) matrix = matrix - coupling_constants[ind] * double_term matrix = ( @@ -221,31 +233,24 @@ def Heisenberg( return Hamiltonian(nqubits, matrix, backend=backend) - hx = _multikron([matrices.X, matrices.X]) - hy = _multikron([matrices.Y, matrices.Y]) - hz = _multikron([matrices.Z, matrices.Z]) - - matrix = ( - -coupling_constants[0] * hx - - coupling_constants[1] * hy - - coupling_constants[2] * hz - ) + def h(symbol): + return lambda q1, q2: symbol(q1, backend=backend) * symbol(q2, backend=backend) - terms = [HamiltonianTerm(matrix, i, i + 1) for i in range(nqubits - 1)] - terms.append(HamiltonianTerm(matrix, nqubits - 1, 0)) + def term(q1, q2): + return sum( + coeff * h(operator)(q1, q2) + for coeff, operator in zip(coupling_constants, paulis) + ) - terms.extend( - [ - -field_strength * HamiltonianTerm(pauli, qubit) - for qubit in range(nqubits) - for field_strength, pauli in zip(external_field_strengths, paulis) - if field_strength != 0.0 - ] + form = -1 * sum(term(i, i + 1) for i in range(nqubits - 1)) - term(nqubits - 1, 0) + form -= sum( + field_strength * pauli(qubit) + for qubit in range(nqubits) + for field_strength, pauli in zip(external_field_strengths, paulis) + if field_strength != 0.0 ) - ham = SymbolicHamiltonian(backend=backend) - ham.terms = terms - + ham = SymbolicHamiltonian(form=form, backend=backend) return ham @@ -342,7 +347,7 @@ def XXZ(nqubits, delta=0.5, dense: bool = True, backend=None): return Heisenberg(nqubits, [-1, -1, -delta], 0, dense=dense, backend=backend) -def _multikron(matrix_list): +def _multikron(matrix_list, backend): """Calculates Kronecker product of a list of matrices. Args: @@ -351,28 +356,35 @@ def _multikron(matrix_list): Returns: ndarray: Kronecker product of all matrices in ``matrix_list``. """ - return reduce(np.kron, matrix_list) + return reduce(backend.np.kron, matrix_list) -def _build_spin_model(nqubits, matrix, condition): +def _build_spin_model(nqubits, matrix, condition, backend): """Helper method for building nearest-neighbor spin model Hamiltonians.""" h = sum( - _multikron(matrix if condition(i, j) else matrices.I for j in range(nqubits)) + reduce( + backend.np.kron, + ( + matrix if condition(i, j) else backend.matrices.I() + for j in range(nqubits) + ), + ) for i in range(nqubits) ) return h -def _OneBodyPauli(nqubits, matrix, dense: bool = True, backend=None): - """Helper method for constracting non-interacting +def _OneBodyPauli(nqubits, operator, dense: bool = True, backend=None): + """Helper method for constructing non-interacting :math:`X`, :math:`Y`, and :math:`Z` Hamiltonians.""" + backend = _check_backend(backend) if dense: condition = lambda i, j: i == j % nqubits - ham = -_build_spin_model(nqubits, matrix, condition) + ham = -_build_spin_model( + nqubits, operator(0, backend=backend).matrix, condition, backend + ) return Hamiltonian(nqubits, ham, backend=backend) - matrix = -matrix - terms = [HamiltonianTerm(matrix, i) for i in range(nqubits)] - ham = SymbolicHamiltonian(backend=backend) - ham.terms = terms + form = sum([-1 * operator(i, backend=backend) for i in range(nqubits)]) + ham = SymbolicHamiltonian(form=form, backend=backend) return ham diff --git a/src/qibo/hamiltonians/terms.py b/src/qibo/hamiltonians/terms.py index c46557abeb..3ceca1f9fa 100644 --- a/src/qibo/hamiltonians/terms.py +++ b/src/qibo/hamiltonians/terms.py @@ -1,7 +1,11 @@ +from functools import cached_property, reduce +from typing import Optional + import numpy as np import sympy -from qibo import gates, symbols +from qibo import gates +from qibo.backends import Backend, _check_backend from qibo.config import raise_error from qibo.symbols import I, X, Y, Z @@ -21,14 +25,15 @@ class HamiltonianTerm: q (list): List of target qubit ids. """ - def __init__(self, matrix, *q): + def __init__(self, matrix, *q, backend: Optional[Backend] = None): + self.backend = _check_backend(backend) for qi in q: if qi < 0: raise_error( ValueError, f"Invalid qubit id {qi} < 0 was given in Hamiltonian term.", ) - if not isinstance(matrix, np.ndarray): + if not isinstance(matrix, self.backend.tensor_types): raise_error(TypeError, f"Invalid type {type(matrix)} of symbol matrix.") dim = int(matrix.shape[0]) if 2 ** len(q) != dim: @@ -41,7 +46,7 @@ def __init__(self, matrix, *q): self.target_qubits = tuple(q) self._gate = None self.hamiltonian = None - self._matrix = matrix + self._matrix = self.backend.cast(matrix) @property def matrix(self): @@ -57,9 +62,7 @@ def gate(self): def exp(self, x): """Matrix exponentiation of the term.""" - from scipy.linalg import expm - - return expm(-1j * x * self.matrix) + return self.backend.calculate_matrix_exp(x, self.matrix) def expgate(self, x): """:class:`qibo.gates.gates.Unitary` gate implementing the action of exp(term) on states.""" @@ -78,8 +81,10 @@ def merge(self, term): "Cannot merge HamiltonianTerm acting on " + f"qubits {term.target_qubits} to term on qubits {self.target_qubits}.", ) - matrix = np.kron(term.matrix, np.eye(2 ** (len(self) - len(term)))) - matrix = np.reshape(matrix, 2 * len(self) * (2,)) + matrix = self.backend.np.kron( + term.matrix, self.backend.matrices.I(2 ** (len(self) - len(term))) + ) + matrix = self.backend.np.reshape(matrix, 2 * len(self) * (2,)) order = [] i = len(term) for qubit in self.target_qubits: @@ -89,15 +94,19 @@ def merge(self, term): order.append(i) i += 1 order.extend([x + len(order) for x in order]) - matrix = np.transpose(matrix, order) - matrix = np.reshape(matrix, 2 * (2 ** len(self),)) - return HamiltonianTerm(self.matrix + matrix, *self.target_qubits) + matrix = self.backend.np.transpose(matrix, order) + matrix = self.backend.np.reshape(matrix, 2 * (2 ** len(self),)) + return HamiltonianTerm( + self.matrix + matrix, *self.target_qubits, backend=self.backend + ) def __len__(self): return len(self.target_qubits) def __mul__(self, x): - return HamiltonianTerm(x * self.matrix, *self.target_qubits) + return HamiltonianTerm( + x * self.matrix, *self.target_qubits, backend=self.backend + ) def __rmul__(self, x): return self.__mul__(x) @@ -128,18 +137,13 @@ class SymbolicTerm(HamiltonianTerm): coefficient (complex): Complex number coefficient of the underlying term in the Hamiltonian. factors (sympy.Expr): Sympy expression for the underlying term. - symbol_map (dict): Dictionary that maps symbols in the given ``factors`` - expression to tuples of (target qubit id, matrix). - This is required only if the expression is not created using Qibo - symbols and to keep compatibility with older versions where Qibo - symbols were not available. """ - def __init__(self, coefficient, factors=1, symbol_map={}): - self.coefficient = complex(coefficient) - self._matrix = None + def __init__(self, coefficient, factors=1, backend: Optional[Backend] = None): self._gate = None self.hamiltonian = None + self.backend = _check_backend(backend) + self.coefficient = complex(coefficient) # List of :class:`qibo.symbols.Symbol` that represent the term factors self.factors = [] @@ -166,16 +170,12 @@ def __init__(self, coefficient, factors=1, symbol_map={}): else: pow = 1 - # if the user is using ``symbol_map`` instead of qibo symbols, - # create the corresponding symbols - if factor in symbol_map: - from qibo.symbols import Symbol - - q, matrix = symbol_map.get(factor) - factor = Symbol(q, matrix, name=factor.name) - if isinstance(factor, sympy.Symbol): - if isinstance(factor.matrix, np.ndarray): + # forces the backend of the factor + # this way it is not necessary to explicitely define the + # backend of a symbol, i.e. Z(q, backend=backend) + factor.backend = self.backend + if isinstance(factor.matrix, self.backend.tensor_types): self.factors.extend(pow * [factor]) q = factor.target_qubit # if pow > 1 the matrix should be multiplied multiple @@ -199,7 +199,7 @@ def __init__(self, coefficient, factors=1, symbol_map={}): self.target_qubits = tuple(sorted(self.matrix_map.keys())) - @property + @cached_property def matrix(self): """Calculates the full matrix corresponding to this term. @@ -208,27 +208,11 @@ def matrix(self): where ``ntargets`` is the number of qubits included in the factors of this term. """ - if self._matrix is None: - - def matrices_product(matrices): - """Product of matrices that act on the same tuple of qubits. - - Args: - matrices (list): List of matrices to multiply, as exists in - the values of ``SymbolicTerm.matrix_map``. - """ - if len(matrices) == 1: - return matrices[0] - matrix = np.copy(matrices[0]) - for m in matrices[1:]: - matrix = matrix @ m - return matrix - - self._matrix = self.coefficient - for q in self.target_qubits: - matrix = matrices_product(self.matrix_map.get(q)) - self._matrix = np.kron(self._matrix, matrix) - return self._matrix + matrices = [ + reduce(self.backend.np.matmul, self.matrix_map.get(q)) + for q in self.target_qubits + ] + return complex(self.coefficient) * reduce(self.backend.np.kron, matrices) def copy(self): """Creates a shallow copy of the term with the same attributes.""" @@ -236,14 +220,13 @@ def copy(self): new.factors = self.factors new.matrix_map = self.matrix_map new.target_qubits = self.target_qubits + new.backend = self.backend return new def __mul__(self, x): """Multiplication of scalar to the Hamiltonian term.""" new = self.copy() new.coefficient *= x - if self._matrix is not None: - new._matrix = x * self._matrix return new def __call__(self, backend, state, nqubits, density_matrix=False): diff --git a/src/qibo/models/tsp.py b/src/qibo/models/tsp.py index 7fcfc92439..c50a9dd71a 100644 --- a/src/qibo/models/tsp.py +++ b/src/qibo/models/tsp.py @@ -20,8 +20,8 @@ def tsp_phaser(distance_matrix, backend=None): if u != v: form += ( distance_matrix[u, v] - * Z(int(two_to_one[u, i])) - * Z(int(two_to_one[v, (i + 1) % num_cities])) + * Z(int(two_to_one[u, i]), backend=backend) + * Z(int(two_to_one[v, (i + 1) % num_cities]), backend=backend) ) ham = SymbolicHamiltonian(form, backend=backend) return ham @@ -29,8 +29,12 @@ def tsp_phaser(distance_matrix, backend=None): def tsp_mixer(num_cities, backend=None): two_to_one = calculate_two_to_one(num_cities) - splus = lambda u, i: X(int(two_to_one[u, i])) + 1j * Y(int(two_to_one[u, i])) - sminus = lambda u, i: X(int(two_to_one[u, i])) - 1j * Y(int(two_to_one[u, i])) + splus = lambda u, i: X(int(two_to_one[u, i]), backend=backend) + 1j * Y( + int(two_to_one[u, i]), backend=backend + ) + sminus = lambda u, i: X(int(two_to_one[u, i]), backend=backend) - 1j * Y( + int(two_to_one[u, i]), backend=backend + ) form = 0 for i in range(num_cities): for u in range(num_cities): diff --git a/src/qibo/solvers.py b/src/qibo/solvers.py index 69ab0d3622..2364364d19 100644 --- a/src/qibo/solvers.py +++ b/src/qibo/solvers.py @@ -44,7 +44,7 @@ class TrotterizedExponential(BaseSolver): Created automatically from the :class:`qibo.solvers.Exponential` if the given Hamiltonian object is a - :class:`qibo.hamiltonians.hamiltonians.TrotterHamiltonian`. + :class:`qibo.hamiltonians.hamiltonians.SymbolicHamiltonian`. """ def __init__(self, dt, hamiltonian): diff --git a/src/qibo/symbols.py b/src/qibo/symbols.py index edb03eb677..c5b7ef289d 100644 --- a/src/qibo/symbols.py +++ b/src/qibo/symbols.py @@ -1,8 +1,10 @@ +from typing import Optional + import numpy as np import sympy from qibo import gates -from qibo.backends import matrices +from qibo.backends import Backend, _check_backend, get_backend, matrices from qibo.config import raise_error @@ -37,17 +39,25 @@ class Symbol(sympy.Symbol): (for example when the Hamiltonian consists of Z terms only). """ - def __new__(cls, q, matrix=None, name="Symbol", commutative=False, **assumptions): + def __new__(cls, q, matrix, name="Symbol", commutative=False, **assumptions): name = f"{name}{q}" assumptions["commutative"] = commutative return super().__new__(cls=cls, name=name, **assumptions) - def __init__(self, q, matrix=None, name="Symbol", commutative=False): + def __init__( + self, + q, + matrix, + name="Symbol", + commutative=False, + backend: Optional[Backend] = None, + ): self.target_qubit = q + self.backend = _check_backend(backend) self._gate = None if not ( - matrix is None - or isinstance(matrix, np.ndarray) + isinstance(matrix, np.ndarray) + or isinstance(matrix, self.backend.tensor_types) or isinstance( matrix, ( @@ -64,7 +74,7 @@ def __init__(self, q, matrix=None, name="Symbol", commutative=False): ) ): raise_error(TypeError, f"Invalid type {type(matrix)} of symbol matrix.") - self.matrix = matrix + self._matrix = matrix def __getstate__(self): return { @@ -78,6 +88,7 @@ def __setstate__(self, data): self.matrix = data.get("matrix") self.name = data.get("name") self._gate = None + self.backend = get_backend() @property def gate(self): @@ -89,11 +100,20 @@ def gate(self): def calculate_gate(self): # pragma: no cover return gates.Unitary(self.matrix, self.target_qubit) + @property + def matrix(self): + return self.backend.cast(self._matrix) + + @matrix.setter + def matrix(self, matrix): + self._matrix = matrix + def full_matrix(self, nqubits): """Calculates the full dense matrix corresponding to the symbol as part of a bigger system. Args: nqubits (int): Total number of qubits in the system. + backend (Backend): Optional backend to represent the matrix with. By default the global backend is used. Returns: Matrix of dimension (2^nqubits, 2^nqubits) composed of the Kronecker @@ -101,11 +121,11 @@ def full_matrix(self, nqubits): """ from qibo.hamiltonians.models import _multikron - matrix_list = self.target_qubit * [matrices.I] + matrix_list = self.target_qubit * [self.backend.matrices.I()] matrix_list.append(self.matrix) n = nqubits - self.target_qubit - 1 - matrix_list.extend(matrices.I for _ in range(n)) - return _multikron(matrix_list) + matrix_list.extend(self.backend.matrices.I() for _ in range(n)) + return _multikron(matrix_list, backend=self.backend) class PauliSymbol(Symbol): @@ -113,10 +133,10 @@ def __new__(cls, q, commutative=False, **assumptions): matrix = getattr(matrices, cls.__name__) return super().__new__(cls, q, matrix, cls.__name__, commutative, **assumptions) - def __init__(self, q, commutative=False): + def __init__(self, q, commutative=False, backend: Optional[Backend] = None): name = self.__class__.__name__ matrix = getattr(matrices, name) - super().__init__(q, matrix, name, commutative) + super().__init__(q, matrix, name, commutative, backend=backend) def calculate_gate(self): name = self.__class__.__name__ diff --git a/tests/test_hamiltonians.py b/tests/test_hamiltonians.py index 8806bd94bb..33fa884767 100644 --- a/tests/test_hamiltonians.py +++ b/tests/test_hamiltonians.py @@ -341,14 +341,14 @@ def test_hamiltonian_eigenvalues(backend, dtype, sparse_type, dense): c1 = dtype(2.5) H2 = c1 * H1 - H2_eigen = sorted(backend.to_numpy(H2._eigenvalues)) + H2_eigen = sorted(backend.to_numpy(H2.eigenvalues())) hH2_eigen = sorted(backend.to_numpy(backend.calculate_eigenvalues(c1 * H1.matrix))) backend.assert_allclose(H2_eigen, hH2_eigen) c2 = dtype(-11.1) H3 = H1 * c2 if sparse_type is None: - H3_eigen = sorted(backend.to_numpy(H3._eigenvalues)) + H3_eigen = sorted(backend.to_numpy(H3.eigenvalues())) hH3_eigen = sorted( backend.to_numpy(backend.calculate_eigenvalues(H1.matrix * c2)) ) @@ -369,20 +369,20 @@ def test_hamiltonian_eigenvectors(backend, dtype, dense): c1 = dtype(2.5) H2 = c1 * H1 - V2 = backend.to_numpy(H2._eigenvectors) - U2 = backend.to_numpy(H2._eigenvalues) + V2 = backend.to_numpy(H2.eigenvectors()) + U2 = backend.to_numpy(H2.eigenvalues()) backend.assert_allclose(H2.matrix, V2 @ np.diag(U2) @ V2.T) c2 = dtype(-11.1) H3 = H1 * c2 V3 = backend.to_numpy(H3.eigenvectors()) - U3 = backend.to_numpy(H3._eigenvalues) + U3 = backend.to_numpy(H3.eigenvalues()) backend.assert_allclose(H3.matrix, V3 @ np.diag(U3) @ V3.T) c3 = dtype(0) H4 = c3 * H1 - V4 = backend.to_numpy(H4._eigenvectors) - U4 = backend.to_numpy(H4._eigenvalues) + V4 = backend.to_numpy(H4.eigenvectors()) + U4 = backend.to_numpy(H4.eigenvalues()) backend.assert_allclose(H4.matrix, V4 @ np.diag(U4) @ V4.T) diff --git a/tests/test_hamiltonians_from_symbols.py b/tests/test_hamiltonians_from_symbols.py index 4e45fec904..e56c0ab4ae 100644 --- a/tests/test_hamiltonians_from_symbols.py +++ b/tests/test_hamiltonians_from_symbols.py @@ -6,7 +6,7 @@ import pytest import sympy -from qibo import hamiltonians, matrices +from qibo import get_backend, hamiltonians, matrices from qibo.backends import NumpyBackend from qibo.quantum_info import random_hermitian from qibo.symbols import I, Symbol, X, Y, Z @@ -19,63 +19,36 @@ def test_symbols_pickling(symbol): new_symbol = pickle.loads(dumped_symbol) for attr in ("target_qubit", "name", "_gate"): assert getattr(symbol, attr) == getattr(new_symbol, attr) - np.testing.assert_allclose(symbol.matrix, new_symbol.matrix) + get_backend().assert_allclose(symbol.matrix, new_symbol.matrix) @pytest.mark.parametrize("nqubits", [4, 5]) -@pytest.mark.parametrize("hamtype", ["normal", "symbolic"]) -@pytest.mark.parametrize("calcterms", [False, True]) -def test_tfim_hamiltonian_from_symbols(backend, nqubits, hamtype, calcterms): +def test_tfim_hamiltonian_from_symbols(backend, nqubits): """Check creating TFIM Hamiltonian using sympy.""" - if hamtype == "symbolic": - h = 0.5 - symham = sum(Z(i) * Z(i + 1) for i in range(nqubits - 1)) - symham += Z(0) * Z(nqubits - 1) - symham += h * sum(X(i) for i in range(nqubits)) - ham = hamiltonians.SymbolicHamiltonian(-symham, backend=backend) - else: - h = 0.5 - z_symbols = sympy.symbols(" ".join(f"Z{i}" for i in range(nqubits))) - x_symbols = sympy.symbols(" ".join(f"X{i}" for i in range(nqubits))) - - symham = sum(z_symbols[i] * z_symbols[i + 1] for i in range(nqubits - 1)) - symham += z_symbols[0] * z_symbols[-1] - symham += h * sum(x_symbols) - symmap = {z: (i, matrices.Z) for i, z in enumerate(z_symbols)} - symmap.update({x: (i, matrices.X) for i, x in enumerate(x_symbols)}) - ham = hamiltonians.Hamiltonian.from_symbolic(-symham, symmap, backend=backend) - - if calcterms: - _ = ham.terms + h = 0.5 + symham = sum( + Z(i, backend=backend) * Z(i + 1, backend=backend) for i in range(nqubits - 1) + ) + symham += Z(0, backend=backend) * Z(nqubits - 1, backend=backend) + symham += h * sum(X(i, backend=backend) for i in range(nqubits)) + ham = hamiltonians.SymbolicHamiltonian(-symham, backend=backend) final_matrix = ham.matrix target_matrix = hamiltonians.TFIM(nqubits, h=h, backend=backend).matrix backend.assert_allclose(final_matrix, target_matrix) -@pytest.mark.parametrize("hamtype", ["normal", "symbolic"]) -@pytest.mark.parametrize("calcterms", [False, True]) -def test_from_symbolic_with_power(backend, hamtype, calcterms): +def test_from_symbolic_with_power(backend): """Check ``from_symbolic`` when the expression contains powers.""" npbackend = NumpyBackend() - if hamtype == "symbolic": - matrix = random_hermitian(2, backend=npbackend) - symham = ( - Symbol(0, matrix) ** 2 - - Symbol(1, matrix) ** 2 - + 3 * Symbol(1, matrix) - - 2 * Symbol(0, matrix) * Symbol(2, matrix) - + 1 - ) - ham = hamiltonians.SymbolicHamiltonian(symham, backend=backend) - else: - z = sympy.symbols(" ".join(f"Z{i}" for i in range(3))) - symham = z[0] ** 2 - z[1] ** 2 + 3 * z[1] - 2 * z[0] * z[2] + 1 - matrix = random_hermitian(2, backend=npbackend) - symmap = {x: (i, matrix) for i, x in enumerate(z)} - ham = hamiltonians.Hamiltonian.from_symbolic(symham, symmap, backend=backend) - - if calcterms: - _ = ham.terms + matrix = random_hermitian(2, backend=npbackend) + symham = ( + Symbol(0, matrix, backend=backend) ** 2 + - Symbol(1, matrix, backend=backend) ** 2 + + 3 * Symbol(1, matrix, backend=backend) + - 2 * Symbol(0, matrix, backend=backend) * Symbol(2, matrix, backend=backend) + + 1 + ) + ham = hamiltonians.SymbolicHamiltonian(symham, backend=backend) final_matrix = ham.matrix matrix2 = matrix.dot(matrix) @@ -88,160 +61,97 @@ def test_from_symbolic_with_power(backend, hamtype, calcterms): backend.assert_allclose(final_matrix, target_matrix) -@pytest.mark.parametrize("hamtype", ["normal", "symbolic"]) -@pytest.mark.parametrize("calcterms", [False, True]) -def test_from_symbolic_with_complex_numbers(backend, hamtype, calcterms): +def test_from_symbolic_with_complex_numbers(backend): """Check ``from_symbolic`` when the expression contains imaginary unit.""" - if hamtype == "symbolic": - symham = ( - (1 + 2j) * X(0) * X(1) - + 2 * Y(0) * Y(1) - - 3j * X(0) * Y(1) - + 1j * Y(0) * X(1) - ) - ham = hamiltonians.SymbolicHamiltonian(symham, backend=backend) - else: - x = sympy.symbols(" ".join(f"X{i}" for i in range(2))) - y = sympy.symbols(" ".join(f"Y{i}" for i in range(2))) - symham = ( - (1 + 2j) * x[0] * x[1] - + 2 * y[0] * y[1] - - 3j * x[0] * y[1] - + 1j * y[0] * x[1] - ) - symmap = {s: (i, matrices.X) for i, s in enumerate(x)} - symmap.update({s: (i, matrices.Y) for i, s in enumerate(y)}) - ham = hamiltonians.Hamiltonian.from_symbolic(symham, symmap, backend=backend) - - if calcterms: - _ = ham.terms - final_matrix = ham.matrix - target_matrix = (1 + 2j) * np.kron(matrices.X, matrices.X) - target_matrix += 2 * np.kron(matrices.Y, matrices.Y) - target_matrix -= 3j * np.kron(matrices.X, matrices.Y) - target_matrix += 1j * np.kron(matrices.Y, matrices.X) - backend.assert_allclose(final_matrix, target_matrix) - - -@pytest.mark.parametrize("calcterms", [False, True]) -def test_from_symbolic_application_hamiltonian(backend, calcterms): - """Check ``from_symbolic`` for a specific four-qubit Hamiltonian.""" - z1, z2, z3, z4 = sympy.symbols("z1 z2 z3 z4") - symmap = {z: (i, matrices.Z) for i, z in enumerate([z1, z2, z3, z4])} symham = ( - z1 * z2 - - 0.5 * z1 * z3 - + 2 * z2 * z3 - + 0.35 * z2 - + 0.25 * z3 * z4 - + 0.5 * z3 - + z4 - - z1 + (1 + 2j) * X(0, backend=backend) * X(1, backend=backend) + + 2 * Y(0, backend=backend) * Y(1, backend=backend) + - 3j * X(0, backend=backend) * Y(1, backend=backend) + + 1j * Y(0, backend=backend) * X(1, backend=backend) ) - # Check that Trotter dense matrix agrees will full Hamiltonian matrix - fham = hamiltonians.Hamiltonian.from_symbolic(symham, symmap, backend=backend) - symham = ( - Z(0) * Z(1) - - 0.5 * Z(0) * Z(2) - + 2 * Z(1) * Z(2) - + 0.35 * Z(1) - + 0.25 * Z(2) * Z(3) - + 0.5 * Z(2) - + Z(3) - - Z(0) - ) - sham = hamiltonians.SymbolicHamiltonian(symham, backend=backend) - if calcterms: - _ = sham.terms - backend.assert_allclose(sham.matrix, fham.matrix) + ham = hamiltonians.SymbolicHamiltonian(symham, backend=backend) + + final_matrix = ham.matrix + target_matrix = (1 + 2j) * backend.np.kron(backend.matrices.X, backend.matrices.X) + target_matrix += 2 * backend.np.kron(backend.matrices.Y, backend.matrices.Y) + target_matrix -= 3j * backend.np.kron(backend.matrices.X, backend.matrices.Y) + target_matrix += 1j * backend.np.kron(backend.matrices.Y, backend.matrices.X) + backend.assert_allclose(final_matrix, target_matrix) @pytest.mark.parametrize("nqubits", [4, 5]) -@pytest.mark.parametrize("hamtype", ["normal", "symbolic"]) -@pytest.mark.parametrize("calcterms", [False, True]) -def test_x_hamiltonian_from_symbols(backend, nqubits, hamtype, calcterms): +def test_x_hamiltonian_from_symbols(backend, nqubits): """Check creating sum(X) Hamiltonian using sympy.""" - if hamtype == "symbolic": - symham = -sum(X(i) for i in range(nqubits)) - ham = hamiltonians.SymbolicHamiltonian(symham, backend=backend) - else: - x_symbols = sympy.symbols(" ".join(f"X{i}" for i in range(nqubits))) - symham = -sum(x_symbols) - symmap = {x: (i, matrices.X) for i, x in enumerate(x_symbols)} - ham = hamiltonians.Hamiltonian.from_symbolic(symham, symmap, backend=backend) - if calcterms: - _ = ham.terms + symham = -sum(X(i, backend=backend) for i in range(nqubits)) + ham = hamiltonians.SymbolicHamiltonian(symham, backend=backend) final_matrix = ham.matrix target_matrix = hamiltonians.X(nqubits, backend=backend).matrix backend.assert_allclose(final_matrix, target_matrix) -@pytest.mark.parametrize("hamtype", ["normal", "symbolic"]) -@pytest.mark.parametrize("calcterms", [False, True]) -def test_three_qubit_term_hamiltonian_from_symbols(backend, hamtype, calcterms): +def test_three_qubit_term_hamiltonian_from_symbols(backend): """Check creating Hamiltonian with three-qubit interaction using sympy.""" - if hamtype == "symbolic": - symham = X(0) * Y(1) * Z(2) + 0.5 * Y(0) * Z(1) * X(3) + Z(0) * X(2) - symham += Y(2) + 1.5 * Z(1) - 2 - 3 * X(1) * Y(3) - ham = hamiltonians.SymbolicHamiltonian(symham, backend=backend) - else: - x_symbols = sympy.symbols(" ".join(f"X{i}" for i in range(4))) - y_symbols = sympy.symbols(" ".join(f"Y{i}" for i in range(4))) - z_symbols = sympy.symbols(" ".join(f"Z{i}" for i in range(4))) - symmap = {x: (i, matrices.X) for i, x in enumerate(x_symbols)} - symmap.update({x: (i, matrices.Y) for i, x in enumerate(y_symbols)}) - symmap.update({x: (i, matrices.Z) for i, x in enumerate(z_symbols)}) - - symham = x_symbols[0] * y_symbols[1] * z_symbols[2] - symham += 0.5 * y_symbols[0] * z_symbols[1] * x_symbols[3] - symham += z_symbols[0] * x_symbols[2] - symham += -3 * x_symbols[1] * y_symbols[3] - symham += y_symbols[2] - symham += 1.5 * z_symbols[1] - symham -= 2 - ham = hamiltonians.Hamiltonian.from_symbolic(symham, symmap, backend=backend) - - if calcterms: - _ = ham.terms + symham = ( + X(0, backend=backend) * Y(1, backend=backend) * Z(2, backend=backend) + + 0.5 * Y(0, backend=backend) * Z(1, backend=backend) * X(3, backend=backend) + + Z(0, backend=backend) * X(2, backend=backend) + ) + symham += ( + Y(2, backend=backend) + + 1.5 * Z(1, backend=backend) + - 2 + - 3 * X(1, backend=backend) * Y(3, backend=backend) + ) + ham = hamiltonians.SymbolicHamiltonian(symham, backend=backend) final_matrix = ham.matrix - target_matrix = np.kron( - np.kron(matrices.X, matrices.Y), np.kron(matrices.Z, matrices.I) + target_matrix = backend.np.kron( + backend.np.kron(backend.matrices.X, backend.matrices.Y), + backend.np.kron(backend.matrices.Z, backend.matrices.I()), ) - target_matrix += 0.5 * np.kron( - np.kron(matrices.Y, matrices.Z), np.kron(matrices.I, matrices.X) + target_matrix += 0.5 * backend.np.kron( + backend.np.kron(backend.matrices.Y, backend.matrices.Z), + backend.np.kron(backend.matrices.I(), backend.matrices.X), ) - target_matrix += np.kron( - np.kron(matrices.Z, matrices.I), np.kron(matrices.X, matrices.I) + target_matrix += backend.np.kron( + backend.np.kron(backend.matrices.Z, backend.matrices.I()), + backend.np.kron(backend.matrices.X, backend.matrices.I()), ) - target_matrix += -3 * np.kron( - np.kron(matrices.I, matrices.X), np.kron(matrices.I, matrices.Y) + target_matrix += -3 * backend.np.kron( + backend.np.kron(backend.matrices.I(), backend.matrices.X), + backend.np.kron(backend.matrices.I(), backend.matrices.Y), ) - target_matrix += np.kron( - np.kron(matrices.I, matrices.I), np.kron(matrices.Y, matrices.I) + target_matrix += backend.np.kron( + backend.np.kron(backend.matrices.I(), backend.matrices.I()), + backend.np.kron(backend.matrices.Y, backend.matrices.I()), ) - target_matrix += 1.5 * np.kron( - np.kron(matrices.I, matrices.Z), np.kron(matrices.I, matrices.I) + target_matrix += 1.5 * backend.np.kron( + backend.np.kron(backend.matrices.I(), backend.matrices.Z), + backend.np.kron(backend.matrices.I(), backend.matrices.I()), ) - target_matrix -= 2 * np.eye(2**4, dtype=target_matrix.dtype) + target_matrix -= 2 * backend.matrices.I(2**4) backend.assert_allclose(final_matrix, target_matrix) -@pytest.mark.parametrize("calcterms", [False, True]) -def test_hamiltonian_with_identity_symbol(backend, calcterms): +def test_hamiltonian_with_identity_symbol(backend): """Check creating Hamiltonian from expression which contains the identity symbol.""" - symham = X(0) * I(1) * Z(2) + 0.5 * Y(0) * Z(1) * I(3) + Z(0) * I(1) * X(2) + symham = ( + X(0, backend=backend) * I(1, backend=backend) * Z(2, backend=backend) + + 0.5 * Y(0, backend=backend) * Z(1, backend=backend) * I(3, backend=backend) + + Z(0, backend=backend) * I(1, backend=backend) * X(2, backend=backend) + ) ham = hamiltonians.SymbolicHamiltonian(symham, backend=backend) - if calcterms: - _ = ham.terms final_matrix = ham.matrix - target_matrix = np.kron( - np.kron(matrices.X, matrices.I), np.kron(matrices.Z, matrices.I) + target_matrix = backend.np.kron( + backend.np.kron(backend.matrices.X, backend.matrices.I()), + backend.np.kron(backend.matrices.Z, backend.matrices.I()), ) target_matrix += 0.5 * np.kron( - np.kron(matrices.Y, matrices.Z), np.kron(matrices.I, matrices.I) + backend.np.kron(backend.matrices.Y, backend.matrices.Z), + backend.np.kron(backend.matrices.I(), backend.matrices.I()), ) - target_matrix += np.kron( - np.kron(matrices.Z, matrices.I), np.kron(matrices.X, matrices.I) + target_matrix += backend.np.kron( + backend.np.kron(backend.matrices.Z, backend.matrices.I()), + backend.np.kron(backend.matrices.X, backend.matrices.I()), ) backend.assert_allclose(final_matrix, target_matrix) diff --git a/tests/test_hamiltonians_models.py b/tests/test_hamiltonians_models.py index 5d2a2017d2..a5b52f5baf 100644 --- a/tests/test_hamiltonians_models.py +++ b/tests/test_hamiltonians_models.py @@ -32,28 +32,32 @@ def test_hamiltonian_models(backend, model, kwargs, filename): assert_regression_fixture(backend, matrix, filename) -@pytest.mark.parametrize("nqubits", [3, 4]) -@pytest.mark.parametrize( - "dense,calcterms", [(True, False), (False, False), (False, True)] -) -def test_maxcut(backend, nqubits, dense, calcterms): - size = 2**nqubits - ham = np.zeros(shape=(size, size), dtype=np.complex128) - for i in range(nqubits): - for j in range(nqubits): - h = np.eye(1) - for k in range(nqubits): - if (k == i) ^ (k == j): - h = np.kron(h, matrices.Z) - else: - h = np.kron(h, matrices.I) - M = np.eye(2**nqubits) - h - ham += M - target_ham = backend.cast(-ham / 2) - final_ham = hamiltonians.MaxCut(nqubits, dense, backend=backend) - if (not dense) and calcterms: - _ = final_ham.terms - backend.assert_allclose(final_ham.matrix, target_ham) +@pytest.mark.parametrize("nqubits,adj_matrix", zip([3, 4], [None, [[0, 1], [2, 3]]])) +@pytest.mark.parametrize("dense", [True, False]) +def test_maxcut(backend, nqubits, adj_matrix, dense): + if adj_matrix is not None: + with pytest.raises(RuntimeError): + final_ham = hamiltonians.MaxCut( + nqubits, dense, adj_matrix=adj_matrix, backend=backend + ) + else: + size = 2**nqubits + ham = np.zeros(shape=(size, size), dtype=np.complex128) + for i in range(nqubits): + for j in range(nqubits): + h = np.eye(1) + for k in range(nqubits): + if (k == i) ^ (k == j): + h = np.kron(h, matrices.Z) + else: + h = np.kron(h, matrices.I) + M = np.eye(2**nqubits) - h + ham += M + target_ham = backend.cast(-ham / 2) + final_ham = hamiltonians.MaxCut( + nqubits, dense, adj_matrix=adj_matrix, backend=backend + ) + backend.assert_allclose(final_ham.matrix, target_ham) @pytest.mark.parametrize("model", ["XXZ", "TFIM"]) diff --git a/tests/test_hamiltonians_symbolic.py b/tests/test_hamiltonians_symbolic.py index ff91e9fb1e..1b73abc50b 100644 --- a/tests/test_hamiltonians_symbolic.py +++ b/tests/test_hamiltonians_symbolic.py @@ -10,13 +10,15 @@ from qibo.symbols import I, Symbol, X, Y, Z -def symbolic_tfim(nqubits, h=1.0): +def symbolic_tfim(nqubits, backend, h=1.0): """Constructs symbolic Hamiltonian for TFIM.""" from qibo.symbols import X, Z - sham = -sum(Z(i) * Z(i + 1) for i in range(nqubits - 1)) - sham -= Z(0) * Z(nqubits - 1) - sham -= h * sum(X(i) for i in range(nqubits)) + sham = -sum( + Z(i, backend=backend) * Z(i + 1, backend=backend) for i in range(nqubits - 1) + ) + sham -= Z(0, backend=backend) * Z(nqubits - 1, backend=backend) + sham -= h * sum(X(i, backend=backend) for i in range(nqubits)) return sham @@ -27,128 +29,128 @@ def test_symbolic_hamiltonian_errors(backend): # Wrong type of symbolic expression with pytest.raises(TypeError): ham = SymbolicHamiltonian("test", backend=backend) - # Passing form with symbol that is not in ``symbol_map`` + # Passing form with symbol that is not a ``qibo.symbols.Symbol`` from qibo import matrices - Z, X = sympy.Symbol("Z"), sympy.Symbol("X") - symbol_map = {Z: (0, matrices.Z)} - with pytest.raises(ValueError): - ham = SymbolicHamiltonian(Z * X, symbol_map=symbol_map, backend=backend) + z, x = sympy.Symbol("z"), sympy.Symbol("x") + with pytest.raises(RuntimeError): + ham = SymbolicHamiltonian(z * x, backend=backend) # Invalid operation in Hamiltonian expresion - ham = SymbolicHamiltonian(sympy.cos(Z), symbol_map=symbol_map, backend=backend) + ham = SymbolicHamiltonian(sympy.cos(Z(0, backend=backend)), backend=backend) with pytest.raises(TypeError): dense = ham.dense +def test_symbolic_hamiltonian_form_setter(backend): + h = SymbolicHamiltonian(Z(0), backend=backend) + new_form = Z(0) * X(1) * Y(3) + h.form = new_form + assert h.form == new_form + assert h.nqubits == 4 + + +def test_symbolic_hamiltonian_dense(backend): + target_matrix = backend.cast( + Z(0, backend=backend).matrix @ Z(0, backend=backend).matrix + + X(0, backend=backend).matrix @ Y(0, backend=backend).matrix + + backend.matrices.I() + ) + form = Z(0) ** 2 + X(0) * Y(0) + 1 + sham = SymbolicHamiltonian(form, nqubits=1, backend=backend) + backend.assert_allclose(sham.dense.matrix, target_matrix) + + @pytest.mark.parametrize("nqubits", [3, 4]) -@pytest.mark.parametrize("calcterms", [False, True]) -def test_symbolictfim_hamiltonian_to_dense(backend, nqubits, calcterms): - final_ham = SymbolicHamiltonian(symbolic_tfim(nqubits, h=1), backend=backend) +def test_symbolictfim_hamiltonian_to_dense(backend, nqubits): + final_ham = SymbolicHamiltonian( + symbolic_tfim(nqubits, backend, h=1), backend=backend + ) target_ham = TFIM(nqubits, h=1, backend=backend) - if calcterms: - _ = final_ham.terms backend.assert_allclose(final_ham.matrix, target_ham.matrix, atol=1e-15) @pytest.mark.parametrize("nqubits", [3, 4]) -@pytest.mark.parametrize("calcterms", [False, True]) -def test_symbolicxxz_hamiltonian_to_dense(backend, nqubits, calcterms): - sham = sum(X(i) * X(i + 1) for i in range(nqubits - 1)) - sham += sum(Y(i) * Y(i + 1) for i in range(nqubits - 1)) - sham += 0.5 * sum(Z(i) * Z(i + 1) for i in range(nqubits - 1)) - sham += X(0) * X(nqubits - 1) + Y(0) * Y(nqubits - 1) + 0.5 * Z(0) * Z(nqubits - 1) +def test_symbolicxxz_hamiltonian_to_dense(backend, nqubits): + sham = sum( + X(i, backend=backend) * X(i + 1, backend=backend) for i in range(nqubits - 1) + ) + sham += sum( + Y(i, backend=backend) * Y(i + 1, backend=backend) for i in range(nqubits - 1) + ) + sham += 0.5 * sum( + Z(i, backend=backend) * Z(i + 1, backend=backend) for i in range(nqubits - 1) + ) + sham += ( + X(0, backend=backend) * X(nqubits - 1, backend=backend) + + Y(0, backend=backend) * Y(nqubits - 1, backend=backend) + + 0.5 * Z(0, backend=backend) * Z(nqubits - 1, backend=backend) + ) final_ham = SymbolicHamiltonian(sham, backend=backend) target_ham = XXZ(nqubits, backend=backend) - if calcterms: - _ = final_ham.terms backend.assert_allclose(final_ham.matrix, target_ham.matrix, atol=1e-15) @pytest.mark.parametrize("nqubits", [3]) -@pytest.mark.parametrize("calcterms", [False, True]) -@pytest.mark.parametrize("calcdense", [False, True]) -def test_symbolic_hamiltonian_scalar_mul(backend, nqubits, calcterms, calcdense): +def test_symbolic_hamiltonian_scalar_mul(backend, nqubits): """Test multiplication of Trotter Hamiltonian with scalar.""" - local_ham = SymbolicHamiltonian(symbolic_tfim(nqubits, h=1.0), backend=backend) + local_ham = SymbolicHamiltonian( + symbolic_tfim(nqubits, backend, h=1.0), backend=backend + ) target_ham = 2 * TFIM(nqubits, h=1.0, backend=backend) - if calcterms: - _ = local_ham.terms - if calcdense: - _ = local_ham.dense local_dense = (2 * local_ham).dense backend.assert_allclose(local_dense.matrix, target_ham.matrix) - local_ham = SymbolicHamiltonian(symbolic_tfim(nqubits, h=1.0), backend=backend) - if calcterms: - _ = local_ham.terms - if calcdense: - _ = local_ham.dense + local_ham = SymbolicHamiltonian( + symbolic_tfim(nqubits, backend, h=1.0), backend=backend + ) local_dense = (local_ham * 2).dense backend.assert_allclose(local_dense.matrix, target_ham.matrix) @pytest.mark.parametrize("nqubits", [4]) -@pytest.mark.parametrize("calcterms", [False, True]) -@pytest.mark.parametrize("calcdense", [False, True]) -def test_symbolic_hamiltonian_scalar_add(backend, nqubits, calcterms, calcdense): +def test_symbolic_hamiltonian_scalar_add(backend, nqubits): """Test addition of Trotter Hamiltonian with scalar.""" - local_ham = SymbolicHamiltonian(symbolic_tfim(nqubits, h=1.0), backend=backend) + local_ham = SymbolicHamiltonian( + symbolic_tfim(nqubits, backend, h=1.0), backend=backend + ) target_ham = 2 + TFIM(nqubits, h=1.0, backend=backend) - if calcterms: - _ = local_ham.terms - if calcdense: - _ = local_ham.dense local_dense = (2 + local_ham).dense backend.assert_allclose(local_dense.matrix, target_ham.matrix) - local_ham = SymbolicHamiltonian(symbolic_tfim(nqubits, h=1.0), backend=backend) - if calcterms: - _ = local_ham.terms - if calcdense: - _ = local_ham.dense + local_ham = SymbolicHamiltonian( + symbolic_tfim(nqubits, backend, h=1.0), backend=backend + ) local_dense = (local_ham + 2).dense backend.assert_allclose(local_dense.matrix, target_ham.matrix) @pytest.mark.parametrize("nqubits", [3]) -@pytest.mark.parametrize("calcterms", [False, True]) -@pytest.mark.parametrize("calcdense", [False, True]) -def test_symbolic_hamiltonian_scalar_sub(backend, nqubits, calcterms, calcdense): +def test_symbolic_hamiltonian_scalar_sub(backend, nqubits): """Test subtraction of Trotter Hamiltonian with scalar.""" - local_ham = SymbolicHamiltonian(symbolic_tfim(nqubits, h=1.0), backend=backend) + local_ham = SymbolicHamiltonian( + symbolic_tfim(nqubits, backend, h=1.0), backend=backend + ) target_ham = 2 - TFIM(nqubits, h=1.0, backend=backend) - if calcterms: - _ = local_ham.terms - if calcdense: - _ = local_ham.dense local_dense = (2 - local_ham).dense backend.assert_allclose(local_dense.matrix, target_ham.matrix) target_ham = TFIM(nqubits, h=1.0, backend=backend) - 2 - local_ham = SymbolicHamiltonian(symbolic_tfim(nqubits, h=1.0), backend=backend) - if calcterms: - _ = local_ham.terms - if calcdense: - _ = local_ham.dense + local_ham = SymbolicHamiltonian( + symbolic_tfim(nqubits, backend, h=1.0), backend=backend + ) local_dense = (local_ham - 2).dense backend.assert_allclose(local_dense.matrix, target_ham.matrix) @pytest.mark.parametrize("nqubits", [3]) -@pytest.mark.parametrize("calcterms", [False, True]) -@pytest.mark.parametrize("calcdense", [False, True]) -def test_symbolic_hamiltonian_operator_add_and_sub( - backend, nqubits, calcterms, calcdense -): +def test_symbolic_hamiltonian_operator_add_and_sub(backend, nqubits): """Test addition and subtraction between Trotter Hamiltonians.""" - local_ham1 = SymbolicHamiltonian(symbolic_tfim(nqubits, h=1.0), backend=backend) - local_ham2 = SymbolicHamiltonian(symbolic_tfim(nqubits, h=0.5), backend=backend) - if calcterms: - _ = local_ham1.terms - _ = local_ham2.terms - if calcdense: - _ = local_ham1.dense - _ = local_ham2.dense + local_ham1 = SymbolicHamiltonian( + symbolic_tfim(nqubits, backend, h=1.0), backend=backend + ) + local_ham2 = SymbolicHamiltonian( + symbolic_tfim(nqubits, backend, h=0.5), backend=backend + ) local_ham = local_ham1 + local_ham2 target_ham = TFIM(nqubits, h=1.0, backend=backend) + TFIM( nqubits, h=0.5, backend=backend @@ -156,14 +158,12 @@ def test_symbolic_hamiltonian_operator_add_and_sub( dense = local_ham.dense backend.assert_allclose(dense.matrix, target_ham.matrix) - local_ham1 = SymbolicHamiltonian(symbolic_tfim(nqubits, h=1.0), backend=backend) - local_ham2 = SymbolicHamiltonian(symbolic_tfim(nqubits, h=0.5), backend=backend) - if calcterms: - _ = local_ham1.terms - _ = local_ham2.terms - if calcdense: - _ = local_ham1.dense - _ = local_ham2.dense + local_ham1 = SymbolicHamiltonian( + symbolic_tfim(nqubits, backend, h=1.0), backend=backend + ) + local_ham2 = SymbolicHamiltonian( + symbolic_tfim(nqubits, backend, h=0.5), backend=backend + ) local_ham = local_ham1 - local_ham2 target_ham = TFIM(nqubits, h=1.0, backend=backend) - TFIM( nqubits, h=0.5, backend=backend @@ -174,13 +174,22 @@ def test_symbolic_hamiltonian_operator_add_and_sub( # Test multiplication and sum target = XXZ(nqubits, backend=backend) term_1 = SymbolicHamiltonian( - X(0) * X(1) + X(1) * X(2) + X(0) * X(2), backend=backend + X(0, backend=backend) * X(1, backend=backend) + + X(1, backend=backend) * X(2, backend=backend) + + X(0, backend=backend) * X(2, backend=backend), + backend=backend, ) term_2 = SymbolicHamiltonian( - Y(0) * Y(1) + Y(1) * Y(2) + Y(0) * Y(2), backend=backend + Y(0, backend=backend) * Y(1, backend=backend) + + Y(1, backend=backend) * Y(2, backend=backend) + + Y(0, backend=backend) * Y(2, backend=backend), + backend=backend, ) term_3 = SymbolicHamiltonian( - Z(0) * Z(1) + Z(1) * Z(2) + Z(0) * Z(2), backend=backend + Z(0, backend=backend) * Z(1, backend=backend) + + Z(1, backend=backend) * Z(2, backend=backend) + + Z(0, backend=backend) * Z(2, backend=backend), + backend=backend, ) hamiltonian = term_1 + term_2 + 0.5 * term_3 matrix = hamiltonian.dense.matrix @@ -189,19 +198,15 @@ def test_symbolic_hamiltonian_operator_add_and_sub( @pytest.mark.parametrize("nqubits", [5]) -@pytest.mark.parametrize("calcterms", [False, True]) -@pytest.mark.parametrize("calcdense", [False, True]) -def test_symbolic_hamiltonian_hamiltonianmatmul(backend, nqubits, calcterms, calcdense): - local_ham1 = SymbolicHamiltonian(symbolic_tfim(nqubits, h=1.0), backend=backend) - local_ham2 = SymbolicHamiltonian(symbolic_tfim(nqubits, h=0.5), backend=backend) +def test_symbolic_hamiltonian_hamiltonianmatmul(backend, nqubits): + local_ham1 = SymbolicHamiltonian( + symbolic_tfim(nqubits, backend, h=1.0), backend=backend + ) + local_ham2 = SymbolicHamiltonian( + symbolic_tfim(nqubits, backend, h=0.5), backend=backend + ) dense_ham1 = TFIM(nqubits, h=1.0, backend=backend) dense_ham2 = TFIM(nqubits, h=0.5, backend=backend) - if calcterms: - _ = local_ham1.terms - _ = local_ham2.terms - if calcdense: - _ = local_ham1.dense - _ = local_ham2.dense local_matmul = local_ham1 @ local_ham2 target_matmul = dense_ham1 @ dense_ham2 backend.assert_allclose(local_matmul.matrix, target_matmul.matrix) @@ -209,33 +214,26 @@ def test_symbolic_hamiltonian_hamiltonianmatmul(backend, nqubits, calcterms, cal @pytest.mark.parametrize("nqubits", [3, 4]) @pytest.mark.parametrize("density_matrix", [False, True]) -@pytest.mark.parametrize("calcterms", [False, True]) -def test_symbolic_hamiltonian_matmul(backend, nqubits, density_matrix, calcterms): +def test_symbolic_hamiltonian_matmul(backend, nqubits, density_matrix): state = ( random_density_matrix(2**nqubits, backend=backend) if density_matrix else random_statevector(2**nqubits, backend=backend) ) - local_ham = SymbolicHamiltonian(symbolic_tfim(nqubits, h=1.0), backend=backend) + local_ham = SymbolicHamiltonian( + symbolic_tfim(nqubits, backend, h=1.0), backend=backend + ) dense_ham = TFIM(nqubits, h=1.0, backend=backend) - if calcterms: - _ = local_ham.terms local_matmul = local_ham @ state target_matmul = dense_ham @ state backend.assert_allclose(local_matmul, target_matmul) @pytest.mark.parametrize("nqubits,normalize", [(3, False), (4, False)]) -@pytest.mark.parametrize("calcterms", [False, True]) -@pytest.mark.parametrize("calcdense", [False, True]) -def test_symbolic_hamiltonian_state_expectation( - backend, nqubits, normalize, calcterms, calcdense -): - local_ham = SymbolicHamiltonian(symbolic_tfim(nqubits, h=1.0), backend=backend) + 2 - if calcterms: - _ = local_ham.terms - if calcdense: - _ = local_ham.dense +def test_symbolic_hamiltonian_state_expectation(backend, nqubits, normalize): + local_ham = ( + SymbolicHamiltonian(symbolic_tfim(nqubits, backend, h=1.0), backend=backend) + 2 + ) dense_ham = TFIM(nqubits, h=1.0, backend=backend) + 2 state = random_statevector(2**nqubits, backend=backend) @@ -250,20 +248,14 @@ def test_symbolic_hamiltonian_state_expectation( @pytest.mark.parametrize("give_nqubits", [False, True]) -@pytest.mark.parametrize("calcterms", [False, True]) -@pytest.mark.parametrize("calcdense", [False, True]) def test_symbolic_hamiltonian_state_expectation_different_nqubits( - backend, give_nqubits, calcterms, calcdense + backend, give_nqubits ): - expr = symbolic_tfim(3, h=1.0) + expr = symbolic_tfim(3, backend, h=1.0) if give_nqubits: local_ham = SymbolicHamiltonian(expr, nqubits=5, backend=backend) else: local_ham = SymbolicHamiltonian(expr, backend=backend) - if calcterms: - _ = local_ham.terms - if calcdense: - _ = local_ham.dense dense_ham = TFIM(3, h=1.0, backend=backend) dense_matrix = np.kron(backend.to_numpy(dense_ham.matrix), np.eye(4)) @@ -312,15 +304,14 @@ def test_hamiltonian_expectation_from_samples(backend, observable, qubit_map): @pytest.mark.parametrize("density_matrix", [False, True]) -@pytest.mark.parametrize("calcterms", [False, True]) -def test_symbolic_hamiltonian_abstract_symbol_ev(backend, density_matrix, calcterms): +def test_symbolic_hamiltonian_abstract_symbol_ev(backend, density_matrix): from qibo.symbols import Symbol, X matrix = np.random.random((2, 2)) - form = X(0) * Symbol(1, matrix) + Symbol(0, matrix) * X(1) + form = X(0, backend=backend) * Symbol(1, matrix, backend=backend) + Symbol( + 0, matrix, backend=backend + ) * X(1, backend=backend) local_ham = SymbolicHamiltonian(form, backend=backend) - if calcterms: - _ = local_ham.terms state = ( random_density_matrix(4, backend=backend) @@ -334,8 +325,8 @@ def test_symbolic_hamiltonian_abstract_symbol_ev(backend, density_matrix, calcte def test_trotter_hamiltonian_operation_errors(backend): """Test errors in ``SymbolicHamiltonian`` addition and subtraction.""" - h1 = SymbolicHamiltonian(symbolic_tfim(3, h=1.0), backend=backend) - h2 = SymbolicHamiltonian(symbolic_tfim(4, h=1.0), backend=backend) + h1 = SymbolicHamiltonian(symbolic_tfim(3, backend, h=1.0), backend=backend) + h2 = SymbolicHamiltonian(symbolic_tfim(4, backend, h=1.0), backend=backend) with pytest.raises(RuntimeError): h = h1 + h2 with pytest.raises(RuntimeError): @@ -355,8 +346,6 @@ def test_trotter_hamiltonian_operation_errors(backend): with pytest.raises(NotImplementedError): h = h1 @ np.ones((2, 2, 2, 2)) h2 = XXZ(3, dense=False, backend=backend) - with pytest.raises(NotImplementedError): - h = h1 @ h2 def test_symbolic_hamiltonian_with_constant(backend): diff --git a/tests/test_hamiltonians_terms.py b/tests/test_hamiltonians_terms.py index 0addb08adc..14a79ae1ea 100644 --- a/tests/test_hamiltonians_terms.py +++ b/tests/test_hamiltonians_terms.py @@ -11,11 +11,11 @@ def test_hamiltonian_term_initialization(backend): """Test initialization and matrix assignment of ``HamiltonianTerm``.""" matrix = np.random.random((2, 2)) - term = terms.HamiltonianTerm(matrix, 0) + term = terms.HamiltonianTerm(matrix, 0, backend=backend) assert term.target_qubits == (0,) backend.assert_allclose(term.matrix, matrix) matrix = np.random.random((4, 4)) - term = terms.HamiltonianTerm(matrix, 2, 3) + term = terms.HamiltonianTerm(matrix, 2, 3, backend=backend) assert term.target_qubits == (2, 3) backend.assert_allclose(term.matrix, matrix) @@ -42,7 +42,7 @@ def test_hamiltonian_term_gates(backend): """Test gate application of ``HamiltonianTerm``.""" nqubits = 4 matrix = np.random.random((nqubits, nqubits)) - term = terms.HamiltonianTerm(matrix, 1, 2) + term = terms.HamiltonianTerm(matrix, 1, 2, backend=backend) gate = term.gate assert gate.target_qubits == (1, 2) backend.assert_allclose(gate.matrix(backend), matrix) @@ -62,8 +62,8 @@ def test_hamiltonian_term_exponentiation(backend): from scipy.linalg import expm # pylint: disable=C0415 matrix = np.random.random((2, 2)) - term = terms.HamiltonianTerm(matrix, 1) - exp_matrix = expm(-0.5j * matrix) + term = terms.HamiltonianTerm(matrix, 1, backend=backend) + exp_matrix = backend.cast(expm(-0.5j * matrix)) backend.assert_allclose(term.exp(0.5), exp_matrix) initial_state = random_statevector(4, backend=backend) @@ -76,7 +76,7 @@ def test_hamiltonian_term_exponentiation(backend): def test_hamiltonian_term_mul(backend): """Test scalar multiplication of ``HamiltonianTerm``.""" matrix = np.random.random((4, 4)) - term = terms.HamiltonianTerm(matrix, 0, 2) + term = terms.HamiltonianTerm(matrix, 0, 2, backend=backend) mterm = 2 * term assert mterm.target_qubits == term.target_qubits backend.assert_allclose(mterm.matrix, 2 * matrix) @@ -89,8 +89,8 @@ def test_hamiltonian_term_merge(backend): """Test ``HamiltonianTerm.merge``.""" matrix1 = np.random.random((2, 2)) matrix2 = np.random.random((4, 4)) - term1 = terms.HamiltonianTerm(matrix1, 1) - term2 = terms.HamiltonianTerm(matrix2, 0, 1) + term1 = terms.HamiltonianTerm(matrix1, 1, backend=backend) + term2 = terms.HamiltonianTerm(matrix2, 0, 1, backend=backend) mterm = term2.merge(term1) target_matrix = np.kron(np.eye(2), matrix1) + matrix2 assert mterm.target_qubits == (0, 1) @@ -99,26 +99,17 @@ def test_hamiltonian_term_merge(backend): term1.merge(term2) -@pytest.mark.parametrize("use_symbols", [True, False]) -def test_symbolic_term_creation(backend, use_symbols): +def test_symbolic_term_creation(backend): """Test creating ``SymbolicTerm`` from sympy expression.""" - if use_symbols: - from qibo.symbols import X, Y - - expression = X(0) * Y(1) * X(1) - symbol_map = {} - else: - import sympy - - x0, x1, y1 = sympy.symbols("X0 X1 Y1", commutative=False) - expression = x0 * y1 * x1 - symbol_map = {x0: (0, matrices.X), x1: (1, matrices.X), y1: (1, matrices.Y)} - term = terms.SymbolicTerm(2, expression, symbol_map) + from qibo.symbols import X, Y + + expression = X(0) * Y(1) * X(1) + term = terms.SymbolicTerm(2, expression, backend=backend) assert term.target_qubits == (0, 1) assert len(term.matrix_map) == 2 - backend.assert_allclose(term.matrix_map.get(0)[0], matrices.X) - backend.assert_allclose(term.matrix_map.get(1)[0], matrices.Y) - backend.assert_allclose(term.matrix_map.get(1)[1], matrices.X) + backend.assert_allclose(term.matrix_map.get(0)[0], backend.matrices.X) + backend.assert_allclose(term.matrix_map.get(1)[0], backend.matrices.Y) + backend.assert_allclose(term.matrix_map.get(1)[1], backend.matrices.X) def test_symbolic_term_with_power_creation(backend): @@ -126,14 +117,14 @@ def test_symbolic_term_with_power_creation(backend): from qibo.symbols import X, Z expression = X(0) ** 4 * Z(1) ** 2 * X(2) - term = terms.SymbolicTerm(2, expression) + term = terms.SymbolicTerm(2, expression, backend=backend) assert term.target_qubits == (2,) assert len(term.matrix_map) == 1 assert term.coefficient == 2 - backend.assert_allclose(term.matrix_map.get(2), [matrices.X]) + backend.assert_allclose(term.matrix_map.get(2), [backend.matrices.X]) -def test_symbolic_term_with_imag_creation(backend): +def test_symbolic_term_with_imag_creation(): """Test creating ``SymbolicTerm`` from sympy expression that contains imaginary coefficients.""" from qibo.symbols import Y @@ -148,10 +139,10 @@ def test_symbolic_term_matrix(backend): from qibo.symbols import X, Y, Z expression = X(0) * Y(1) * Z(2) * X(1) - term = terms.SymbolicTerm(2, expression) + term = terms.SymbolicTerm(2, expression, backend=backend) assert term.target_qubits == (0, 1, 2) target_matrix = np.kron(matrices.X, matrices.Y @ matrices.X) - target_matrix = 2 * np.kron(target_matrix, matrices.Z) + target_matrix = backend.cast(2 * np.kron(target_matrix, matrices.Z)) backend.assert_allclose(term.matrix, target_matrix) @@ -160,9 +151,11 @@ def test_symbolic_term_mul(backend): from qibo.symbols import X, Y, Z expression = Y(2) * Z(3) * X(2) * X(3) - term = terms.SymbolicTerm(1, expression) + term = terms.SymbolicTerm(1, expression, backend=backend) assert term.target_qubits == (2, 3) - target_matrix = np.kron(matrices.Y @ matrices.X, matrices.Z @ matrices.X) + target_matrix = backend.cast( + np.kron(matrices.Y @ matrices.X, matrices.Z @ matrices.X) + ) backend.assert_allclose(term.matrix, target_matrix) backend.assert_allclose((2 * term).matrix, 2 * target_matrix) backend.assert_allclose((term * 3).matrix, 3 * target_matrix) @@ -200,10 +193,10 @@ def test_symbolic_term_merge(backend): from qibo.symbols import X, Z matrix = np.random.random((4, 4)) - term1 = terms.HamiltonianTerm(matrix, 0, 1) - term2 = terms.SymbolicTerm(1, X(0) * Z(1)) + term1 = terms.HamiltonianTerm(matrix, 0, 1, backend=backend) + term2 = terms.SymbolicTerm(1, X(0) * Z(1), backend=backend) term = term1.merge(term2) - target_matrix = matrix + np.kron(matrices.X, matrices.Z) + target_matrix = backend.cast(matrix + np.kron(matrices.X, matrices.Z)) backend.assert_allclose(term.matrix, target_matrix) @@ -227,13 +220,13 @@ def test_term_group_to_term(backend): from qibo.symbols import X, Z matrix = np.random.random((8, 8)) - term1 = terms.HamiltonianTerm(matrix, 0, 1, 3) - term2 = terms.SymbolicTerm(1, X(0) * Z(3)) - term3 = terms.SymbolicTerm(2, X(1)) + term1 = terms.HamiltonianTerm(matrix, 0, 1, 3, backend=backend) + term2 = terms.SymbolicTerm(1, X(0) * Z(3), backend=backend) + term3 = terms.SymbolicTerm(2, X(1), backend=backend) group = terms.TermGroup(term1) group.append(term2) group.append(term3) matrix2 = np.kron(np.kron(matrices.X, np.eye(2)), matrices.Z) matrix3 = np.kron(np.kron(np.eye(2), matrices.X), np.eye(2)) - target_matrix = matrix + matrix2 + 2 * matrix3 + target_matrix = backend.cast(matrix + matrix2 + 2 * matrix3) backend.assert_allclose(group.term.matrix, target_matrix) diff --git a/tests/test_hamiltonians_trotter.py b/tests/test_hamiltonians_trotter.py index 0c2d2f1756..a6855b82f8 100644 --- a/tests/test_hamiltonians_trotter.py +++ b/tests/test_hamiltonians_trotter.py @@ -96,68 +96,11 @@ def test_trotter_hamiltonian_matmul(backend, nqubits, normalize): backend.assert_allclose(trotter_matmul, target_matmul) -def test_trotter_hamiltonian_three_qubit_term(backend): - """Test creating ``TrotterHamiltonian`` with three qubit term.""" - from scipy.linalg import expm - - from qibo.hamiltonians.terms import HamiltonianTerm - - numpy_backend = NumpyBackend() - - m1 = random_hermitian(2**3, backend=numpy_backend) - m2 = random_hermitian(2**2, backend=numpy_backend) - m3 = random_hermitian(2**1, backend=numpy_backend) - - terms = [ - HamiltonianTerm(m1, 0, 1, 2), - HamiltonianTerm(m2, 2, 3), - HamiltonianTerm(m3, 1), - ] - m1 = backend.cast(m1, dtype=m1.dtype) - m2 = backend.cast(m2, dtype=m2.dtype) - m3 = backend.cast(m3, dtype=m3.dtype) - - ham = hamiltonians.SymbolicHamiltonian(backend=backend) - ham.terms = terms - - # Test that the `TrotterHamiltonian` dense matrix is correct - eye = np.eye(2, dtype=complex) - eye = backend.cast(eye, dtype=eye.dtype) - mm1 = backend.np.kron(m1, eye) - mm2 = backend.np.kron(backend.np.kron(eye, eye), m2) - mm3 = backend.np.kron(backend.np.kron(eye, m3), backend.np.kron(eye, eye)) - target_ham = hamiltonians.Hamiltonian(4, mm1 + mm2 + mm3, backend=backend) - backend.assert_allclose(ham.matrix, target_ham.matrix) - - dt = 1e-2 - initial_state = random_statevector(2**4, backend=backend) - circuit = ham.circuit(dt=dt) - final_state = backend.execute_circuit( - circuit, backend.np.copy(initial_state) - ).state() - mm1 = backend.to_numpy(mm1) - mm2 = backend.to_numpy(mm2) - mm3 = backend.to_numpy(mm3) - u = [expm(-0.5j * dt * (mm1 + mm3)), expm(-0.5j * dt * mm2)] - u = backend.cast(u) - target_state = backend.np.matmul(u[1], backend.np.matmul(u[0], initial_state)) - target_state = backend.np.matmul(u[0], backend.np.matmul(u[1], target_state)) - backend.assert_allclose(final_state, target_state) - - def test_symbolic_hamiltonian_circuit_different_dts(backend): """Issue: https://github.com/qiboteam/qibo/issues/1357.""" - ham = hamiltonians.SymbolicHamiltonian(symbols.Z(0)) + ham = hamiltonians.SymbolicHamiltonian(symbols.Z(0), backend=backend) a = ham.circuit(0.1) b = ham.circuit(0.1) matrix1 = ham.circuit(0.2).unitary(backend) matrix2 = (a + b).unitary(backend) backend.assert_allclose(matrix1, matrix2) - - -def test_old_trotter_hamiltonian_errors(): - """Check errors when creating the deprecated ``TrotterHamiltonian`` object.""" - with pytest.raises(NotImplementedError): - h = hamiltonians.TrotterHamiltonian() - with pytest.raises(NotImplementedError): - h = hamiltonians.TrotterHamiltonian.from_symbolic(0, 1) diff --git a/tests/test_models_error_mitigation.py b/tests/test_models_error_mitigation.py index 62bd804f5e..a73f70cf7a 100644 --- a/tests/test_models_error_mitigation.py +++ b/tests/test_models_error_mitigation.py @@ -342,7 +342,7 @@ def test_ics(backend, nqubits, noise, full_output, readout): # Define the circuit c = get_circuit(nqubits, nqubits - 1) # Define the observable - obs = np.prod([Z(i) for i in range(nqubits - 1)]) + obs = np.prod([Z(i, backend=backend) for i in range(nqubits - 1)]) obs_exact = SymbolicHamiltonian(obs, nqubits=nqubits, backend=backend) obs = SymbolicHamiltonian(obs, backend=backend) # Noise-free expected value diff --git a/tests/test_states.py b/tests/test_states.py index 3c885c13fd..0bf559648a 100644 --- a/tests/test_states.py +++ b/tests/test_states.py @@ -91,8 +91,12 @@ def test_state_probabilities(backend, density_matrix): def test_expectation_from_samples(backend): # fix seed to use the same samples in every execution np.random.seed(123) - obs0 = 2 * Z(0) * Z(1) + Z(0) * Z(2) - obs1 = 2 * Z(0) * Z(1) + Z(0) * Z(2) * I(3) + obs0 = 2 * Z(0, backend=backend) * Z(1, backend=backend) + Z( + 0, backend=backend + ) * Z(2, backend=backend) + obs1 = 2 * Z(0, backend=backend) * Z(1, backend=backend) + Z( + 0, backend=backend + ) * Z(2, backend=backend) * I(3, backend=backend) h_sym = hamiltonians.SymbolicHamiltonian(obs0, backend=backend) h_dense = hamiltonians.Hamiltonian(3, h_sym.matrix, backend=backend) h1 = hamiltonians.SymbolicHamiltonian(obs1, backend=backend)