From 5f2528ff5decf51ffa10b85b2400204a523fc13f Mon Sep 17 00:00:00 2001 From: lillian542 Date: Fri, 22 Mar 2024 16:11:02 -0400 Subject: [PATCH 01/59] add use_new_opmath variable --- .github/workflows/unit-test.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index c4d7d792764..af2151899da 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -94,6 +94,11 @@ on: required: false type: string default: '' + use_new_opmath: + description: Whether to use the new op_math or not when running the tests + required: false + type: bool + default: true jobs: test: @@ -169,6 +174,7 @@ jobs: COV_CORE_CONFIG: .coveragerc COV_CORE_DATAFILE: .coverage.eager # Calling PyTest by invoking Python first as that adds the current directory to sys.path + run: python -m import pennylane as qml && qml.operation.__use_new_opmath = ${{ inputs.use_new_opmath }} run: python -m pytest ${{ inputs.pytest_test_directory }} ${{ steps.pytest_args.outputs.args }} ${{ env.PYTEST_MARKER }} - name: Adjust coverage file for Codecov From 3e1905e49654a0485605a37d2fa5e4814fc50c9d Mon Sep 17 00:00:00 2001 From: lillian542 Date: Fri, 22 Mar 2024 16:11:16 -0400 Subject: [PATCH 02/59] [ci skip] From 27352dff118c316d9c4f0eeb5c5d2eec2709ec24 Mon Sep 17 00:00:00 2001 From: lillian542 Date: Fri, 22 Mar 2024 16:11:58 -0400 Subject: [PATCH 03/59] add initial legacy_opmath workflow --- .github/workflows/legacy_op_math.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 .github/workflows/legacy_op_math.yml diff --git a/.github/workflows/legacy_op_math.yml b/.github/workflows/legacy_op_math.yml new file mode 100644 index 00000000000..3fdf98a33e8 --- /dev/null +++ b/.github/workflows/legacy_op_math.yml @@ -0,0 +1,14 @@ +name: Legacy opmath tests + +on: + schedule: + - cron: "0 0 2 * *" + workflow_dispatch: + +jobs: + tests: + uses: ./.github/workflows/interface-unit-tests.yml + with: + branch: 'master' + run_lightened_ci: false + use_new_opmath: false \ No newline at end of file From a85f990fb3668aed9a31accb61d444fd8fb9bc50 Mon Sep 17 00:00:00 2001 From: lillian542 Date: Wed, 3 Apr 2024 14:53:49 -0400 Subject: [PATCH 04/59] trigger ci From 60f61a77ceb48e841109cea973f6264a6ab57b91 Mon Sep 17 00:00:00 2001 From: lillian542 <38584660+lillian542@users.noreply.github.com> Date: Wed, 3 Apr 2024 15:05:22 -0400 Subject: [PATCH 05/59] for science --- .github/workflows/unit-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index af2151899da..dbc47c63f7a 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -174,7 +174,7 @@ jobs: COV_CORE_CONFIG: .coveragerc COV_CORE_DATAFILE: .coverage.eager # Calling PyTest by invoking Python first as that adds the current directory to sys.path - run: python -m import pennylane as qml && qml.operation.__use_new_opmath = ${{ inputs.use_new_opmath }} + # run: python -m import pennylane as qml && qml.operation.__use_new_opmath = ${{ inputs.use_new_opmath }} run: python -m pytest ${{ inputs.pytest_test_directory }} ${{ steps.pytest_args.outputs.args }} ${{ env.PYTEST_MARKER }} - name: Adjust coverage file for Codecov From da9a5d8f91c720cc0f427b01f3c68a56458e6ad1 Mon Sep 17 00:00:00 2001 From: lillian542 Date: Wed, 3 Apr 2024 15:12:36 -0400 Subject: [PATCH 06/59] see if this triggers full ci --- pennylane/pulse/rydberg.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pennylane/pulse/rydberg.py b/pennylane/pulse/rydberg.py index 4e2adbfbdba..4abaea567c6 100644 --- a/pennylane/pulse/rydberg.py +++ b/pennylane/pulse/rydberg.py @@ -123,6 +123,11 @@ def circuit(): ) +def test_for_ci(): + """docstring for pylint""" + return 3 + + def rydberg_drive(amplitude, phase, detuning, wires): r"""Returns a :class:`ParametrizedHamiltonian` representing the action of a driving laser field From f97f29581034726bfbaab3beaed714e24358d3e8 Mon Sep 17 00:00:00 2001 From: lillian542 <38584660+lillian542@users.noreply.github.com> Date: Wed, 3 Apr 2024 15:14:07 -0400 Subject: [PATCH 07/59] or does this make ci run? --- .github/workflows/unit-test.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index dbc47c63f7a..ee21328f9e8 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -94,11 +94,11 @@ on: required: false type: string default: '' - use_new_opmath: - description: Whether to use the new op_math or not when running the tests - required: false - type: bool - default: true + # use_new_opmath: + # description: Whether to use the new op_math or not when running the tests + # required: false + # type: bool + # default: true jobs: test: From 3699cf7a9e61ac0ea190eaf7b14a0ee4ed12527f Mon Sep 17 00:00:00 2001 From: lillian542 Date: Wed, 3 Apr 2024 15:18:12 -0400 Subject: [PATCH 08/59] will ci still run? --- .github/workflows/unit-test.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index ee21328f9e8..dc18dbf5a49 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -94,11 +94,11 @@ on: required: false type: string default: '' - # use_new_opmath: - # description: Whether to use the new op_math or not when running the tests - # required: false - # type: bool - # default: true + use_new_opmath: + description: Whether to use the new op_math or not when running the tests + required: false + type: boolean + default: true jobs: test: From 639f411e60070fef2389ad79e046b53eddae4b68 Mon Sep 17 00:00:00 2001 From: lillian542 Date: Wed, 3 Apr 2024 15:23:09 -0400 Subject: [PATCH 09/59] undo previous test change --- pennylane/pulse/rydberg.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/pennylane/pulse/rydberg.py b/pennylane/pulse/rydberg.py index 4abaea567c6..4e2adbfbdba 100644 --- a/pennylane/pulse/rydberg.py +++ b/pennylane/pulse/rydberg.py @@ -123,11 +123,6 @@ def circuit(): ) -def test_for_ci(): - """docstring for pylint""" - return 3 - - def rydberg_drive(amplitude, phase, detuning, wires): r"""Returns a :class:`ParametrizedHamiltonian` representing the action of a driving laser field From 4d2657d2fe013b352e1e95b0cf2f286d6b7a728a Mon Sep 17 00:00:00 2001 From: lillian542 <38584660+lillian542@users.noreply.github.com> Date: Wed, 3 Apr 2024 15:24:09 -0400 Subject: [PATCH 10/59] try to add line explicitly setting __use_new_opmath --- .github/workflows/unit-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index dc18dbf5a49..81c59292e32 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -174,7 +174,7 @@ jobs: COV_CORE_CONFIG: .coveragerc COV_CORE_DATAFILE: .coverage.eager # Calling PyTest by invoking Python first as that adds the current directory to sys.path - # run: python -m import pennylane as qml && qml.operation.__use_new_opmath = ${{ inputs.use_new_opmath }} + run: python -m import pennylane as qml && qml.operation.__use_new_opmath = ${{ inputs.use_new_opmath }} run: python -m pytest ${{ inputs.pytest_test_directory }} ${{ steps.pytest_args.outputs.args }} ${{ env.PYTEST_MARKER }} - name: Adjust coverage file for Codecov From 8ef1ac8c84f9811c1c0796f134c10d2f223f21c1 Mon Sep 17 00:00:00 2001 From: lillian542 Date: Wed, 3 Apr 2024 15:27:41 -0400 Subject: [PATCH 11/59] fix syntax for two line run statement --- .github/workflows/unit-test.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index 81c59292e32..55b6726f9ac 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -174,8 +174,9 @@ jobs: COV_CORE_CONFIG: .coveragerc COV_CORE_DATAFILE: .coverage.eager # Calling PyTest by invoking Python first as that adds the current directory to sys.path - run: python -m import pennylane as qml && qml.operation.__use_new_opmath = ${{ inputs.use_new_opmath }} - run: python -m pytest ${{ inputs.pytest_test_directory }} ${{ steps.pytest_args.outputs.args }} ${{ env.PYTEST_MARKER }} + run: | + python -m import pennylane as qml && qml.operation.__use_new_opmath = ${{ inputs.use_new_opmath }} + python -m pytest ${{ inputs.pytest_test_directory }} ${{ steps.pytest_args.outputs.args }} ${{ env.PYTEST_MARKER }} - name: Adjust coverage file for Codecov if: inputs.pipeline_mode == 'unit-tests' From cbaef13cf69be8e9b8c3b2afac41c696e9174a93 Mon Sep 17 00:00:00 2001 From: lillian542 Date: Wed, 3 Apr 2024 15:59:04 -0400 Subject: [PATCH 12/59] temporarily run on pull request --- .github/workflows/legacy_op_math.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/legacy_op_math.yml b/.github/workflows/legacy_op_math.yml index 3fdf98a33e8..cfdae0d7b9f 100644 --- a/.github/workflows/legacy_op_math.yml +++ b/.github/workflows/legacy_op_math.yml @@ -3,6 +3,7 @@ name: Legacy opmath tests on: schedule: - cron: "0 0 2 * *" + pull_request: workflow_dispatch: jobs: From 742d548450a813c24a4e7bec69051acd7c9967f8 Mon Sep 17 00:00:00 2001 From: lillian542 Date: Wed, 3 Apr 2024 16:00:39 -0400 Subject: [PATCH 13/59] don't run on pull requests --- .github/workflows/legacy_op_math.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/legacy_op_math.yml b/.github/workflows/legacy_op_math.yml index cfdae0d7b9f..3fdf98a33e8 100644 --- a/.github/workflows/legacy_op_math.yml +++ b/.github/workflows/legacy_op_math.yml @@ -3,7 +3,6 @@ name: Legacy opmath tests on: schedule: - cron: "0 0 2 * *" - pull_request: workflow_dispatch: jobs: From c823f14c89806eac73b1dfa67ee1c8cc2c8ba58a Mon Sep 17 00:00:00 2001 From: lillian542 Date: Wed, 3 Apr 2024 16:11:47 -0400 Subject: [PATCH 14/59] also add variable to interface-unit-tests --- .github/workflows/interface-unit-tests.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/interface-unit-tests.yml b/.github/workflows/interface-unit-tests.yml index d103c73a754..68c32a1d67c 100644 --- a/.github/workflows/interface-unit-tests.yml +++ b/.github/workflows/interface-unit-tests.yml @@ -33,6 +33,11 @@ on: required: false type: string default: '' + use_new_opmath: + description: Whether to use the new op_math or not when running the tests + required: false + type: boolean + default: true jobs: setup-ci-load: From 9a30cd5213f04f06595794127d299caec09c99ff Mon Sep 17 00:00:00 2001 From: lillian542 <38584660+lillian542@users.noreply.github.com> Date: Wed, 3 Apr 2024 16:21:26 -0400 Subject: [PATCH 15/59] try this --- .github/workflows/legacy_op_math.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/legacy_op_math.yml b/.github/workflows/legacy_op_math.yml index 3fdf98a33e8..334c41523f2 100644 --- a/.github/workflows/legacy_op_math.yml +++ b/.github/workflows/legacy_op_math.yml @@ -11,4 +11,4 @@ jobs: with: branch: 'master' run_lightened_ci: false - use_new_opmath: false \ No newline at end of file + # use_new_opmath: false \ No newline at end of file From 52248a925e641130dfe51f9ec28f40007f37736f Mon Sep 17 00:00:00 2001 From: lillian542 Date: Wed, 3 Apr 2024 16:29:48 -0400 Subject: [PATCH 16/59] run on PR --- .github/workflows/legacy_op_math.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/legacy_op_math.yml b/.github/workflows/legacy_op_math.yml index 334c41523f2..389647bd657 100644 --- a/.github/workflows/legacy_op_math.yml +++ b/.github/workflows/legacy_op_math.yml @@ -3,6 +3,7 @@ name: Legacy opmath tests on: schedule: - cron: "0 0 2 * *" + pull_request: workflow_dispatch: jobs: From 8cbd9e27097e1387afdf0ad25a075dbb961e14ac Mon Sep 17 00:00:00 2001 From: lillian542 Date: Wed, 3 Apr 2024 16:38:20 -0400 Subject: [PATCH 17/59] uncomment use_new_opmath kwarg --- .github/workflows/legacy_op_math.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/legacy_op_math.yml b/.github/workflows/legacy_op_math.yml index 389647bd657..cfdae0d7b9f 100644 --- a/.github/workflows/legacy_op_math.yml +++ b/.github/workflows/legacy_op_math.yml @@ -12,4 +12,4 @@ jobs: with: branch: 'master' run_lightened_ci: false - # use_new_opmath: false \ No newline at end of file + use_new_opmath: false \ No newline at end of file From 8188231a8fda0c59b61867360622ea78738df8fd Mon Sep 17 00:00:00 2001 From: lillian542 Date: Wed, 3 Apr 2024 17:01:20 -0400 Subject: [PATCH 18/59] sanity check that tests are running as expected --- tests/test_operation.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/test_operation.py b/tests/test_operation.py index b473f4c5b39..f0fa8ecf334 100644 --- a/tests/test_operation.py +++ b/tests/test_operation.py @@ -46,6 +46,18 @@ I_broadcasted = I[pnp.newaxis] +def test_that_opmath_is_enabled(): + """Confirm that the tests are running by default with new_opmath enabled""" + if not qml.operation.active_new_opmath(): + raise RuntimeError + + +def test_that_opmath_is_disabled(): + """Confirm that the tests are running by default with new_opmath disabled""" + if qml.operation.active_new_opmath(): + raise RuntimeError + + class TestOperatorConstruction: """Test custom operators' construction.""" From b62c727b52454d07e2bfd2d5213377c1cf0b0ef9 Mon Sep 17 00:00:00 2001 From: lillian542 Date: Wed, 3 Apr 2024 18:03:35 -0400 Subject: [PATCH 19/59] set use_new_opmath to false for all --- .github/workflows/interface-unit-tests.yml | 2 +- .github/workflows/unit-test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/interface-unit-tests.yml b/.github/workflows/interface-unit-tests.yml index 68c32a1d67c..d2285176fc0 100644 --- a/.github/workflows/interface-unit-tests.yml +++ b/.github/workflows/interface-unit-tests.yml @@ -37,7 +37,7 @@ on: description: Whether to use the new op_math or not when running the tests required: false type: boolean - default: true + default: false jobs: setup-ci-load: diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index 55b6726f9ac..2d259a22ea8 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -98,7 +98,7 @@ on: description: Whether to use the new op_math or not when running the tests required: false type: boolean - default: true + default: false jobs: test: From 97f9a7b57f838968709f37e25ee9b123342a1c17 Mon Sep 17 00:00:00 2001 From: lillian542 Date: Thu, 4 Apr 2024 10:08:28 -0400 Subject: [PATCH 20/59] temporary test to sanity check testing behaviour --- tests/test_operation.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/test_operation.py b/tests/test_operation.py index f0fa8ecf334..e267693e56a 100644 --- a/tests/test_operation.py +++ b/tests/test_operation.py @@ -58,6 +58,11 @@ def test_that_opmath_is_disabled(): raise RuntimeError +def test_that_this_file_is_being_tested(): + """Confirm that this file is running in tests""" + raise RuntimeError("This test should fail") + + class TestOperatorConstruction: """Test custom operators' construction.""" From 0ef2a0424ff07012e62e23b22029fa0ec5a5f4c0 Mon Sep 17 00:00:00 2001 From: lillian542 Date: Thu, 4 Apr 2024 12:06:37 -0400 Subject: [PATCH 21/59] update legacy workflow to run on this branch instead of master for now --- .github/workflows/legacy_op_math.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/legacy_op_math.yml b/.github/workflows/legacy_op_math.yml index cfdae0d7b9f..caea7d53b6f 100644 --- a/.github/workflows/legacy_op_math.yml +++ b/.github/workflows/legacy_op_math.yml @@ -3,13 +3,13 @@ name: Legacy opmath tests on: schedule: - cron: "0 0 2 * *" - pull_request: + pull_request: # this should be removed so it only runs on the schedule before merging workflow_dispatch: jobs: tests: uses: ./.github/workflows/interface-unit-tests.yml with: - branch: 'master' + branch: ${{ github.ref }} # this should be set back to master before merging run_lightened_ci: false use_new_opmath: false \ No newline at end of file From e19db173163b0d6a0aefa1e1150cd4ffdeef9577 Mon Sep 17 00:00:00 2001 From: lillian542 Date: Thu, 4 Apr 2024 12:07:27 -0400 Subject: [PATCH 22/59] add pytest fixture and input variable to optionally disable op_math --- tests/conftest.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/conftest.py b/tests/conftest.py index 824ecdadd66..362f6036c9c 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -178,6 +178,17 @@ def tear_down_thermitian(): # Fixtures for testing under new and old opmath +def pytest_addoption(parser): + parser.addoption("--disable-opmath", action="store", default=False) + + +@pytest.fixture(scope="session", autouse=True) +def disable_opmath_if_requested(request): + disable_opmath = request.config.getoption("--disable-opmath") + if disable_opmath: + qml.operation.disable_new_opmath() + + @pytest.fixture(scope="function") def use_legacy_opmath(): with disable_new_opmath_cm() as cm: From a73f32481566d61d0bff12f93e25c837630f490f Mon Sep 17 00:00:00 2001 From: lillian542 Date: Thu, 4 Apr 2024 12:23:56 -0400 Subject: [PATCH 23/59] update to use the disable-opmath fixture --- .github/workflows/interface-unit-tests.yml | 4 ++-- .github/workflows/legacy_op_math.yml | 2 +- .github/workflows/unit-test.yml | 8 +++----- 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/.github/workflows/interface-unit-tests.yml b/.github/workflows/interface-unit-tests.yml index d2285176fc0..d97a3adac10 100644 --- a/.github/workflows/interface-unit-tests.yml +++ b/.github/workflows/interface-unit-tests.yml @@ -33,8 +33,8 @@ on: required: false type: string default: '' - use_new_opmath: - description: Whether to use the new op_math or not when running the tests + disable_new_opmath: + description: Whether to disable the new op_math or not when running the tests required: false type: boolean default: false diff --git a/.github/workflows/legacy_op_math.yml b/.github/workflows/legacy_op_math.yml index caea7d53b6f..f816f47d2c1 100644 --- a/.github/workflows/legacy_op_math.yml +++ b/.github/workflows/legacy_op_math.yml @@ -12,4 +12,4 @@ jobs: with: branch: ${{ github.ref }} # this should be set back to master before merging run_lightened_ci: false - use_new_opmath: false \ No newline at end of file + disable_new_opmath: true \ No newline at end of file diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index 2d259a22ea8..8642fcb05ec 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -94,8 +94,8 @@ on: required: false type: string default: '' - use_new_opmath: - description: Whether to use the new op_math or not when running the tests + disable_new_opmath: + description: Whether to disable the new op_math or not when running the tests required: false type: boolean default: false @@ -174,9 +174,7 @@ jobs: COV_CORE_CONFIG: .coveragerc COV_CORE_DATAFILE: .coverage.eager # Calling PyTest by invoking Python first as that adds the current directory to sys.path - run: | - python -m import pennylane as qml && qml.operation.__use_new_opmath = ${{ inputs.use_new_opmath }} - python -m pytest ${{ inputs.pytest_test_directory }} ${{ steps.pytest_args.outputs.args }} ${{ env.PYTEST_MARKER }} + run: python -m pytest ${{ inputs.pytest_test_directory }} ${{ steps.pytest_args.outputs.args }} ${{ env.PYTEST_MARKER }} --disable-opmath=${{ inputs.disable_new_opmath }} - name: Adjust coverage file for Codecov if: inputs.pipeline_mode == 'unit-tests' From 04b6402ee07ebe04898a66b0887c2e1c9c6704de Mon Sep 17 00:00:00 2001 From: lillian542 Date: Thu, 4 Apr 2024 12:24:15 -0400 Subject: [PATCH 24/59] remove old commented out code --- tests/conftest.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 362f6036c9c..6f2274672ff 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -195,12 +195,6 @@ def use_legacy_opmath(): yield cm -# @pytest.fixture(scope="function") -# def use_legacy_opmath(): -# with disable_new_opmath_cm(): -# yield - - @pytest.fixture(scope="function") def use_new_opmath(): with enable_new_opmath_cm() as cm: From f37925a5d077025f0edd538e9d05d7c9e39df8c0 Mon Sep 17 00:00:00 2001 From: lillian542 Date: Thu, 4 Apr 2024 12:55:31 -0400 Subject: [PATCH 25/59] use and evaluate string instead of using yaml boolean --- .github/workflows/interface-unit-tests.yml | 4 ++-- .github/workflows/unit-test.yml | 4 ++-- tests/conftest.py | 4 +++- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/interface-unit-tests.yml b/.github/workflows/interface-unit-tests.yml index d97a3adac10..d68fe4e1a96 100644 --- a/.github/workflows/interface-unit-tests.yml +++ b/.github/workflows/interface-unit-tests.yml @@ -36,8 +36,8 @@ on: disable_new_opmath: description: Whether to disable the new op_math or not when running the tests required: false - type: boolean - default: false + type: string + default: "False" jobs: setup-ci-load: diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index 8642fcb05ec..ee50a7252a2 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -97,8 +97,8 @@ on: disable_new_opmath: description: Whether to disable the new op_math or not when running the tests required: false - type: boolean - default: false + type: string + default: "False" jobs: test: diff --git a/tests/conftest.py b/tests/conftest.py index 6f2274672ff..5ada35932ff 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -182,10 +182,12 @@ def pytest_addoption(parser): parser.addoption("--disable-opmath", action="store", default=False) +# pylint: disable=eval-used @pytest.fixture(scope="session", autouse=True) def disable_opmath_if_requested(request): disable_opmath = request.config.getoption("--disable-opmath") - if disable_opmath: + # value from yaml file is a string, convert to boolean + if eval(disable_opmath): qml.operation.disable_new_opmath() From 2dd46207ba57138f156eb5aa3476f9a5eabf5690 Mon Sep 17 00:00:00 2001 From: lillian542 Date: Thu, 4 Apr 2024 12:56:06 -0400 Subject: [PATCH 26/59] update value in legacy_op_math workflow --- .github/workflows/legacy_op_math.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/legacy_op_math.yml b/.github/workflows/legacy_op_math.yml index f816f47d2c1..92e111f4d8f 100644 --- a/.github/workflows/legacy_op_math.yml +++ b/.github/workflows/legacy_op_math.yml @@ -12,4 +12,4 @@ jobs: with: branch: ${{ github.ref }} # this should be set back to master before merging run_lightened_ci: false - disable_new_opmath: true \ No newline at end of file + disable_new_opmath: "True" \ No newline at end of file From e2f37e1ac67085c3c6eb57c42e7bb2217c76067c Mon Sep 17 00:00:00 2001 From: lillian542 Date: Thu, 4 Apr 2024 13:05:04 -0400 Subject: [PATCH 27/59] pass value for disable_new_opmath through to unit-test.yml --- .github/workflows/interface-unit-tests.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/workflows/interface-unit-tests.yml b/.github/workflows/interface-unit-tests.yml index d68fe4e1a96..2b3c98ed351 100644 --- a/.github/workflows/interface-unit-tests.yml +++ b/.github/workflows/interface-unit-tests.yml @@ -156,6 +156,7 @@ jobs: pytest_coverage_flags: ${{ inputs.pytest_coverage_flags }} pytest_markers: torch and not qcut and not finite-diff and not param-shift requirements_file: ${{ strategy.job-index == 0 && 'torch.txt' || '' }} + disable_new_opmath: ${{ inputs.disable_new_opmath }} autograd-tests: @@ -187,6 +188,7 @@ jobs: install_pennylane_lightning_master: true pytest_coverage_flags: ${{ inputs.pytest_coverage_flags }} pytest_markers: autograd and not qcut and not finite-diff and not param-shift + disable_new_opmath: ${{ inputs.disable_new_opmath }} tf-tests: @@ -222,6 +224,7 @@ jobs: pytest_additional_args: --splits 3 --group ${{ matrix.group }} --durations-path='.github/workflows/tf_tests_durations.json' additional_pip_packages: pytest-split requirements_file: ${{ strategy.job-index == 0 && 'tf.txt' || '' }} + disable_new_opmath: ${{ inputs.disable_new_opmath }} jax-tests: @@ -257,6 +260,7 @@ jobs: pytest_additional_args: --splits 5 --group ${{ matrix.group }} --durations-path='.github/workflows/jax_tests_durations.json' additional_pip_packages: pytest-split requirements_file: ${{ strategy.job-index == 0 && 'jax.txt' || '' }} + disable_new_opmath: ${{ inputs.disable_new_opmath }} core-tests: @@ -292,6 +296,7 @@ jobs: pytest_additional_args: --splits 5 --group ${{ matrix.group }} --durations-path='.github/workflows/core_tests_durations.json' additional_pip_packages: pytest-split requirements_file: ${{ strategy.job-index == 0 && 'core.txt' || '' }} + disable_new_opmath: ${{ inputs.disable_new_opmath }} all-interfaces-tests: @@ -324,6 +329,7 @@ jobs: pytest_coverage_flags: ${{ inputs.pytest_coverage_flags }} pytest_markers: all_interfaces requirements_file: ${{ strategy.job-index == 0 && 'all_interfaces.txt' || '' }} + disable_new_opmath: ${{ inputs.disable_new_opmath }} external-libraries-tests: @@ -357,6 +363,7 @@ jobs: pytest_markers: external additional_pip_packages: pyzx pennylane-catalyst matplotlib stim requirements_file: ${{ strategy.job-index == 0 && 'external.txt' || '' }} + disable_new_opmath: ${{ inputs.disable_new_opmath }} qcut-tests: @@ -389,6 +396,7 @@ jobs: pytest_coverage_flags: ${{ inputs.pytest_coverage_flags }} pytest_markers: qcut additional_pip_packages: kahypar==1.1.7 opt_einsum + disable_new_opmath: ${{ inputs.disable_new_opmath }} qchem-tests: @@ -421,6 +429,7 @@ jobs: pytest_coverage_flags: ${{ inputs.pytest_coverage_flags }} pytest_markers: qchem additional_pip_packages: openfermionpyscf basis-set-exchange + disable_new_opmath: ${{ inputs.disable_new_opmath }} gradients-tests: needs: @@ -454,6 +463,7 @@ jobs: install_pennylane_lightning_master: false pytest_coverage_flags: ${{ inputs.pytest_coverage_flags }} pytest_markers: ${{ matrix.config.suite }} + disable_new_opmath: ${{ inputs.disable_new_opmath }} data-tests: @@ -486,6 +496,7 @@ jobs: pytest_coverage_flags: ${{ inputs.pytest_coverage_flags }} pytest_markers: data additional_pip_packages: h5py + disable_new_opmath: ${{ inputs.disable_new_opmath }} device-tests: @@ -533,6 +544,7 @@ jobs: pytest_test_directory: pennylane/devices/tests pytest_coverage_flags: ${{ inputs.pytest_coverage_flags }} pytest_additional_args: --device=${{ matrix.config.device }} --shots=${{ matrix.config.shots }} + disable_new_opmath: ${{ inputs.disable_new_opmath }} upload-to-codecov: From 2571b1be3a6f8df9db6a6289936bab29e70cf70c Mon Sep 17 00:00:00 2001 From: lillian542 Date: Thu, 4 Apr 2024 14:55:26 -0400 Subject: [PATCH 28/59] use quotations when passing variable --- .github/workflows/unit-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index ee50a7252a2..5c6fe08dbc6 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -174,7 +174,7 @@ jobs: COV_CORE_CONFIG: .coveragerc COV_CORE_DATAFILE: .coverage.eager # Calling PyTest by invoking Python first as that adds the current directory to sys.path - run: python -m pytest ${{ inputs.pytest_test_directory }} ${{ steps.pytest_args.outputs.args }} ${{ env.PYTEST_MARKER }} --disable-opmath=${{ inputs.disable_new_opmath }} + run: python -m pytest ${{ inputs.pytest_test_directory }} ${{ steps.pytest_args.outputs.args }} ${{ env.PYTEST_MARKER }} --disable-opmath="${{ inputs.disable_new_opmath }}" - name: Adjust coverage file for Codecov if: inputs.pipeline_mode == 'unit-tests' From 668591c44cd3d1910190c5a5b685264591d26158 Mon Sep 17 00:00:00 2001 From: lillian542 Date: Thu, 4 Apr 2024 15:59:06 -0400 Subject: [PATCH 29/59] add option to devices conftest too --- pennylane/devices/tests/conftest.py | 14 ++++++++++++++ tests/conftest.py | 4 +++- tests/test_operation.py | 9 ++------- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/pennylane/devices/tests/conftest.py b/pennylane/devices/tests/conftest.py index ce4d823fe3d..d502a178f56 100755 --- a/pennylane/devices/tests/conftest.py +++ b/pennylane/devices/tests/conftest.py @@ -209,6 +209,20 @@ def pytest_addoption(parser): metavar="KEY=VAL", help="Additional device kwargs.", ) + addoption( + "--disable-opmath", action="store", default=False, help="Whether to disable new_opmath" + ) + + +# pylint: disable=eval-used +@pytest.fixture(scope="session", autouse=True) +def disable_opmath_if_requested(request): + """Check the value of the --disable-opmath option and turn off + if True before running the tests""" + disable_opmath = request.config.getoption("--disable-opmath") + # value from yaml file is a string, convert to boolean + if eval(disable_opmath): + qml.operation.disable_new_opmath() def pytest_generate_tests(metafunc): diff --git a/tests/conftest.py b/tests/conftest.py index 5ada35932ff..7e908c45fb9 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -179,7 +179,9 @@ def tear_down_thermitian(): def pytest_addoption(parser): - parser.addoption("--disable-opmath", action="store", default=False) + parser.addoption( + "--disable-opmath", action="store", default=False, help="Whether to disable new_opmath" + ) # pylint: disable=eval-used diff --git a/tests/test_operation.py b/tests/test_operation.py index e267693e56a..7209dcc1470 100644 --- a/tests/test_operation.py +++ b/tests/test_operation.py @@ -49,18 +49,13 @@ def test_that_opmath_is_enabled(): """Confirm that the tests are running by default with new_opmath enabled""" if not qml.operation.active_new_opmath(): - raise RuntimeError + raise RuntimeError("new_opmath is disabled!") def test_that_opmath_is_disabled(): """Confirm that the tests are running by default with new_opmath disabled""" if qml.operation.active_new_opmath(): - raise RuntimeError - - -def test_that_this_file_is_being_tested(): - """Confirm that this file is running in tests""" - raise RuntimeError("This test should fail") + raise RuntimeError("new_opmath is enabled!") class TestOperatorConstruction: From ab595f9e90dfd9c40a62d92c526f9ab3a5b60694 Mon Sep 17 00:00:00 2001 From: lillian542 Date: Thu, 4 Apr 2024 16:28:24 -0400 Subject: [PATCH 30/59] remove temporary sanity-check tests --- tests/test_operation.py | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/tests/test_operation.py b/tests/test_operation.py index 7209dcc1470..b473f4c5b39 100644 --- a/tests/test_operation.py +++ b/tests/test_operation.py @@ -46,18 +46,6 @@ I_broadcasted = I[pnp.newaxis] -def test_that_opmath_is_enabled(): - """Confirm that the tests are running by default with new_opmath enabled""" - if not qml.operation.active_new_opmath(): - raise RuntimeError("new_opmath is disabled!") - - -def test_that_opmath_is_disabled(): - """Confirm that the tests are running by default with new_opmath disabled""" - if qml.operation.active_new_opmath(): - raise RuntimeError("new_opmath is enabled!") - - class TestOperatorConstruction: """Test custom operators' construction.""" From e1716e204e56c111c6f0632b9281c9d1ea45bc68 Mon Sep 17 00:00:00 2001 From: lillian542 Date: Fri, 5 Apr 2024 11:12:08 -0400 Subject: [PATCH 31/59] Legacy Hamiltonian converts Prods to Tensors --- .github/workflows/legacy_op_math.yml | 2 +- .github/workflows/unit-test.yml | 2 +- pennylane/ops/qubit/hamiltonian.py | 5 +++++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/legacy_op_math.yml b/.github/workflows/legacy_op_math.yml index 92e111f4d8f..6b5dd165954 100644 --- a/.github/workflows/legacy_op_math.yml +++ b/.github/workflows/legacy_op_math.yml @@ -12,4 +12,4 @@ jobs: with: branch: ${{ github.ref }} # this should be set back to master before merging run_lightened_ci: false - disable_new_opmath: "True" \ No newline at end of file + disable_new_opmath: "True" diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index 5c6fe08dbc6..ee50a7252a2 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -174,7 +174,7 @@ jobs: COV_CORE_CONFIG: .coveragerc COV_CORE_DATAFILE: .coverage.eager # Calling PyTest by invoking Python first as that adds the current directory to sys.path - run: python -m pytest ${{ inputs.pytest_test_directory }} ${{ steps.pytest_args.outputs.args }} ${{ env.PYTEST_MARKER }} --disable-opmath="${{ inputs.disable_new_opmath }}" + run: python -m pytest ${{ inputs.pytest_test_directory }} ${{ steps.pytest_args.outputs.args }} ${{ env.PYTEST_MARKER }} --disable-opmath=${{ inputs.disable_new_opmath }} - name: Adjust coverage file for Codecov if: inputs.pipeline_mode == 'unit-tests' diff --git a/pennylane/ops/qubit/hamiltonian.py b/pennylane/ops/qubit/hamiltonian.py index 17c6de25277..ecdf6561d87 100644 --- a/pennylane/ops/qubit/hamiltonian.py +++ b/pennylane/ops/qubit/hamiltonian.py @@ -203,6 +203,11 @@ def __init__( ) for obs in observables: + if isinstance(obs, qml.ops.Prod): + # we don't really want this to ever happen, but it makes testing easier during the deprecation phase + # because we don't have to generate separate lists of parametrization for old and new opmath testing + obs = qml.simplify(obs) + obs = qml.operation.Tensor(*obs) if not isinstance(obs, Observable): raise ValueError( "Could not create circuits. Some or all observables are not valid." From 668938a62c4fc98002ea253b2a430eb18e81e7d0 Mon Sep 17 00:00:00 2001 From: lillian542 Date: Fri, 5 Apr 2024 11:12:37 -0400 Subject: [PATCH 32/59] change handling of disable-opmath input --- tests/conftest.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 7e908c45fb9..d4abaf9626c 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -188,8 +188,9 @@ def pytest_addoption(parser): @pytest.fixture(scope="session", autouse=True) def disable_opmath_if_requested(request): disable_opmath = request.config.getoption("--disable-opmath") - # value from yaml file is a string, convert to boolean - if eval(disable_opmath): + + # depending on how it's passed, disable_opmath may be a str or bool at this point + if str(disable_opmath) == "True": qml.operation.disable_new_opmath() From d3feda0b23caa7cfb43601417297a3be7ea5e692 Mon Sep 17 00:00:00 2001 From: lillian542 Date: Fri, 5 Apr 2024 11:15:59 -0400 Subject: [PATCH 33/59] make disable-opmath input variable type consistent --- pennylane/devices/tests/conftest.py | 2 +- tests/conftest.py | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/pennylane/devices/tests/conftest.py b/pennylane/devices/tests/conftest.py index d502a178f56..779088c79db 100755 --- a/pennylane/devices/tests/conftest.py +++ b/pennylane/devices/tests/conftest.py @@ -210,7 +210,7 @@ def pytest_addoption(parser): help="Additional device kwargs.", ) addoption( - "--disable-opmath", action="store", default=False, help="Whether to disable new_opmath" + "--disable-opmath", action="store", default="False", help="Whether to disable new_opmath" ) diff --git a/tests/conftest.py b/tests/conftest.py index d4abaf9626c..2d9573ea773 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -180,7 +180,7 @@ def tear_down_thermitian(): def pytest_addoption(parser): parser.addoption( - "--disable-opmath", action="store", default=False, help="Whether to disable new_opmath" + "--disable-opmath", action="store", default="False", help="Whether to disable new_opmath" ) @@ -188,9 +188,8 @@ def pytest_addoption(parser): @pytest.fixture(scope="session", autouse=True) def disable_opmath_if_requested(request): disable_opmath = request.config.getoption("--disable-opmath") - - # depending on how it's passed, disable_opmath may be a str or bool at this point - if str(disable_opmath) == "True": + # value from yaml file is a string, convert to boolean + if eval(disable_opmath): qml.operation.disable_new_opmath() From 649c53474163875eeb468e47cdcc785576ec95b7 Mon Sep 17 00:00:00 2001 From: lillian542 Date: Fri, 5 Apr 2024 15:05:32 -0400 Subject: [PATCH 34/59] update failing tests --- .../data/attributes/operator/test_operator.py | 22 ++++++++++++++++++- tests/devices/test_default_qubit_tf.py | 2 ++ tests/devices/test_default_qubit_torch.py | 1 + .../legacy/test_classical_shadow_legacy.py | 5 ++++- tests/measurements/test_classical_shadow.py | 5 ++++- tests/shadow/test_shadow_class.py | 5 ++++- tests/transforms/test_qcut.py | 4 ++-- 7 files changed, 38 insertions(+), 6 deletions(-) diff --git a/tests/data/attributes/operator/test_operator.py b/tests/data/attributes/operator/test_operator.py index e21a9be02e8..0f7d9db085d 100644 --- a/tests/data/attributes/operator/test_operator.py +++ b/tests/data/attributes/operator/test_operator.py @@ -83,6 +83,9 @@ def test_value_init(self, obs_in): """Test that a DatasetOperator can be value-initialized from an observable, and that the deserialized operator is equivalent.""" + if not qml.operation.active_new_opmath() and isinstance(obs_in, qml.ops.LinearCombination): + obs_in = qml.operation.convert_to_legacy_H(obs_in) + dset_op = DatasetOperator(obs_in) assert dset_op.info["type_id"] == "operator" @@ -95,6 +98,9 @@ def test_value_init(self, obs_in): def test_bind_init(self, obs_in): """Test that DatasetOperator can be initialized from a HDF5 group that contains a operator attribute.""" + if not qml.operation.active_new_opmath() and isinstance(obs_in, qml.ops.LinearCombination): + obs_in = qml.operation.convert_to_legacy_H(obs_in) + bind = DatasetOperator(obs_in).bind dset_op = DatasetOperator(bind=bind) @@ -124,6 +130,9 @@ def test_value_init(self, obs_in): """Test that a DatasetOperator can be value-initialized from an observable, and that the deserialized operator is equivalent.""" + if not qml.operation.active_new_opmath() and isinstance(obs_in, qml.ops.LinearCombination): + obs_in = qml.operation.convert_to_legacy_H(obs_in) + dset_op = DatasetOperator(obs_in) assert dset_op.info["type_id"] == "operator" @@ -135,6 +144,9 @@ def test_value_init(self, obs_in): def test_bind_init(self, obs_in): """Test that DatasetOperator can be initialized from a HDF5 group that contains an operator attribute.""" + if not qml.operation.active_new_opmath() and isinstance(obs_in, qml.ops.LinearCombination): + obs_in = qml.operation.convert_to_legacy_H(obs_in) + bind = DatasetOperator(obs_in).bind dset_op = DatasetOperator(bind=bind) @@ -160,6 +172,9 @@ def test_value_init(self, op_in): """Test that a DatasetOperator can be value-initialized from an operator, and that the deserialized operator is equivalent.""" + if not qml.operation.active_new_opmath() and isinstance(op_in, qml.ops.LinearCombination): + op_in = qml.operation.convert_to_legacy_H(op_in) + dset_op = DatasetOperator(op_in) assert dset_op.info["type_id"] == "operator" @@ -172,7 +187,9 @@ def test_value_init(self, op_in): def test_value_init_not_supported(self): """Test that a ValueError is raised if attempting to serialize an unsupported operator.""" - class NotSupported(Operator): # pylint: disable=too-few-public-methods + class NotSupported( + Operator + ): # pylint: disable=too-few-public-methods, unnecessary-ellipsis """An operator.""" ... @@ -195,6 +212,9 @@ def test_bind_init(self, op_in): """Test that a DatasetOperator can be bind-initialized from an operator, and that the deserialized operator is equivalent.""" + if not qml.operation.active_new_opmath() and isinstance(op_in, qml.ops.LinearCombination): + op_in = qml.operation.convert_to_legacy_H(op_in) + bind = DatasetOperator(op_in).bind dset_op = DatasetOperator(bind=bind) diff --git a/tests/devices/test_default_qubit_tf.py b/tests/devices/test_default_qubit_tf.py index ac81f6cf36c..474ef10e47b 100644 --- a/tests/devices/test_default_qubit_tf.py +++ b/tests/devices/test_default_qubit_tf.py @@ -519,6 +519,7 @@ def test_four_qubit_parameters(self, init_state, op, func, theta, tol): expected = func(theta) @ state assert np.allclose(res, expected, atol=tol, rtol=0) + # pylint: disable=use-implicit-booleaness-not-comparison def test_apply_ops_not_supported(self, mocker, monkeypatch): """Test that when a version of TensorFlow before 2.3.0 is used, the _apply_ops dictionary is empty and application of a CNOT gate is performed using _apply_unitary_einsum""" @@ -927,6 +928,7 @@ def test_three_qubit_no_parameters_broadcasted(self, broadcasted_init_state, op, expected = np.einsum("ij,lj->li", mat, state) assert np.allclose(res, expected, atol=tol, rtol=0) + @pytest.mark.usefixtures("use_new_opmath") def test_direct_eval_hamiltonian_broadcasted_tf(self): """Tests that the correct result is returned when attempting to evaluate a Hamiltonian with broadcasting and shots=None directly via its sparse representation with TF.""" diff --git a/tests/devices/test_default_qubit_torch.py b/tests/devices/test_default_qubit_torch.py index 0f8f5200e42..012bc3e2536 100644 --- a/tests/devices/test_default_qubit_torch.py +++ b/tests/devices/test_default_qubit_torch.py @@ -914,6 +914,7 @@ def test_three_qubit_no_parameters_broadcasted( expected = qml.math.einsum("ij,lj->li", op_mat, state) assert torch.allclose(res, expected, atol=tol, rtol=0) + @pytest.mark.usefixtures("use_new_opmath") def test_direct_eval_hamiltonian_broadcasted_torch(self, device, torch_device, mocker): """Tests that the correct result is returned when attempting to evaluate a Hamiltonian with broadcasting and shots=None directly via its sparse representation with torch.""" diff --git a/tests/measurements/legacy/test_classical_shadow_legacy.py b/tests/measurements/legacy/test_classical_shadow_legacy.py index 506a28a7d2e..691570506e5 100644 --- a/tests/measurements/legacy/test_classical_shadow_legacy.py +++ b/tests/measurements/legacy/test_classical_shadow_legacy.py @@ -420,7 +420,10 @@ def test_non_pauli_error(self): """Test that an error is raised when a non-Pauli observable is passed""" circuit = hadamard_circuit(3) - msg = "Observable must have a valid pauli representation." + legacy_msg = "Observable must be a linear combination of Pauli observables" + new_opmath_msg = "Observable must have a valid pauli representation." + msg = new_opmath_msg if qml.operation.active_new_opmath() else legacy_msg + with pytest.raises(ValueError, match=msg): circuit(qml.Hadamard(0) @ qml.Hadamard(2)) diff --git a/tests/measurements/test_classical_shadow.py b/tests/measurements/test_classical_shadow.py index 45384c43267..0dba945afc9 100644 --- a/tests/measurements/test_classical_shadow.py +++ b/tests/measurements/test_classical_shadow.py @@ -573,7 +573,10 @@ def test_non_pauli_error(self): """Test that an error is raised when a non-Pauli observable is passed""" circuit = hadamard_circuit(3) - msg = "Observable must have a valid pauli representation." + legacy_msg = "Observable must be a linear combination of Pauli observables" + new_opmath_msg = "Observable must have a valid pauli representation." + msg = new_opmath_msg if qml.operation.active_new_opmath() else legacy_msg + with pytest.raises(ValueError, match=msg): circuit(qml.Hadamard(0) @ qml.Hadamard(2)) diff --git a/tests/shadow/test_shadow_class.py b/tests/shadow/test_shadow_class.py index bcd3de1c4ac..025d68d54c4 100644 --- a/tests/shadow/test_shadow_class.py +++ b/tests/shadow/test_shadow_class.py @@ -364,7 +364,10 @@ def test_non_pauli_error_no_pauli_rep(self): H = qml.Hadamard(0) @ qml.Hadamard(2) - msg = "Observable must have a valid pauli representation." + legacy_msg = "Observable must be a linear combination of Pauli observables" + new_opmath_msg = "Observable must have a valid pauli representation." + msg = new_opmath_msg if qml.operation.active_new_opmath() else legacy_msg + with pytest.raises(ValueError, match=msg): shadow.expval(H, k=10) diff --git a/tests/transforms/test_qcut.py b/tests/transforms/test_qcut.py index aa2a6e6effd..26c8de18c33 100644 --- a/tests/transforms/test_qcut.py +++ b/tests/transforms/test_qcut.py @@ -16,7 +16,7 @@ """ # pylint: disable=protected-access,too-few-public-methods,too-many-arguments # pylint: disable=too-many-public-methods,comparison-with-callable -# pylint: disable=no-value-for-parameter,no-member,not-callable +# pylint: disable=no-value-for-parameter,no-member,not-callable, use-implicit-booleaness-not-comparison import copy import itertools import string @@ -5871,10 +5871,10 @@ def block(weights, wires): # each frag should have the device size constraint satisfied. assert all(len(set(e[2] for e in f.edges.data("wire"))) <= device_size for f in frags) - @pytest.mark.xfail def test_hamiltonian_with_tape(self): """Test that an expand function that generates multiple tapes is applied before the transform and the transform returns correct results.""" + ops = [qml.Identity(0), qml.PauliZ(0), qml.PauliZ(1), qml.PauliZ(2)] coeffs = [0.4567, 0.25, 0.25, 0.5] From bcc882d06f01494260685771e92931d41fc50938 Mon Sep 17 00:00:00 2001 From: lillian542 <38584660+lillian542@users.noreply.github.com> Date: Fri, 5 Apr 2024 15:08:16 -0400 Subject: [PATCH 35/59] Update tests/transforms/test_qcut.py --- tests/transforms/test_qcut.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/transforms/test_qcut.py b/tests/transforms/test_qcut.py index 26c8de18c33..bdb253e0769 100644 --- a/tests/transforms/test_qcut.py +++ b/tests/transforms/test_qcut.py @@ -5874,7 +5874,6 @@ def block(weights, wires): def test_hamiltonian_with_tape(self): """Test that an expand function that generates multiple tapes is applied before the transform and the transform returns correct results.""" - ops = [qml.Identity(0), qml.PauliZ(0), qml.PauliZ(1), qml.PauliZ(2)] coeffs = [0.4567, 0.25, 0.25, 0.5] From f8e2e0e24e25c4a312744e4f7bfa4a7dd57517bf Mon Sep 17 00:00:00 2001 From: qottmann Date: Mon, 8 Apr 2024 10:57:03 +0200 Subject: [PATCH 36/59] test_autograd --- tests/interfaces/test_autograd.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/tests/interfaces/test_autograd.py b/tests/interfaces/test_autograd.py index 7296669ddd2..8b95f9d2135 100644 --- a/tests/interfaces/test_autograd.py +++ b/tests/interfaces/test_autograd.py @@ -211,6 +211,36 @@ def test_no_batch_transform(self, mocker): assert isinstance(res[0], np.ndarray) assert res[0].shape == () assert np.allclose(res[0], np.cos(y), atol=0.1) + + @pytest.mark.usefixtures("use_legacy_opmath") + def test_no_batch_transform_legacy_opmath(self, mocker): + """Test functionality to enable and disable""" + dev = qml.device("default.qubit.legacy", wires=2, shots=100000) + + H = qml.PauliZ(0) @ qml.PauliZ(1) - qml.PauliX(0) + x = 0.6 + y = 0.2 + + with qml.queuing.AnnotatedQueue() as q: + qml.RX(x, wires=0) + qml.RY(y, wires=1) + qml.CNOT(wires=[0, 1]) + qml.expval(H) + + tape = qml.tape.QuantumScript.from_queue(q) + spy = mocker.spy(dev, "batch_transform") + + with pytest.raises(AssertionError, match="Hamiltonian must be used with shots=None"): + res = qml.execute([tape], dev, None, device_batch_transform=False) + + spy.assert_not_called() + + res = qml.execute([tape], dev, None, device_batch_transform=True) + spy.assert_called() + + assert isinstance(res[0], np.ndarray) + assert res[0].shape == () + assert np.allclose(res[0], np.cos(y), atol=0.1) def test_batch_transform_dynamic_shots(self): """Tests that the batch transform considers the number of shots for the execution, not those From 9eec37f4a33842747d6b0344439932c0dc7065ea Mon Sep 17 00:00:00 2001 From: qottmann Date: Mon, 8 Apr 2024 11:09:23 +0200 Subject: [PATCH 37/59] black formatting --- tests/interfaces/test_autograd.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/interfaces/test_autograd.py b/tests/interfaces/test_autograd.py index 8b95f9d2135..384f1669afe 100644 --- a/tests/interfaces/test_autograd.py +++ b/tests/interfaces/test_autograd.py @@ -211,7 +211,7 @@ def test_no_batch_transform(self, mocker): assert isinstance(res[0], np.ndarray) assert res[0].shape == () assert np.allclose(res[0], np.cos(y), atol=0.1) - + @pytest.mark.usefixtures("use_legacy_opmath") def test_no_batch_transform_legacy_opmath(self, mocker): """Test functionality to enable and disable""" From 244ee086354aec214cbe57b55695c8d7636f8c17 Mon Sep 17 00:00:00 2001 From: lillian542 Date: Thu, 11 Apr 2024 17:45:38 -0400 Subject: [PATCH 38/59] update qutrit device test --- tests/devices/qutrit_mixed/test_qutrit_mixed_sampling.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/devices/qutrit_mixed/test_qutrit_mixed_sampling.py b/tests/devices/qutrit_mixed/test_qutrit_mixed_sampling.py index 00e98c5de5a..f3ff8a19bc0 100644 --- a/tests/devices/qutrit_mixed/test_qutrit_mixed_sampling.py +++ b/tests/devices/qutrit_mixed/test_qutrit_mixed_sampling.py @@ -365,7 +365,7 @@ def test_sample_observables(self): qml.sample(qml.GellMann(0, 1) @ qml.GellMann(1, 1)), state, shots=shots ) assert results_gel_1s.shape == (shots.total_shots,) - assert results_gel_1s.dtype == np.float64 + assert results_gel_1s.dtype == np.float64 if qml.operation.active_new_opmath() else np.int64 assert sorted(np.unique(results_gel_1s)) == [-1, 0, 1] @flaky From b103d23d4d61f9f3b5c976dbc40c42d33a924fa2 Mon Sep 17 00:00:00 2001 From: lillian542 Date: Thu, 11 Apr 2024 17:46:03 -0400 Subject: [PATCH 39/59] run CI with lightning master instead of stable --- .github/workflows/interface-unit-tests.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/interface-unit-tests.yml b/.github/workflows/interface-unit-tests.yml index 2b3c98ed351..0673131f5be 100644 --- a/.github/workflows/interface-unit-tests.yml +++ b/.github/workflows/interface-unit-tests.yml @@ -325,7 +325,7 @@ jobs: install_jax: true install_tensorflow: true install_pytorch: true - install_pennylane_lightning_master: false + install_pennylane_lightning_master: true pytest_coverage_flags: ${{ inputs.pytest_coverage_flags }} pytest_markers: all_interfaces requirements_file: ${{ strategy.job-index == 0 && 'all_interfaces.txt' || '' }} @@ -358,7 +358,7 @@ jobs: install_jax: true install_tensorflow: true install_pytorch: false - install_pennylane_lightning_master: false + install_pennylane_lightning_master: true pytest_coverage_flags: ${{ inputs.pytest_coverage_flags }} pytest_markers: external additional_pip_packages: pyzx pennylane-catalyst matplotlib stim @@ -392,7 +392,7 @@ jobs: install_jax: true install_tensorflow: true install_pytorch: true - install_pennylane_lightning_master: false + install_pennylane_lightning_master: true pytest_coverage_flags: ${{ inputs.pytest_coverage_flags }} pytest_markers: qcut additional_pip_packages: kahypar==1.1.7 opt_einsum @@ -425,7 +425,7 @@ jobs: install_jax: false install_tensorflow: false install_pytorch: false - install_pennylane_lightning_master: false + install_pennylane_lightning_master: true pytest_coverage_flags: ${{ inputs.pytest_coverage_flags }} pytest_markers: qchem additional_pip_packages: openfermionpyscf basis-set-exchange @@ -460,7 +460,7 @@ jobs: install_jax: true install_tensorflow: true install_pytorch: true - install_pennylane_lightning_master: false + install_pennylane_lightning_master: true pytest_coverage_flags: ${{ inputs.pytest_coverage_flags }} pytest_markers: ${{ matrix.config.suite }} disable_new_opmath: ${{ inputs.disable_new_opmath }} @@ -492,7 +492,7 @@ jobs: install_jax: false install_tensorflow: false install_pytorch: false - install_pennylane_lightning_master: false + install_pennylane_lightning_master: true pytest_coverage_flags: ${{ inputs.pytest_coverage_flags }} pytest_markers: data additional_pip_packages: h5py @@ -540,7 +540,7 @@ jobs: install_jax: ${{ contains(matrix.config.device, 'jax') }} install_tensorflow: ${{ contains(matrix.config.device, 'tf') }} install_pytorch: ${{ contains(matrix.config.device, 'torch') }} - install_pennylane_lightning_master: false + install_pennylane_lightning_master: true pytest_test_directory: pennylane/devices/tests pytest_coverage_flags: ${{ inputs.pytest_coverage_flags }} pytest_additional_args: --device=${{ matrix.config.device }} --shots=${{ matrix.config.shots }} From 3828844ed11e44fac263c25666c721df7b6aab7f Mon Sep 17 00:00:00 2001 From: lillian542 Date: Fri, 12 Apr 2024 10:37:03 -0400 Subject: [PATCH 40/59] undo lightning thing --- .github/workflows/interface-unit-tests.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/interface-unit-tests.yml b/.github/workflows/interface-unit-tests.yml index 0673131f5be..2b3c98ed351 100644 --- a/.github/workflows/interface-unit-tests.yml +++ b/.github/workflows/interface-unit-tests.yml @@ -325,7 +325,7 @@ jobs: install_jax: true install_tensorflow: true install_pytorch: true - install_pennylane_lightning_master: true + install_pennylane_lightning_master: false pytest_coverage_flags: ${{ inputs.pytest_coverage_flags }} pytest_markers: all_interfaces requirements_file: ${{ strategy.job-index == 0 && 'all_interfaces.txt' || '' }} @@ -358,7 +358,7 @@ jobs: install_jax: true install_tensorflow: true install_pytorch: false - install_pennylane_lightning_master: true + install_pennylane_lightning_master: false pytest_coverage_flags: ${{ inputs.pytest_coverage_flags }} pytest_markers: external additional_pip_packages: pyzx pennylane-catalyst matplotlib stim @@ -392,7 +392,7 @@ jobs: install_jax: true install_tensorflow: true install_pytorch: true - install_pennylane_lightning_master: true + install_pennylane_lightning_master: false pytest_coverage_flags: ${{ inputs.pytest_coverage_flags }} pytest_markers: qcut additional_pip_packages: kahypar==1.1.7 opt_einsum @@ -425,7 +425,7 @@ jobs: install_jax: false install_tensorflow: false install_pytorch: false - install_pennylane_lightning_master: true + install_pennylane_lightning_master: false pytest_coverage_flags: ${{ inputs.pytest_coverage_flags }} pytest_markers: qchem additional_pip_packages: openfermionpyscf basis-set-exchange @@ -460,7 +460,7 @@ jobs: install_jax: true install_tensorflow: true install_pytorch: true - install_pennylane_lightning_master: true + install_pennylane_lightning_master: false pytest_coverage_flags: ${{ inputs.pytest_coverage_flags }} pytest_markers: ${{ matrix.config.suite }} disable_new_opmath: ${{ inputs.disable_new_opmath }} @@ -492,7 +492,7 @@ jobs: install_jax: false install_tensorflow: false install_pytorch: false - install_pennylane_lightning_master: true + install_pennylane_lightning_master: false pytest_coverage_flags: ${{ inputs.pytest_coverage_flags }} pytest_markers: data additional_pip_packages: h5py @@ -540,7 +540,7 @@ jobs: install_jax: ${{ contains(matrix.config.device, 'jax') }} install_tensorflow: ${{ contains(matrix.config.device, 'tf') }} install_pytorch: ${{ contains(matrix.config.device, 'torch') }} - install_pennylane_lightning_master: true + install_pennylane_lightning_master: false pytest_test_directory: pennylane/devices/tests pytest_coverage_flags: ${{ inputs.pytest_coverage_flags }} pytest_additional_args: --device=${{ matrix.config.device }} --shots=${{ matrix.config.shots }} From 1722b46d0bb1b0678d534e538fd08adeb9c0ce8f Mon Sep 17 00:00:00 2001 From: lillian542 Date: Fri, 12 Apr 2024 11:18:51 -0400 Subject: [PATCH 41/59] use lightning master again --- .github/workflows/interface-unit-tests.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/interface-unit-tests.yml b/.github/workflows/interface-unit-tests.yml index 2b3c98ed351..0673131f5be 100644 --- a/.github/workflows/interface-unit-tests.yml +++ b/.github/workflows/interface-unit-tests.yml @@ -325,7 +325,7 @@ jobs: install_jax: true install_tensorflow: true install_pytorch: true - install_pennylane_lightning_master: false + install_pennylane_lightning_master: true pytest_coverage_flags: ${{ inputs.pytest_coverage_flags }} pytest_markers: all_interfaces requirements_file: ${{ strategy.job-index == 0 && 'all_interfaces.txt' || '' }} @@ -358,7 +358,7 @@ jobs: install_jax: true install_tensorflow: true install_pytorch: false - install_pennylane_lightning_master: false + install_pennylane_lightning_master: true pytest_coverage_flags: ${{ inputs.pytest_coverage_flags }} pytest_markers: external additional_pip_packages: pyzx pennylane-catalyst matplotlib stim @@ -392,7 +392,7 @@ jobs: install_jax: true install_tensorflow: true install_pytorch: true - install_pennylane_lightning_master: false + install_pennylane_lightning_master: true pytest_coverage_flags: ${{ inputs.pytest_coverage_flags }} pytest_markers: qcut additional_pip_packages: kahypar==1.1.7 opt_einsum @@ -425,7 +425,7 @@ jobs: install_jax: false install_tensorflow: false install_pytorch: false - install_pennylane_lightning_master: false + install_pennylane_lightning_master: true pytest_coverage_flags: ${{ inputs.pytest_coverage_flags }} pytest_markers: qchem additional_pip_packages: openfermionpyscf basis-set-exchange @@ -460,7 +460,7 @@ jobs: install_jax: true install_tensorflow: true install_pytorch: true - install_pennylane_lightning_master: false + install_pennylane_lightning_master: true pytest_coverage_flags: ${{ inputs.pytest_coverage_flags }} pytest_markers: ${{ matrix.config.suite }} disable_new_opmath: ${{ inputs.disable_new_opmath }} @@ -492,7 +492,7 @@ jobs: install_jax: false install_tensorflow: false install_pytorch: false - install_pennylane_lightning_master: false + install_pennylane_lightning_master: true pytest_coverage_flags: ${{ inputs.pytest_coverage_flags }} pytest_markers: data additional_pip_packages: h5py @@ -540,7 +540,7 @@ jobs: install_jax: ${{ contains(matrix.config.device, 'jax') }} install_tensorflow: ${{ contains(matrix.config.device, 'tf') }} install_pytorch: ${{ contains(matrix.config.device, 'torch') }} - install_pennylane_lightning_master: false + install_pennylane_lightning_master: true pytest_test_directory: pennylane/devices/tests pytest_coverage_flags: ${{ inputs.pytest_coverage_flags }} pytest_additional_args: --device=${{ matrix.config.device }} --shots=${{ matrix.config.shots }} From ec5d379dcf0ed2954705f4c7c20fec9c2e6f117b Mon Sep 17 00:00:00 2001 From: lillian542 Date: Fri, 12 Apr 2024 11:19:06 -0400 Subject: [PATCH 42/59] add codecov token --- .github/workflows/legacy_op_math.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/legacy_op_math.yml b/.github/workflows/legacy_op_math.yml index 6b5dd165954..d428eb4485c 100644 --- a/.github/workflows/legacy_op_math.yml +++ b/.github/workflows/legacy_op_math.yml @@ -9,6 +9,8 @@ on: jobs: tests: uses: ./.github/workflows/interface-unit-tests.yml + secrets: + codecov_token: ${{ secrets.CODECOV_TOKEN }} with: branch: ${{ github.ref }} # this should be set back to master before merging run_lightened_ci: false From 17ed5ffe384636b4f1e776d7e2bc719b072fbe3b Mon Sep 17 00:00:00 2001 From: lillian542 Date: Fri, 12 Apr 2024 12:38:34 -0400 Subject: [PATCH 43/59] put external libraries back to lightning stable --- .github/workflows/interface-unit-tests.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/interface-unit-tests.yml b/.github/workflows/interface-unit-tests.yml index 779b4c22c08..17088962858 100644 --- a/.github/workflows/interface-unit-tests.yml +++ b/.github/workflows/interface-unit-tests.yml @@ -362,7 +362,8 @@ jobs: install_jax: true install_tensorflow: true install_pytorch: false - install_pennylane_lightning_master: true + # using lightning master does not work for the tests with external libraries + install_pennylane_lightning_master: false pytest_coverage_flags: ${{ inputs.pytest_coverage_flags }} pytest_markers: external additional_pip_packages: pyzx pennylane-catalyst matplotlib stim From 9301d227a2af23926cf9b6d75e38cc3b5824e81a Mon Sep 17 00:00:00 2001 From: lillian542 Date: Fri, 12 Apr 2024 12:38:56 -0400 Subject: [PATCH 44/59] make autograd test compatible with both --- tests/interfaces/test_autograd.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/interfaces/test_autograd.py b/tests/interfaces/test_autograd.py index 384f1669afe..79c328da7f9 100644 --- a/tests/interfaces/test_autograd.py +++ b/tests/interfaces/test_autograd.py @@ -200,8 +200,12 @@ def test_no_batch_transform(self, mocker): tape = qml.tape.QuantumScript.from_queue(q) spy = mocker.spy(dev, "batch_transform") - res = qml.execute([tape], dev, None, device_batch_transform=False) - assert np.allclose(res[0], np.cos(y), atol=0.1) + if qml.operation.active_new_opmath(): + res = qml.execute([tape], dev, None, device_batch_transform=False) + assert np.allclose(res[0], np.cos(y), atol=0.1) + else: + with pytest.raises(AssertionError, match="Hamiltonian must be used with shots=None"): + qml.execute([tape], dev, None, device_batch_transform=False) spy.assert_not_called() From 837aee51949bd29478d9437003a21550d03c9168 Mon Sep 17 00:00:00 2001 From: lillian542 Date: Fri, 12 Apr 2024 13:01:07 -0400 Subject: [PATCH 45/59] temporarily comment out test --- .../test_default_qubit_tracking.py | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/tests/devices/default_qubit/test_default_qubit_tracking.py b/tests/devices/default_qubit/test_default_qubit_tracking.py index 3975a42145c..46b6e744d78 100644 --- a/tests/devices/default_qubit/test_default_qubit_tracking.py +++ b/tests/devices/default_qubit/test_default_qubit_tracking.py @@ -252,22 +252,22 @@ def test_single_expval(mps, expected_exec, expected_shots): assert dev.tracker.totals["shots"] == 3 * expected_shots -@pytest.mark.xfail # TODO Prod instances are not automatically -def test_multiple_expval_with_prods(): - mps, expected_exec, expected_shots = ( - [qml.expval(qml.PauliX(0)), qml.expval(qml.PauliX(0) @ qml.PauliY(1))], - 1, - 10, - ) - dev = qml.device("default.qubit") - tape = qml.tape.QuantumScript([], mps, shots=10) - - with dev.tracker: - dev.execute(tape) - - assert dev.tracker.totals["executions"] == expected_exec - assert dev.tracker.totals["simulations"] == 1 - assert dev.tracker.totals["shots"] == expected_shots +# @pytest.mark.xfail # TODO Prod instances are not automatically +# def test_multiple_expval_with_prods(): +# mps, expected_exec, expected_shots = ( +# [qml.expval(qml.PauliX(0)), qml.expval(qml.PauliX(0) @ qml.PauliY(1))], +# 1, +# 10, +# ) +# dev = qml.device("default.qubit") +# tape = qml.tape.QuantumScript([], mps, shots=10) +# +# with dev.tracker: +# dev.execute(tape) +# +# assert dev.tracker.totals["executions"] == expected_exec +# assert dev.tracker.totals["simulations"] == 1 +# assert dev.tracker.totals["shots"] == expected_shots @pytest.mark.usefixtures("use_legacy_opmath") From 0ee82e7e66c3613e35e71c46d5759b624a2f5862 Mon Sep 17 00:00:00 2001 From: lillian542 Date: Fri, 12 Apr 2024 16:42:26 -0400 Subject: [PATCH 46/59] update tests --- tests/ops/functions/test_generator.py | 2 ++ tests/ops/op_math/test_adjoint.py | 6 ++++-- tests/ops/op_math/test_evolution.py | 3 ++- tests/ops/op_math/test_linear_combination.py | 2 +- tests/ops/op_math/test_sum.py | 1 + tests/test_qaoa.py | 1 + tests/test_queuing.py | 1 + tests/test_vqe.py | 22 ++++++++++++++++++++ 8 files changed, 34 insertions(+), 4 deletions(-) diff --git a/tests/ops/functions/test_generator.py b/tests/ops/functions/test_generator.py index 935eddb0b90..23a60a946a6 100644 --- a/tests/ops/functions/test_generator.py +++ b/tests/ops/functions/test_generator.py @@ -348,6 +348,7 @@ def test_observable(self): assert gen.name == "Hamiltonian" assert gen.compare(ObservableOp(0.5, wires=0).generator()) + @pytest.mark.usefixtures("use_new_opmath") def test_observable_opmath(self): """Test a generator that returns a single observable is correct with opmath enabled""" gen = qml.generator(ObservableOp, format="observable")(0.5, wires=0) @@ -361,6 +362,7 @@ def test_tensor_observable(self): assert gen.name == "Hamiltonian" assert gen.compare(TensorOp(0.5, wires=[0, 1]).generator()) + @pytest.mark.usefixtures("use_new_opmath") def test_tensor_observable_opmath(self): """Test a generator that returns a tensor observable is correct with opmath enabled""" gen = qml.generator(TensorOp, format="observable")(0.5, wires=[0, 1]) diff --git a/tests/ops/op_math/test_adjoint.py b/tests/ops/op_math/test_adjoint.py index 58504bfd7bc..f84afe58901 100644 --- a/tests/ops/op_math/test_adjoint.py +++ b/tests/ops/op_math/test_adjoint.py @@ -124,6 +124,7 @@ def test_pickling(self, op): class TestInitialization: """Test the initialization process and standard properties.""" + # pylint: disable=use-implicit-booleaness-not-comparison def test_nonparametric_ops(self): """Test adjoint initialization for a non parameteric operation.""" base = qml.PauliX("a") @@ -1049,7 +1050,6 @@ def test_single_op_eager(self): assert isinstance(out, qml.RX) assert out.data == (-x,) - @pytest.mark.xfail # TODO not sure what the expected behavior here is with new opmath def test_observable(self): """Test providing a preconstructed Observable outside of a queuing context.""" @@ -1057,7 +1057,9 @@ def test_observable(self): obs = adjoint(base) assert isinstance(obs, Adjoint) - assert isinstance(obs, qml.operation.Observable) + assert isinstance(base, qml.operation.Observable) == isinstance( + obs, qml.operation.Observable + ) assert obs.base is base def test_single_op_function(self): diff --git a/tests/ops/op_math/test_evolution.py b/tests/ops/op_math/test_evolution.py index 852b557593b..5ee11ea5b52 100644 --- a/tests/ops/op_math/test_evolution.py +++ b/tests/ops/op_math/test_evolution.py @@ -72,13 +72,14 @@ def test_generator(self): assert U.base == U.generator() @pytest.mark.usefixtures("use_legacy_opmath") - def test_num_params_for_parametric_bas_legacy_opmath(self): + def test_num_params_for_parametric_base_legacy_opmath(self): base_op = 0.5 * qml.PauliY(0) + qml.PauliZ(0) @ qml.PauliX(1) op = Evolution(base_op, 1.23) assert base_op.num_params == 2 assert op.num_params == 1 + @pytest.mark.usefixtures("use_new_opmath") def test_num_params_for_parametric_base(self): base_op = 0.5 * qml.PauliY(0) + qml.PauliZ(0) @ qml.PauliX(1) op = Evolution(base_op, 1.23) diff --git a/tests/ops/op_math/test_linear_combination.py b/tests/ops/op_math/test_linear_combination.py index cb05bcbfda0..52970279b70 100644 --- a/tests/ops/op_math/test_linear_combination.py +++ b/tests/ops/op_math/test_linear_combination.py @@ -535,6 +535,7 @@ def circuit2(param): dev = qml.device("default.qubit", wires=2) +@pytest.mark.usefixtures("use_new_opmath") class TestLinearCombination: """Test the LinearCombination class""" @@ -912,7 +913,6 @@ def test_LinearCombination_queue_outside(self): def test_LinearCombination_queue_inside(self): """Tests that LinearCombination are queued correctly when components are instantiated inside the recording context.""" - assert qml.operation.active_new_opmath() with qml.queuing.AnnotatedQueue() as q: m = qml.expval(qml.ops.LinearCombination([1, 3, 1], [X(1), Z(0) @ Z(2), Z(1)])) diff --git a/tests/ops/op_math/test_sum.py b/tests/ops/op_math/test_sum.py index 32c149f412e..9c3203ea13f 100644 --- a/tests/ops/op_math/test_sum.py +++ b/tests/ops/op_math/test_sum.py @@ -328,6 +328,7 @@ def test_repr(self, op, repr_true): # qml.sum(*[0.5 * X(i) for i in range(10)]) # multiline output needs fixing of https://github.com/PennyLaneAI/pennylane/issues/5162 before working ) + @pytest.mark.usefixtures("use_new_opmath") @pytest.mark.parametrize("op", SUM_REPR_EVAL) def test_eval_sum(self, op): """Test that string representations of Sum can be evaluated and yield the same operator""" diff --git a/tests/test_qaoa.py b/tests/test_qaoa.py index 84ed32f7446..591b5a5ce3f 100644 --- a/tests/test_qaoa.py +++ b/tests/test_qaoa.py @@ -2018,6 +2018,7 @@ def test_inner_net_flow_constraint_hamiltonian_error(self, g): @pytest.mark.parametrize( "g", [nx.complete_graph(3).to_directed(), rx.generators.directed_mesh_graph(3, [0, 1, 2])] ) + @pytest.mark.usefixtures("use_new_opmath") def test_inner_out_flow_constraint_hamiltonian_non_complete(self, g): """Test if the _inner_out_flow_constraint_hamiltonian function returns the expected result on a manually-calculated example of a 3-node complete digraph relative to the 0 node, with diff --git a/tests/test_queuing.py b/tests/test_queuing.py index 7f335027553..48bb6a30891 100644 --- a/tests/test_queuing.py +++ b/tests/test_queuing.py @@ -224,6 +224,7 @@ def test_append_tensor_ops_overloaded(self): assert q.queue == [tensor_op] assert tensor_op.obs == [A, B] + @pytest.mark.usefixtures("use_new_opmath") def test_append_prod_ops_overloaded(self): """Test that Prod ops created using `@` are successfully added to the queue, as well as the `Prod` object.""" diff --git a/tests/test_vqe.py b/tests/test_vqe.py index 1ab64be9838..aa78b7ff6f2 100644 --- a/tests/test_vqe.py +++ b/tests/test_vqe.py @@ -1019,9 +1019,31 @@ def circuit(w): dc = jax.grad(circuit)(w) assert np.allclose(dc, big_hamiltonian_grad, atol=tol) + @pytest.mark.usefixtures("use_legacy_opmath") + def test_specs_legacy(self): + """Test that the specs of a VQE circuit can be computed""" + dev = qml.device("default.qubit", wires=2) + H = qml.Hamiltonian([0.1, 0.2], [qml.PauliZ(0), qml.PauliZ(0) @ qml.PauliX(1)]) + + @qml.qnode(dev) + def circuit(): + qml.Hadamard(wires=0) + qml.CNOT(wires=[0, 1]) + return qml.expval(H) + + res = qml.specs(circuit)() + + assert res["num_observables"] == 1 + + # currently this returns 1 instead, because diagonalizing gates exist for H, + # but they aren't used in executing this qnode + # to be revisited in [sc-59117] + assert res["num_diagonalizing_gates"] == 0 + @pytest.mark.xfail( reason="diagonalizing gates defined but not used, should not be included in specs" ) + @pytest.mark.usefixtures("use_new_opmath") def test_specs(self): """Test that the specs of a VQE circuit can be computed""" dev = qml.device("default.qubit", wires=2) From d31585ea7fe35ff048380d903a23a4ff37ea63c3 Mon Sep 17 00:00:00 2001 From: lillian542 Date: Fri, 12 Apr 2024 17:09:59 -0400 Subject: [PATCH 47/59] update based on code review --- tests/devices/test_default_qubit_tf.py | 2 +- tests/devices/test_default_qubit_torch.py | 2 +- tests/interfaces/test_autograd.py | 9 +++------ 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/tests/devices/test_default_qubit_tf.py b/tests/devices/test_default_qubit_tf.py index 474ef10e47b..195a5e7adfe 100644 --- a/tests/devices/test_default_qubit_tf.py +++ b/tests/devices/test_default_qubit_tf.py @@ -933,7 +933,7 @@ def test_direct_eval_hamiltonian_broadcasted_tf(self): """Tests that the correct result is returned when attempting to evaluate a Hamiltonian with broadcasting and shots=None directly via its sparse representation with TF.""" dev = qml.device("default.qubit.tf", wires=2) - ham = qml.Hamiltonian(tf.Variable([0.1, 0.2]), [qml.PauliX(0), qml.PauliZ(1)]) + ham = qml.ops.LinearCombination(tf.Variable([0.1, 0.2]), [qml.PauliX(0), qml.PauliZ(1)]) @qml.qnode(dev, diff_method="backprop", interface="tf") def circuit(): diff --git a/tests/devices/test_default_qubit_torch.py b/tests/devices/test_default_qubit_torch.py index 012bc3e2536..9bcbae44b03 100644 --- a/tests/devices/test_default_qubit_torch.py +++ b/tests/devices/test_default_qubit_torch.py @@ -920,7 +920,7 @@ def test_direct_eval_hamiltonian_broadcasted_torch(self, device, torch_device, m broadcasting and shots=None directly via its sparse representation with torch.""" dev = device(wires=2, torch_device=torch_device) - ham = qml.Hamiltonian( + ham = qml.ops.LinearCombination( torch.tensor([0.1, 0.2], requires_grad=True), [qml.PauliX(0), qml.PauliZ(1)] ) diff --git a/tests/interfaces/test_autograd.py b/tests/interfaces/test_autograd.py index 79c328da7f9..69b76a88152 100644 --- a/tests/interfaces/test_autograd.py +++ b/tests/interfaces/test_autograd.py @@ -183,6 +183,7 @@ class TestBatchTransformExecution: """Tests to ensure batch transforms can be correctly executed via qml.execute and map_batch_transform""" + @pytest.mark.usefixtures("use_new_opmath") def test_no_batch_transform(self, mocker): """Test that batch transforms can be disabled and enabled""" dev = qml.device("default.qubit.legacy", wires=2, shots=100000) @@ -200,12 +201,8 @@ def test_no_batch_transform(self, mocker): tape = qml.tape.QuantumScript.from_queue(q) spy = mocker.spy(dev, "batch_transform") - if qml.operation.active_new_opmath(): - res = qml.execute([tape], dev, None, device_batch_transform=False) - assert np.allclose(res[0], np.cos(y), atol=0.1) - else: - with pytest.raises(AssertionError, match="Hamiltonian must be used with shots=None"): - qml.execute([tape], dev, None, device_batch_transform=False) + res = qml.execute([tape], dev, None, device_batch_transform=False) + assert np.allclose(res[0], np.cos(y), atol=0.1) spy.assert_not_called() From 0ffda5d7732f4b59794082c825b71fac2997ed15 Mon Sep 17 00:00:00 2001 From: lillian542 Date: Fri, 12 Apr 2024 18:00:34 -0400 Subject: [PATCH 48/59] add test for lines added to hamiltonian --- tests/ops/qubit/test_hamiltonian.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tests/ops/qubit/test_hamiltonian.py b/tests/ops/qubit/test_hamiltonian.py index c88b1978a92..8f94639936f 100644 --- a/tests/ops/qubit/test_hamiltonian.py +++ b/tests/ops/qubit/test_hamiltonian.py @@ -14,7 +14,7 @@ """ Tests for the Hamiltonian class. """ -# pylint: disable=too-many-public-methods +# pylint: disable=too-many-public-methods, superfluous-parens, unnecessary-dunder-call from collections.abc import Iterable from unittest.mock import patch @@ -678,6 +678,16 @@ def circuit2(param): dev = qml.device("default.qubit", wires=2) +@pytest.mark.usefixtures("use_legacy_and_new_opmath") +@pytest.mark.filterwarnings("ignore::pennylane.PennyLaneDeprecationWarning") +def test_hamiltonian_accepts_prod_observables(): + """Test that prods of observables can be passed to Hamiltonian. Note that we don't + really want that to happen, since old and new operator arithmetic should not be mixed. + Added to simplify generating test parameterizations.""" + # behold, no error is raised: + qml.ops.Hamiltonian([1, 2], [qml.PauliX(0), qml.prod(qml.PauliY(0), qml.PauliZ(1))]) + + @pytest.mark.usefixtures("use_legacy_and_new_opmath") def test_matmul_queuing(): """Test that the other and self are removed during Hamiltonian.__matmul__ .""" From b50bf154d9f7b5b588c4d40002a8d6f3d901a899 Mon Sep 17 00:00:00 2001 From: lillian542 Date: Fri, 12 Apr 2024 18:19:25 -0400 Subject: [PATCH 49/59] mark new opmath version as xfail --- .../test_default_qubit_tracking.py | 37 ++++++++++--------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/tests/devices/default_qubit/test_default_qubit_tracking.py b/tests/devices/default_qubit/test_default_qubit_tracking.py index 46b6e744d78..5390ee04fde 100644 --- a/tests/devices/default_qubit/test_default_qubit_tracking.py +++ b/tests/devices/default_qubit/test_default_qubit_tracking.py @@ -252,26 +252,29 @@ def test_single_expval(mps, expected_exec, expected_shots): assert dev.tracker.totals["shots"] == 3 * expected_shots -# @pytest.mark.xfail # TODO Prod instances are not automatically -# def test_multiple_expval_with_prods(): -# mps, expected_exec, expected_shots = ( -# [qml.expval(qml.PauliX(0)), qml.expval(qml.PauliX(0) @ qml.PauliY(1))], -# 1, -# 10, -# ) -# dev = qml.device("default.qubit") -# tape = qml.tape.QuantumScript([], mps, shots=10) -# -# with dev.tracker: -# dev.execute(tape) -# -# assert dev.tracker.totals["executions"] == expected_exec -# assert dev.tracker.totals["simulations"] == 1 -# assert dev.tracker.totals["shots"] == expected_shots +@pytest.mark.usefixtures("use_new_opmath") +@pytest.mark.xfail(reason="bug in grouping for tracker with new opmath") +def test_multiple_expval_with_prods(): + """Can be combined with test below once the bug is fixed - there shouldn't + be a difference in behaviour between old and new opmath here""" + mps, expected_exec, expected_shots = ( + [qml.expval(qml.PauliX(0)), qml.expval(qml.PauliX(0) @ qml.PauliY(1))], + 1, + 10, + ) + dev = qml.device("default.qubit") + tape = qml.tape.QuantumScript([], mps, shots=10) + + with dev.tracker: + dev.execute(tape) + + assert dev.tracker.totals["executions"] == expected_exec + assert dev.tracker.totals["simulations"] == 1 + assert dev.tracker.totals["shots"] == expected_shots @pytest.mark.usefixtures("use_legacy_opmath") -def test_multiple_expval_with_Tensors_legacy_opmath(): +def test_multiple_expval_with_tensors_legacy_opmath(): mps, expected_exec, expected_shots = ( [qml.expval(qml.PauliX(0)), qml.expval(qml.operation.Tensor(qml.PauliX(0), qml.PauliY(1)))], 1, From da3bfb7528a875dafbaf859ed26695f8c8eae307 Mon Sep 17 00:00:00 2001 From: lillian542 Date: Mon, 15 Apr 2024 21:56:17 -0400 Subject: [PATCH 50/59] update tests --- tests/ops/functions/test_equal.py | 2 + tests/ops/qubit/test_parametric_ops.py | 1 + tests/pauli/test_conversion.py | 8 ++++ tests/pauli/test_pauli_utils.py | 1 + tests/test_device.py | 1 + tests/test_operation.py | 55 +++++++++++++------------- 6 files changed, 40 insertions(+), 28 deletions(-) diff --git a/tests/ops/functions/test_equal.py b/tests/ops/functions/test_equal.py index f9d61178894..e0b89c53024 100644 --- a/tests/ops/functions/test_equal.py +++ b/tests/ops/functions/test_equal.py @@ -1647,6 +1647,7 @@ def test_s_prod_comparison_with_tolerance(self): assert not qml.equal(op1, op2, atol=1e-5, rtol=1e-4) +@pytest.mark.usefixtures("use_new_opmath") class TestProdComparisons: """Tests comparisons between Prod operators""" @@ -1744,6 +1745,7 @@ def test_prod_of_prods(self): assert qml.equal(op1, op2) +@pytest.mark.usefixtures("use_new_opmath") class TestSumComparisons: """Tests comparisons between Sum operators""" diff --git a/tests/ops/qubit/test_parametric_ops.py b/tests/ops/qubit/test_parametric_ops.py index 88ead3da971..fc3c49928ae 100644 --- a/tests/ops/qubit/test_parametric_ops.py +++ b/tests/ops/qubit/test_parametric_ops.py @@ -3028,6 +3028,7 @@ def test_pauli_rot_generator_legacy_opmath(self): assert gen.operands[0].name == expected.obs[0].name assert gen.operands[1].wires == expected.obs[1].wires + @pytest.mark.usefixtures("use_new_opmath") def test_pauli_rot_generator(self): """Test that the generator of the PauliRot operation is correctly returned.""" diff --git a/tests/pauli/test_conversion.py b/tests/pauli/test_conversion.py index f111c562bb5..9753b953e3e 100644 --- a/tests/pauli/test_conversion.py +++ b/tests/pauli/test_conversion.py @@ -143,6 +143,7 @@ def test_observable_types_legacy_opmath(self, hamiltonian, hide_identity): _, decomposed_obs = qml.pauli_decompose(hamiltonian, hide_identity).terms() assert all((isinstance(o, allowed_obs) for o in decomposed_obs)) + @pytest.mark.usefixtures("use_new_opmath") @pytest.mark.parametrize("hide_identity", [True, False]) @pytest.mark.parametrize("hamiltonian", test_hamiltonians) def test_observable_types(self, hamiltonian, hide_identity): @@ -162,6 +163,7 @@ def test_result_length(self, hamiltonian): tensors = filter(lambda obs: isinstance(obs, Tensor), decomposed_obs) assert all(len(tensor.obs) == n for tensor in tensors) + # pylint: disable = consider-using-generator @pytest.mark.parametrize("hamiltonian", test_hamiltonians) def test_decomposition(self, hamiltonian): """Tests that pauli_decompose successfully decomposes Hamiltonians into a @@ -266,6 +268,7 @@ def test_observable_types_legacy_opmath(self, hamiltonian, hide_identity): ).terms() assert all((isinstance(o, allowed_obs) for o in decomposed_obs)) + @pytest.mark.usefixtures("use_new_opmath") @pytest.mark.parametrize("hide_identity", [True, False]) @pytest.mark.parametrize("hamiltonian", test_hamiltonians) def test_observable_types(self, hamiltonian, hide_identity): @@ -288,6 +291,7 @@ def test_result_length(self, hamiltonian): tensors = filter(lambda obs: isinstance(obs, Tensor), decomposed_obs) assert all(len(tensor.obs) == n for tensor in tensors) + # pylint: disable = consider-using-generator @pytest.mark.parametrize("hamiltonian", test_hamiltonians) def test_decomposition(self, hamiltonian): """Tests that pauli_decompose successfully decomposes Hamiltonians into a @@ -314,6 +318,7 @@ def test_to_paulisentence(self, hamiltonian): assert isinstance(ps, qml.pauli.PauliSentence) assert np.allclose(hamiltonian, ps.to_mat(range(num_qubits))) + # pylint: disable = consider-using-generator @pytest.mark.usefixtures("use_legacy_opmath") @pytest.mark.parametrize("hide_identity", [True, False]) @pytest.mark.parametrize("matrix", test_general_matrix) @@ -342,6 +347,8 @@ def test_observable_types_general_legacy_opmath(self, matrix, hide_identity): tensors = filter(lambda obs: isinstance(obs, Tensor), decomposed_obs) assert all(len(tensor.obs) == num_qubits for tensor in tensors) + # pylint: disable = consider-using-generator + @pytest.mark.usefixtures("use_new_opmath") @pytest.mark.parametrize("hide_identity", [True, False]) @pytest.mark.parametrize("matrix", test_general_matrix) def test_observable_types_general(self, matrix, hide_identity): @@ -428,6 +435,7 @@ def test_builtins(self, matrix): coeffs = qml.pauli_decompose(mat).coeffs assert qml.math.get_interface(coeffs[0]) == interface + # pylint: disable = superfluous-parens # Multiple interfaces will be tested with math module @pytest.mark.all_interfaces @pytest.mark.parametrize( diff --git a/tests/pauli/test_pauli_utils.py b/tests/pauli/test_pauli_utils.py index fa386c493d4..2f21637e06e 100644 --- a/tests/pauli/test_pauli_utils.py +++ b/tests/pauli/test_pauli_utils.py @@ -471,6 +471,7 @@ def test_pauli_word_to_string_invalid_input(self, non_pauli_word): with pytest.raises(TypeError): pauli_word_to_string(non_pauli_word) + @pytest.mark.usefixtures("use_new_opmath") @pytest.mark.parametrize( "pauli_string,wire_map,expected_pauli", [ diff --git a/tests/test_device.py b/tests/test_device.py index 0422e9dfd79..96064b9d894 100644 --- a/tests/test_device.py +++ b/tests/test_device.py @@ -357,6 +357,7 @@ def test_check_validity_on_tensor_support_legacy_opmath(self, mock_device_suppor with pytest.raises(DeviceError, match="Tensor observables not supported"): dev.check_validity(queue, observables) + @pytest.mark.usefixtures("use_new_opmath") def test_check_validity_on_prod_support(self, mock_device_supporting_paulis): """Tests the function Device.check_validity with prod support capability""" dev = mock_device_supporting_paulis() diff --git a/tests/test_operation.py b/tests/test_operation.py index b473f4c5b39..a476200a3a7 100644 --- a/tests/test_operation.py +++ b/tests/test_operation.py @@ -2632,15 +2632,10 @@ def test_composed(self): ] +@pytest.mark.usefixtures("use_new_opmath") class TestNewOpMath: """Tests dunder operations with new operator arithmetic enabled.""" - # @pytest.fixture(autouse=True, scope="function") # this came from a push to ham-tests but I think it should not be there as it explicitly disabled new opmath after each test, so also leaving it in that state for other tests. - # def run_before_and_after_tests(self): - # qml.operation.enable_new_opmath() - # yield - # qml.operation.disable_new_opmath() - class TestAdd: """Test the __add__/__radd__/__sub__ dunders.""" @@ -2755,32 +2750,33 @@ def test_mul_does_not_auto_simplify(self): assert qml.equal(op[0], op0 @ op1) assert qml.equal(op[1], op2) - class TestHamiltonianLinearCombinationAlias: - """Unit tests for using qml.Hamiltonian as an alias for LinearCombination""" - @pytest.mark.usefixtures("use_new_opmath") - def test_hamiltonian_linear_combination_alias_enabled(self): - """Test that qml.Hamiltonian is an alias for LinearCombination with new operator - arithmetic enabled""" - op = qml.Hamiltonian([1.0], [qml.X(0)]) +class TestHamiltonianLinearCombinationAlias: + """Unit tests for using qml.Hamiltonian as an alias for LinearCombination""" + + @pytest.mark.usefixtures("use_new_opmath") + def test_hamiltonian_linear_combination_alias_enabled(self): + """Test that qml.Hamiltonian is an alias for LinearCombination with new operator + arithmetic enabled""" + op = qml.Hamiltonian([1.0], [qml.X(0)]) - assert isinstance(op, qml.ops.LinearCombination) - assert isinstance(op, qml.Hamiltonian) - assert not isinstance(op, qml.ops.Hamiltonian) - assert not isinstance(op, qml.ops.qubit.Hamiltonian) - assert not isinstance(op, qml.ops.qubit.hamiltonian.Hamiltonian) + assert isinstance(op, qml.ops.LinearCombination) + assert isinstance(op, qml.Hamiltonian) + assert not isinstance(op, qml.ops.Hamiltonian) + assert not isinstance(op, qml.ops.qubit.Hamiltonian) + assert not isinstance(op, qml.ops.qubit.hamiltonian.Hamiltonian) - @pytest.mark.usefixtures("use_legacy_opmath") - def test_hamiltonian_linear_combination_alias_disabled(self): - """Test that qml.Hamiltonian is not an alias for LinearCombination with new operator - arithmetic disabled""" - op = qml.Hamiltonian([1.0], [qml.X(0)]) + @pytest.mark.usefixtures("use_legacy_opmath") + def test_hamiltonian_linear_combination_alias_disabled(self): + """Test that qml.Hamiltonian is not an alias for LinearCombination with new operator + arithmetic disabled""" + op = qml.Hamiltonian([1.0], [qml.X(0)]) - assert not isinstance(op, qml.ops.LinearCombination) - assert isinstance(op, qml.Hamiltonian) - assert isinstance(op, qml.ops.Hamiltonian) - assert isinstance(op, qml.ops.qubit.Hamiltonian) - assert isinstance(op, qml.ops.qubit.hamiltonian.Hamiltonian) + assert not isinstance(op, qml.ops.LinearCombination) + assert isinstance(op, qml.Hamiltonian) + assert isinstance(op, qml.ops.Hamiltonian) + assert isinstance(op, qml.ops.qubit.Hamiltonian) + assert isinstance(op, qml.ops.qubit.hamiltonian.Hamiltonian) @pytest.mark.parametrize( @@ -2819,6 +2815,7 @@ def test_symmetric_matrix_early_return(op, mocker): assert np.allclose(actual, manually_expanded) +@pytest.mark.usefixtures("use_new_opmath") def test_op_arithmetic_toggle(): """Tests toggling op arithmetic on and off, and that it is on by default.""" assert qml.operation.active_new_opmath() @@ -2954,6 +2951,7 @@ def test_use_legacy_opmath_fixture(): ] +@pytest.mark.usefixtures("use_new_opmath") @pytest.mark.parametrize("coeffs, obs", CONVERT_HAMILTONAIN) def test_convert_to_hamiltonian(coeffs, obs): """Test that arithmetic operators can be converted to Hamiltonian instances""" @@ -2999,6 +2997,7 @@ def test_convert_to_hamiltonian_error(coeffs, obs): convert_to_legacy_H(qml.dot(coeffs, obs)) +@pytest.mark.usefixtures("use_new_opmath") def test_convert_to_H(): operator = ( 2 * qml.X(0) From d9508ac62dafdee01e867d98a67d9f0e5a013b5a Mon Sep 17 00:00:00 2001 From: lillian542 Date: Mon, 15 Apr 2024 22:02:06 -0400 Subject: [PATCH 51/59] revert changes to hamiltonian --- pennylane/ops/qubit/hamiltonian.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/pennylane/ops/qubit/hamiltonian.py b/pennylane/ops/qubit/hamiltonian.py index ecdf6561d87..17c6de25277 100644 --- a/pennylane/ops/qubit/hamiltonian.py +++ b/pennylane/ops/qubit/hamiltonian.py @@ -203,11 +203,6 @@ def __init__( ) for obs in observables: - if isinstance(obs, qml.ops.Prod): - # we don't really want this to ever happen, but it makes testing easier during the deprecation phase - # because we don't have to generate separate lists of parametrization for old and new opmath testing - obs = qml.simplify(obs) - obs = qml.operation.Tensor(*obs) if not isinstance(obs, Observable): raise ValueError( "Could not create circuits. Some or all observables are not valid." From 994f8342a569068a02ddc599046d03f3f47a8362 Mon Sep 17 00:00:00 2001 From: lillian542 Date: Mon, 15 Apr 2024 22:28:24 -0400 Subject: [PATCH 52/59] revert added hamiltonian test --- tests/ops/qubit/test_hamiltonian.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/tests/ops/qubit/test_hamiltonian.py b/tests/ops/qubit/test_hamiltonian.py index 8f94639936f..9db2647a87f 100644 --- a/tests/ops/qubit/test_hamiltonian.py +++ b/tests/ops/qubit/test_hamiltonian.py @@ -678,16 +678,6 @@ def circuit2(param): dev = qml.device("default.qubit", wires=2) -@pytest.mark.usefixtures("use_legacy_and_new_opmath") -@pytest.mark.filterwarnings("ignore::pennylane.PennyLaneDeprecationWarning") -def test_hamiltonian_accepts_prod_observables(): - """Test that prods of observables can be passed to Hamiltonian. Note that we don't - really want that to happen, since old and new operator arithmetic should not be mixed. - Added to simplify generating test parameterizations.""" - # behold, no error is raised: - qml.ops.Hamiltonian([1, 2], [qml.PauliX(0), qml.prod(qml.PauliY(0), qml.PauliZ(1))]) - - @pytest.mark.usefixtures("use_legacy_and_new_opmath") def test_matmul_queuing(): """Test that the other and self are removed during Hamiltonian.__matmul__ .""" From 37ddf42d56b37f5710aae15f43336ccec289062e Mon Sep 17 00:00:00 2001 From: lillian542 Date: Mon, 15 Apr 2024 23:05:21 -0400 Subject: [PATCH 53/59] update qcut tests --- tests/transforms/test_qcut.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/transforms/test_qcut.py b/tests/transforms/test_qcut.py index bdb253e0769..a59938fff15 100644 --- a/tests/transforms/test_qcut.py +++ b/tests/transforms/test_qcut.py @@ -5716,7 +5716,7 @@ def test_circuit_with_hamiltonian_opmath(self, mocker): hamiltonian = qml.Hamiltonian( [1.0, 1.0], - [qml.prod(qml.PauliZ(1), qml.PauliZ(2), qml.PauliZ(3)), qml.PauliY(0) @ qml.PauliX(1)], + [qml.PauliZ(1) @ qml.PauliZ(2) @ qml.PauliZ(3), qml.PauliY(0) @ qml.PauliX(1)], ) def two_qubit_unitary(param, wires): @@ -5840,8 +5840,8 @@ def block(weights, wires): hamiltonian = qml.Hamiltonian( [1.0, 1.0], [ - qml.prod(qml.PauliZ(1), qml.PauliZ(8), qml.PauliZ(3)), - qml.prod(qml.PauliY(5), qml.PauliX(4)), + qml.PauliZ(1) @ qml.PauliZ(8) @ qml.PauliZ(3), + qml.PauliY(5) @ qml.PauliX(4), ], ) From 42442b6ed518c2bf37a07bf34e50107cb997a02c Mon Sep 17 00:00:00 2001 From: lillian542 Date: Mon, 15 Apr 2024 23:58:17 -0400 Subject: [PATCH 54/59] update fermi tests --- tests/fermi/test_bravyi_kitaev.py | 436 ++++++++++++++++++++++++++++ tests/fermi/test_fermi_mapping.py | 362 +++++++++++++++++++++++ tests/fermi/test_parity_mapping.py | 446 +++++++++++++++++++++++++++++ 3 files changed, 1244 insertions(+) diff --git a/tests/fermi/test_bravyi_kitaev.py b/tests/fermi/test_bravyi_kitaev.py index b962df0ad4e..eefe3470504 100644 --- a/tests/fermi/test_bravyi_kitaev.py +++ b/tests/fermi/test_bravyi_kitaev.py @@ -427,7 +427,412 @@ def test_error_is_raised_for_dimension_mismatch(): ), ] +with qml.operation.disable_new_opmath_cm(): + FERMI_WORDS_AND_OPS_LEGACY = [ + ( + FermiWord({(0, 0): "+"}), + 1, + # trivial case of a creation operator with one qubit, 0^ -> (X_0 - iY_0) / 2 : Same as Jordan-Wigner + ([0.5, -0.5j], [qml.PauliX(0), qml.PauliY(0)]), + ), + ( + FermiWord({(0, 0): "-"}), + 1, + # trivial case of an annihilation operator with one qubit , 0 -> (X_0 + iY_0) / 2 : Same as Jordan-Wigner + ([(0.5 + 0j), (0.0 + 0.5j)], [qml.PauliX(0), qml.PauliY(0)]), + ), + ( + FermiWord({(0, 0): "+"}), + 2, + # trivial case of a creation operator with two qubits, 0^ -> (X_0 @ X_1 - iY_0 @ X_1) / 2 + ([0.5, -0.5j], [qml.PauliX(0) @ qml.PauliX(1), qml.PauliY(0) @ qml.PauliX(1)]), + ), + ( + FermiWord({(0, 0): "-"}), + 2, + # trivial case of an annihilation operator with two qubits , 0 -> (X_0 @ X_1 + iY_0 @ X_1) / 2 + ( + [(0.5 + 0j), (0.0 + 0.5j)], + [qml.PauliX(0) @ qml.PauliX(1), qml.PauliY(0) @ qml.PauliX(1)], + ), + ), + ( + FermiWord({(0, 0): "+", (1, 0): "-"}), + 4, + # obtained with openfermion using: binary_code_transform(FermionOperator('0^ 0'), parity_code(n_qubits)) for n_qubits = 4 + # reformatted the original openfermion output: (0.5+0j) [] + (-0.5+0j) [Z0] + ([(0.5 + 0j), (-0.5 + 0j)], [qml.Identity(0), qml.PauliZ(0)]), + ), + ( + FermiWord({(0, 0): "-", (1, 0): "+"}), + 4, + # obtained with openfermion using: binary_code_transform(FermionOperator('0 0^'), parity_code(n_qubits)) for n_qubits = 4 + # reformatted the original openfermion output: (0.5+0j) [] + (0.5+0j) [Z0] + ([(0.5 + 0j), (0.5 + 0j)], [qml.Identity(0), qml.PauliZ(0)]), + ), + ( + FermiWord({(0, 0): "-", (1, 1): "+"}), + 4, + # obtained with openfermion using: binary_code_transform(FermionOperator('0 1^'), parity_code(n_qubits)) for n_qubits = 4 + # reformatted the original openfermion output: + # (-0.25+0j) [X0] + + # 0.25 [X0 Z1] + + # (-0-0.25j) [Y0] + + # 0.25j [Y0 Z1] + ( + [(-0.25 + 0j), 0.25, (-0 - 0.25j), (0.25j)], + [ + qml.PauliX(0), + qml.PauliX(0) @ qml.PauliZ(1), + qml.PauliY(0), + qml.PauliY(0) @ qml.PauliZ(1), + ], + ), + ), + ( + FermiWord({(0, 3): "+", (1, 0): "-"}), + 4, + # obtained with openfermion using: binary_code_transform(FermionOperator('3^ 0'), parity_code(n_qubits)) for n_qubits = 4 + # reformatted the original openfermion output + # (-0.25+0j) [X0 X1 Z3] + + # 0.25j [X0 Y1 Z2] + + # -0.25j [Y0 X1 Z3] + + # (-0.25+0j) [Y0 Y1 Z2] + ( + [(-0.25 + 0j), 0.25j, (-0 - 0.25j), -0.25], + [ + qml.PauliX(0) @ qml.PauliX(1) @ qml.PauliZ(3), + qml.PauliX(0) @ qml.PauliY(1) @ qml.PauliZ(2), + qml.PauliY(0) @ qml.PauliX(1) @ qml.PauliZ(3), + qml.PauliY(0) @ qml.PauliY(1) @ qml.PauliZ(2), + ], + ), + ), + ( + FermiWord({(0, 5): "+", (1, 5): "-", (2, 5): "+", (3, 5): "-"}), + 6, + # obtained with openfermion using: binary_code_transform(FermionOperator('5^ 5 5^ 5'), parity_code(n_qubits)) with 6 qubits + ( + [(0.5 + 0j), (-0.5 + 0j)], + [qml.Identity(0), qml.PauliZ(4) @ qml.PauliZ(5)], + ), + ), + ( + FermiWord({(0, 3): "+", (1, 3): "-", (2, 3): "+", (3, 1): "-"}), + 6, + # obtained with openfermion using: binary_code_transform(FermionOperator('3^ 3 3^ 1'), parity_code(n_qubits)) with 6 qubits + # (-0.25+0j) [Z0 X1 Z3] + + # 0.25j [Z0 Y1 Z2] + + # (0.25+0j) [X1 Z2] + + # -0.25j [Y1 Z3] + ( + [-0.25, 0.25j, -0.25j, 0.25], + [ + qml.PauliZ(0) @ qml.PauliX(1) @ qml.PauliZ(3), + qml.PauliZ(0) @ qml.PauliY(1) @ qml.PauliZ(2), + qml.PauliY(1) @ qml.PauliZ(3), + qml.PauliX(1) @ qml.PauliZ(2), + ], + ), + ), + ( + FermiWord({(0, 1): "+", (1, 0): "-", (2, 1): "+", (3, 1): "-"}), + 6, + # obtained with openfermion using: binary_code_transform(FermionOperator('1^ 0 1^ 1'), parity_code(n_qubits)) with 6 qubits + ([0], [qml.Identity(0)]), + ), + ] + + FERMI_OPS_COMPLEX_LEGACY = [ + ( + FermiWord({(0, 2): "-", (1, 0): "+", (2, 3): "+"}), + 4, + # obtained with openfermion using: binary_code_transform(FermionOperator('2 0^ 3^'), parity_code(n_qubits)) for n_qubits = 4 + # reformatted the original openfermion output + # (0.125+0j) [X0 X1 X2 X3] + + # 0.125j [X0 X1 Y2 X3] + + # (0.125+0j) [X0 Y1 X2 Y3] + + # 0.125j [X0 Y1 Y2 Y3] + + # -0.125j [Y0 X1 X2 X3] + + # (0.125+0j) [Y0 X1 Y2 X3] + + # -0.125j [Y0 Y1 X2 Y3] + + # (0.125+0j) [Y0 Y1 Y2 Y3] + ( + [0.125, 0.125j, 0.125 + 0j, 0.125j, -0.125j, 0.125 + 0j, -0.125j, 0.125], + [ + qml.PauliX(0) @ qml.PauliX(1) @ qml.PauliX(2) @ qml.PauliX(3), + qml.PauliX(0) @ qml.PauliX(1) @ qml.PauliY(2) @ qml.PauliX(3), + qml.PauliX(0) @ qml.PauliY(1) @ qml.PauliX(2) @ qml.PauliY(3), + qml.PauliX(0) @ qml.PauliY(1) @ qml.PauliY(2) @ qml.PauliY(3), + qml.PauliY(0) @ qml.PauliX(1) @ qml.PauliX(2) @ qml.PauliX(3), + qml.PauliY(0) @ qml.PauliX(1) @ qml.PauliY(2) @ qml.PauliX(3), + qml.PauliY(0) @ qml.PauliY(1) @ qml.PauliX(2) @ qml.PauliY(3), + qml.PauliY(0) @ qml.PauliY(1) @ qml.PauliY(2) @ qml.PauliY(3), + ], + ), + ), + ( + FermiWord({(0, 0): "-", (1, 3): "+"}), + 4, + # obtained with openfermion using: binary_code_transform(FermionOperator('0 3^'), parity_code(n_qubits)) for n_qubits = 4 + # reformatted the original openfermion output + # (0.25+0j) [X0 X1 Z3] + + # -0.25j [X0 Y1 Z2] + + # 0.25j [Y0 X1 Z3] + + # (0.25+0j) [Y0 Y1 Z2] + ( + [0.25, -0.25j, 0.25j, 0.25], + [ + qml.PauliX(0) @ qml.PauliX(1) @ qml.PauliZ(3), + qml.PauliX(0) @ qml.PauliY(1) @ qml.PauliZ(2), + qml.PauliY(0) @ qml.PauliX(1) @ qml.PauliZ(3), + qml.PauliY(0) @ qml.PauliY(1) @ qml.PauliZ(2), + ], + ), + ), + ( + FermiWord({(0, 3): "+", (1, 1): "+", (2, 3): "-", (3, 1): "-"}), + 6, + # obtained with openfermion using: binary_code_transform(FermionOperator('3^ 1^ 3 1'), parity_code(n_qubits)) with 6 qubits + # -0.25 [] + + # 0.25 [Z0 Z1] + + # -0.25 [Z0 Z2 Z3] + + # 0.25 [Z1 Z2 Z3] + # reformatted the original openfermion output + ( + [(-0.25 + 0j), (0.25 + 0j), (-0.25 + 0j), (0.25 + 0j)], + [ + qml.Identity(0), + qml.PauliZ(0) @ qml.PauliZ(1), + qml.PauliZ(0) @ qml.PauliZ(2) @ qml.PauliZ(3), + qml.PauliZ(1) @ qml.PauliZ(2) @ qml.PauliZ(3), + ], + ), + ), + ( + FermiWord({(0, 1): "+", (1, 4): "-", (2, 3): "-", (3, 4): "+"}), + 6, + # obtained with openfermion using: binary_code_transform(FermionOperator('1^ 4 3 4^'), parity_code(n_qubits)) with 6 qubits + # reformatted the original openfermion output + # (0.125+0j) [Z0 X1 Z3] + + # (0.125+0j) [Z0 X1 Z3 Z4] + + # 0.125j [Z0 Y1 Z2] + + # 0.125j [Z0 Y1 Z2 Z4] + + # (-0.125+0j) [X1 Z2] + + # (-0.125+0j) [X1 Z2 Z4] + + # -0.125j [Y1 Z3] + + # -0.125j [Y1 Z3 Z4] + ( + [0.125, 0.125, 0.125j, 0.125j, -0.125, -0.125, -0.125j, -0.125j], + [ + qml.PauliZ(0) @ qml.PauliX(1) @ qml.PauliZ(3), + qml.PauliZ(0) @ qml.PauliX(1) @ qml.PauliZ(3) @ qml.PauliZ(4), + qml.PauliZ(0) @ qml.PauliY(1) @ qml.PauliZ(2), + qml.PauliZ(0) @ qml.PauliY(1) @ qml.PauliZ(2) @ qml.PauliZ(4), + qml.PauliX(1) @ qml.PauliZ(2), + qml.PauliX(1) @ qml.PauliZ(2) @ qml.PauliZ(4), + qml.PauliY(1) @ qml.PauliZ(3), + qml.PauliY(1) @ qml.PauliZ(3) @ qml.PauliZ(4), + ], + ), + ), + ( + FermiWord({(0, 3): "+", (1, 1): "-", (2, 3): "+", (3, 1): "-"}), + 6, + # obtained with openfermion using: binary_code_transform(FermionOperator('3^ 1 3^ 1'), parity_code(n_qubits)) with 6 qubits + ([0], [qml.Identity(3)]), + ), + ( + FermiWord({(0, 1): "+", (1, 0): "+", (2, 4): "-", (3, 5): "-"}), + 6, + # obtained with openfermion using: binary_code_transform(FermionOperator('1^ 0^ 4 5'), parity_code(n_qubits)) with 6 qubits + # (0.0625+0j) [X0 Z1 X4] + + # (0.0625+0j) [X0 Z1 X4 Z5] + + # 0.0625j [X0 Z1 Y4] + + # 0.0625j [X0 Z1 Y4 Z5] + + # (0.0625+0j) [X0 X4] + + # (0.0625+0j) [X0 X4 Z5] + + # 0.0625j [X0 Y4] + + # 0.0625j [X0 Y4 Z5] + + # -0.0625j [Y0 Z1 X4] + + # -0.0625j [Y0 Z1 X4 Z5] + + # (0.0625+0j) [Y0 Z1 Y4] + + # (0.0625+0j) [Y0 Z1 Y4 Z5] + + # -0.0625j [Y0 X4] + + # -0.0625j [Y0 X4 Z5] + + # (0.0625+0j) [Y0 Y4] + + # (0.0625+0j) [Y0 Y4 Z5] + ( + [ + 0.0625, + 0.0625, + 0.0625j, + 0.0625j, + 0.0625, + 0.0625, + 0.0625j, + 0.0625j, + -0.0625j, + -0.0625j, + 0.0625, + 0.0625, + -0.0625j, + -0.0625j, + 0.0625, + 0.0625, + ], + [ + qml.PauliX(0) @ qml.PauliZ(1) @ qml.PauliX(4), + qml.PauliX(0) @ qml.PauliZ(1) @ qml.PauliX(4) @ qml.PauliZ(5), + qml.PauliX(0) @ qml.PauliZ(1) @ qml.PauliY(4), + qml.PauliX(0) @ qml.PauliZ(1) @ qml.PauliY(4) @ qml.PauliZ(5), + qml.PauliX(0) @ qml.PauliX(4), + qml.PauliX(0) @ qml.PauliX(4) @ qml.PauliZ(5), + qml.PauliX(0) @ qml.PauliY(4), + qml.PauliX(0) @ qml.PauliY(4) @ qml.PauliZ(5), + qml.PauliY(0) @ qml.PauliZ(1) @ qml.PauliX(4), + qml.PauliY(0) @ qml.PauliZ(1) @ qml.PauliX(4) @ qml.PauliZ(5), + qml.PauliY(0) @ qml.PauliZ(1) @ qml.PauliY(4), + qml.PauliY(0) @ qml.PauliZ(1) @ qml.PauliY(4) @ qml.PauliZ(5), + qml.PauliY(0) @ qml.PauliX(4), + qml.PauliY(0) @ qml.PauliX(4) @ qml.PauliZ(5), + qml.PauliY(0) @ qml.PauliY(4), + qml.PauliY(0) @ qml.PauliY(4) @ qml.PauliZ(5), + ], + ), + ), + ( + FermiWord({(0, 1): "-", (1, 0): "+"}), + 4, + # obtained with openfermion using: binary_code_transform(FermionOperator('1 0^'), parity_code(n_qubits)) for n_qubits = 4 + # reformatted the original openfermion output: + # -0.25 [X0] + + # 0.25 [X0 Z1] + + # 0.25j [Y0] + + # (-0-0.25j) [Y0 Z1] + ( + [(-0.25 + 0j), 0.25, 0.25j, (-0 - 0.25j)], + [ + qml.PauliX(0), + qml.PauliX(0) @ qml.PauliZ(1), + qml.PauliY(0), + qml.PauliY(0) @ qml.PauliZ(1), + ], + ), + ), + ( + FermiWord( + {(0, 1): "+", (1, 1): "-", (2, 3): "+", (3, 4): "-", (4, 2): "+", (5, 5): "-"} + ), + 6, + # obtained with openfermion using: binary_code_transform(FermionOperator('1^ 1 3^ 4 2^ 5'), parity_code(n_qubits)) with 6 qubits + # (0.03125+0j) [Z0 Z1 X2 X4] + + # (0.03125+0j) [Z0 Z1 X2 X4 Z5] + + # 0.03125j [Z0 Z1 X2 Y4] + + # 0.03125j [Z0 Z1 X2 Y4 Z5] + + # -0.03125j [Z0 Z1 Y2 X4] + + # -0.03125j [Z0 Z1 Y2 X4 Z5] + + # (0.03125+0j) [Z0 Z1 Y2 Y4] + + # (0.03125+0j) [Z0 Z1 Y2 Y4 Z5] + + # (0.03125+0j) [Z0 X2 Z3 X4] + + # (0.03125+0j) [Z0 X2 Z3 X4 Z5] + + # 0.03125j [Z0 X2 Z3 Y4] + + # 0.03125j [Z0 X2 Z3 Y4 Z5] + + # -0.03125j [Z0 Y2 Z3 X4] + + # -0.03125j [Z0 Y2 Z3 X4 Z5] + + # (0.03125+0j) [Z0 Y2 Z3 Y4] + + # (0.03125+0j) [Z0 Y2 Z3 Y4 Z5] + + # (-0.03125+0j) [Z1 X2 Z3 X4] + + # (-0.03125+0j) [Z1 X2 Z3 X4 Z5] + + # -0.03125j [Z1 X2 Z3 Y4] + + # -0.03125j [Z1 X2 Z3 Y4 Z5] + + # 0.03125j [Z1 Y2 Z3 X4] + + # 0.03125j [Z1 Y2 Z3 X4 Z5] + + # (-0.03125+0j) [Z1 Y2 Z3 Y4] + + # (-0.03125+0j) [Z1 Y2 Z3 Y4 Z5] + + # (-0.03125+0j) [X2 X4] + + # (-0.03125+0j) [X2 X4 Z5] + + # -0.03125j [X2 Y4] + + # -0.03125j [X2 Y4 Z5] + + # 0.03125j [Y2 X4] + + # 0.03125j [Y2 X4 Z5] + + # (-0.03125+0j) [Y2 Y4] + + # (-0.03125+0j) [Y2 Y4 Z5] + ( + [ + 0.03125, + 0.03125, + 0.03125j, + 0.03125j, + -0.03125j, + -0.03125j, + 0.03125, + 0.03125, + 0.03125, + 0.03125, + 0.03125j, + 0.03125j, + -0.03125j, + -0.03125j, + 0.03125, + 0.03125, + -0.03125, + -0.03125, + -0.03125j, + -0.03125j, + 0.03125j, + 0.03125j, + -0.03125, + -0.03125, + -0.03125, + -0.03125, + -0.03125j, + -0.03125j, + 0.03125j, + 0.03125j, + -0.03125, + -0.03125, + ], + [ + qml.PauliZ(0) @ qml.PauliZ(1) @ qml.PauliX(2) @ qml.PauliX(4), + qml.PauliZ(0) @ qml.PauliZ(1) @ qml.PauliX(2) @ qml.PauliX(4) @ qml.PauliZ(5), + qml.PauliZ(0) @ qml.PauliZ(1) @ qml.PauliX(2) @ qml.PauliY(4), + qml.PauliZ(0) @ qml.PauliZ(1) @ qml.PauliX(2) @ qml.PauliY(4) @ qml.PauliZ(5), + qml.PauliZ(0) @ qml.PauliZ(1) @ qml.PauliY(2) @ qml.PauliX(4), + qml.PauliZ(0) @ qml.PauliZ(1) @ qml.PauliY(2) @ qml.PauliX(4) @ qml.PauliZ(5), + qml.PauliZ(0) @ qml.PauliZ(1) @ qml.PauliY(2) @ qml.PauliY(4), + qml.PauliZ(0) @ qml.PauliZ(1) @ qml.PauliY(2) @ qml.PauliY(4) @ qml.PauliZ(5), + qml.PauliZ(0) @ qml.PauliX(2) @ qml.PauliZ(3) @ qml.PauliX(4), + qml.PauliZ(0) @ qml.PauliX(2) @ qml.PauliZ(3) @ qml.PauliX(4) @ qml.PauliZ(5), + qml.PauliZ(0) @ qml.PauliX(2) @ qml.PauliZ(3) @ qml.PauliY(4), + qml.PauliZ(0) @ qml.PauliX(2) @ qml.PauliZ(3) @ qml.PauliY(4) @ qml.PauliZ(5), + qml.PauliZ(0) @ qml.PauliY(2) @ qml.PauliZ(3) @ qml.PauliX(4), + qml.PauliZ(0) @ qml.PauliY(2) @ qml.PauliZ(3) @ qml.PauliX(4) @ qml.PauliZ(5), + qml.PauliZ(0) @ qml.PauliY(2) @ qml.PauliZ(3) @ qml.PauliY(4), + qml.PauliZ(0) @ qml.PauliY(2) @ qml.PauliZ(3) @ qml.PauliY(4) @ qml.PauliZ(5), + qml.PauliZ(1) @ qml.PauliX(2) @ qml.PauliZ(3) @ qml.PauliX(4), + qml.PauliZ(1) @ qml.PauliX(2) @ qml.PauliZ(3) @ qml.PauliX(4) @ qml.PauliZ(5), + qml.PauliZ(1) @ qml.PauliX(2) @ qml.PauliZ(3) @ qml.PauliY(4), + qml.PauliZ(1) @ qml.PauliX(2) @ qml.PauliZ(3) @ qml.PauliY(4) @ qml.PauliZ(5), + qml.PauliZ(1) @ qml.PauliY(2) @ qml.PauliZ(3) @ qml.PauliX(4), + qml.PauliZ(1) @ qml.PauliY(2) @ qml.PauliZ(3) @ qml.PauliX(4) @ qml.PauliZ(5), + qml.PauliZ(1) @ qml.PauliY(2) @ qml.PauliZ(3) @ qml.PauliY(4), + qml.PauliZ(1) @ qml.PauliY(2) @ qml.PauliZ(3) @ qml.PauliY(4) @ qml.PauliZ(5), + qml.PauliX(2) @ qml.PauliX(4), + qml.PauliX(2) @ qml.PauliX(4) @ qml.PauliZ(5), + qml.PauliX(2) @ qml.PauliY(4), + qml.PauliX(2) @ qml.PauliY(4) @ qml.PauliZ(5), + qml.PauliY(2) @ qml.PauliX(4), + qml.PauliY(2) @ qml.PauliX(4) @ qml.PauliZ(5), + qml.PauliY(2) @ qml.PauliY(4), + qml.PauliY(2) @ qml.PauliY(4) @ qml.PauliZ(5), + ], + ), + ), + ] + +@pytest.mark.usefixtures("use_new_opmath") @pytest.mark.parametrize("fermionic_op, n_qubits, result", FERMI_WORDS_AND_OPS + FERMI_OPS_COMPLEX) def test_bravyi_kitaev_fermi_word_ps(fermionic_op, n_qubits, result): """Test that the parity_transform function returns the correct qubit operator.""" @@ -442,6 +847,24 @@ def test_bravyi_kitaev_fermi_word_ps(fermionic_op, n_qubits, result): assert qubit_op == expected_op +@pytest.mark.usefixtures("use_legacy_opmath") +@pytest.mark.parametrize( + "fermionic_op, n_qubits, result", FERMI_WORDS_AND_OPS_LEGACY + FERMI_OPS_COMPLEX_LEGACY +) +def test_bravyi_kitaev_fermi_word_ps_legacy(fermionic_op, n_qubits, result): + """Test that the parity_transform function returns the correct qubit operator.""" + # convert FermiWord to PauliSentence and simplify + qubit_op = bravyi_kitaev(fermionic_op, n_qubits, ps=True) + qubit_op.simplify() + + # get expected op as PauliSentence and simplify + expected_op = pauli_sentence(qml.Hamiltonian(result[0], result[1])) + expected_op.simplify() + + assert qubit_op == expected_op + + +@pytest.mark.usefixtures("use_new_opmath") @pytest.mark.parametrize("fermionic_op, n_qubits, result", FERMI_WORDS_AND_OPS) def test_bravyi_kitaev_fermi_word_operation(fermionic_op, n_qubits, result): wires = fermionic_op.wires or [0] @@ -454,6 +877,19 @@ def test_bravyi_kitaev_fermi_word_operation(fermionic_op, n_qubits, result): assert qml.equal(qubit_op.simplify(), expected_op.simplify()) +@pytest.mark.usefixtures("use_legacy_opmath") +@pytest.mark.parametrize("fermionic_op, n_qubits, result", FERMI_WORDS_AND_OPS_LEGACY) +def test_bravyi_kitaev_fermi_word_operation_legacy(fermionic_op, n_qubits, result): + wires = fermionic_op.wires or [0] + + qubit_op = bravyi_kitaev(fermionic_op, n_qubits) + + expected_op = pauli_sentence(qml.Hamiltonian(result[0], result[1])) + expected_op = expected_op.operation(wires) + + assert qml.equal(qubit_op.simplify(), expected_op.simplify()) + + def test_bravyi_kitaev_for_identity(): """Test that the bravyi_kitaev function returns the correct qubit operator for Identity.""" assert qml.equal(bravyi_kitaev(FermiWord({}), 2), qml.Identity(0)) diff --git a/tests/fermi/test_fermi_mapping.py b/tests/fermi/test_fermi_mapping.py index ddf12ece5b7..540f4c67f57 100644 --- a/tests/fermi/test_fermi_mapping.py +++ b/tests/fermi/test_fermi_mapping.py @@ -350,6 +350,336 @@ ] +with qml.operation.disable_new_opmath_cm(): + FERMI_WORDS_AND_OPS_LEGACY = [ + ( + FermiWord({(0, 0): "+"}), + # trivial case of a creation operator, 0^ -> (X_0 - iY_0) / 2 + ([0.5, -0.5j], [qml.PauliX(0), qml.PauliY(0)]), + ), + ( + FermiWord({(0, 0): "-"}), + # trivial case of an annihilation operator, 0 -> (X_0 + iY_0) / 2 + ([(0.5 + 0j), (0.0 + 0.5j)], [qml.PauliX(0), qml.PauliY(0)]), + ), + ( + FermiWord({(0, 0): "+", (1, 0): "-"}), + # obtained with openfermion using: jordan_wigner(FermionOperator('0^ 0', 1)) + # reformatted the original openfermion output: (0.5+0j) [] + (-0.5+0j) [Z0] + ([(0.5 + 0j), (-0.5 + 0j)], [qml.Identity(0), qml.PauliZ(0)]), + ), + ( + FermiWord({(0, 0): "-", (1, 0): "+"}), + # obtained with openfermion using: jordan_wigner(FermionOperator('0 0^')) + # reformatted the original openfermion output: (0.5+0j) [] + (0.5+0j) [Z0] + ([(0.5 + 0j), (0.5 + 0j)], [qml.Identity(0), qml.PauliZ(0)]), + ), + ( + FermiWord({(0, 0): "-", (1, 1): "+"}), + # obtained with openfermion using: jordan_wigner(FermionOperator('0 1^')) + # reformatted the original openfermion output: + # (-0.25+0j) [X0 X1] + + # 0.25j [X0 Y1] + + # -0.25j [Y0 X1] + + # (-0.25+0j) [Y0 Y1] + ( + [(-0.25 + 0j), 0.25j, -0.25j, (-0.25 + 0j)], + [ + qml.PauliX(0) @ qml.PauliX(1), + qml.PauliX(0) @ qml.PauliY(1), + qml.PauliY(0) @ qml.PauliX(1), + qml.PauliY(0) @ qml.PauliY(1), + ], + ), + ), + ( + FermiWord({(0, 1): "-", (1, 0): "+"}), + # obtained with openfermion using: jordan_wigner(FermionOperator('1 0^')) + # reformatted the original openfermion output: + # (-0.25+0j) [X0 X1] + + # -0.25j [X0 Y1] + + # 0.25j [Y0 X1] + + # (-0.25+0j) [Y0 Y1] + ( + [(-0.25 + 0j), -0.25j, 0.25j, (-0.25 + 0j)], + [ + qml.PauliX(0) @ qml.PauliX(1), + qml.PauliX(0) @ qml.PauliY(1), + qml.PauliY(0) @ qml.PauliX(1), + qml.PauliY(0) @ qml.PauliY(1), + ], + ), + ), + ( + FermiWord({(0, 3): "+", (1, 0): "-"}), + # obtained with openfermion using: jordan_wigner(FermionOperator('3^ 0', 1)) + # reformatted the original openfermion output + ( + [(0.25 + 0j), -0.25j, 0.25j, (0.25 + 0j)], + [ + qml.PauliX(0) @ qml.PauliZ(1) @ qml.PauliZ(2) @ qml.PauliX(3), + qml.PauliX(0) @ qml.PauliZ(1) @ qml.PauliZ(2) @ qml.PauliY(3), + qml.PauliY(0) @ qml.PauliZ(1) @ qml.PauliZ(2) @ qml.PauliX(3), + qml.PauliY(0) @ qml.PauliZ(1) @ qml.PauliZ(2) @ qml.PauliY(3), + ], + ), + ), + ( + FermiWord({(0, 0): "-", (1, 3): "+"}), + # obtained with openfermion using: jordan_wigner(FermionOperator('0 3^')) + # reformatted the original openfermion output + ( + [(-0.25 + 0j), 0.25j, -0.25j, (-0.25 + 0j)], + [ + qml.PauliX(0) @ qml.PauliZ(1) @ qml.PauliZ(2) @ qml.PauliX(3), + qml.PauliX(0) @ qml.PauliZ(1) @ qml.PauliZ(2) @ qml.PauliY(3), + qml.PauliY(0) @ qml.PauliZ(1) @ qml.PauliZ(2) @ qml.PauliX(3), + qml.PauliY(0) @ qml.PauliZ(1) @ qml.PauliZ(2) @ qml.PauliY(3), + ], + ), + ), + ( + FermiWord({(0, 3): "-", (1, 0): "+"}), + # obtained with openfermion using: jordan_wigner(FermionOperator('3 0^')) + # reformatted the original openfermion output + ( + [(-0.25 + 0j), -0.25j, 0.25j, (-0.25 + 0j)], + [ + qml.PauliX(0) @ qml.PauliZ(1) @ qml.PauliZ(2) @ qml.PauliX(3), + qml.PauliX(0) @ qml.PauliZ(1) @ qml.PauliZ(2) @ qml.PauliY(3), + qml.PauliY(0) @ qml.PauliZ(1) @ qml.PauliZ(2) @ qml.PauliX(3), + qml.PauliY(0) @ qml.PauliZ(1) @ qml.PauliZ(2) @ qml.PauliY(3), + ], + ), + ), + ( + FermiWord({(0, 1): "+", (1, 4): "-"}), + # obtained with openfermion using: jordan_wigner(FermionOperator('1^ 4', 1)) + # reformatted the original openfermion output + ( + [(0.25 + 0j), 0.25j, -0.25j, (0.25 + 0j)], + [ + qml.PauliX(1) @ qml.PauliZ(2) @ qml.PauliZ(3) @ qml.PauliX(4), + qml.PauliX(1) @ qml.PauliZ(2) @ qml.PauliZ(3) @ qml.PauliY(4), + qml.PauliY(1) @ qml.PauliZ(2) @ qml.PauliZ(3) @ qml.PauliX(4), + qml.PauliY(1) @ qml.PauliZ(2) @ qml.PauliZ(3) @ qml.PauliY(4), + ], + ), + ), + ( + FermiWord({(0, 1): "+", (1, 1): "+", (2, 1): "-", (3, 1): "-"}), # [1, 1, 1, 1], + # obtained with openfermion using: jordan_wigner(FermionOperator('1^ 1^ 1 1', 1)) + ([0], [qml.Identity(1)]), + ), + ( + FermiWord({(0, 3): "+", (1, 1): "+", (2, 3): "-", (3, 1): "-"}), # [3, 1, 3, 1], + # obtained with openfermion using: jordan_wigner(FermionOperator('3^ 1^ 3 1', 1)) + # reformatted the original openfermion output + ( + [(-0.25 + 0j), (0.25 + 0j), (-0.25 + 0j), (0.25 + 0j)], + [qml.Identity(0), qml.PauliZ(1), qml.PauliZ(1) @ qml.PauliZ(3), qml.PauliZ(3)], + ), + ), + ( + FermiWord({(0, 3): "+", (1, 1): "-", (2, 3): "+", (3, 1): "-"}), # [3, 1, 3, 1], + # obtained with openfermion using: jordan_wigner(FermionOperator('3^ 1 3^ 1', 1)) + ([0], [qml.Identity(1)]), + ), + ( + FermiWord({(0, 1): "+", (1, 0): "-", (2, 1): "+", (3, 1): "-"}), # [1, 0, 1, 1], + # obtained with openfermion using: jordan_wigner(FermionOperator('1^ 0 1^ 1', 1)) + ([0], [qml.Identity(0)]), + ), + ( + FermiWord({(0, 1): "+", (1, 1): "-", (2, 0): "+", (3, 0): "-"}), # [1, 1, 0, 0], + # obtained with openfermion using: jordan_wigner(FermionOperator('1^ 1 0^ 0', 1)) + ( + [(0.25 + 0j), (-0.25 + 0j), (0.25 + 0j), (-0.25 + 0j)], + [qml.Identity(0), qml.PauliZ(0), qml.PauliZ(0) @ qml.PauliZ(1), qml.PauliZ(1)], + ), + ), + ( + FermiWord({(0, 5): "+", (1, 5): "-", (2, 5): "+", (3, 5): "-"}), # [5, 5, 5, 5], + # obtained with openfermion using: jordan_wigner(FermionOperator('5^ 5 5^ 5', 1)) + ( + [(0.5 + 0j), (-0.5 + 0j)], + [qml.Identity(0), qml.PauliZ(5)], + ), + ), + ( + FermiWord({(0, 3): "+", (1, 3): "-", (2, 3): "+", (3, 1): "-"}), + # obtained with openfermion using: jordan_wigner(FermionOperator('3^ 3 3^ 1', 1)) + ( + [(0.25 + 0j), (-0.25j), (0.25j), (0.25 + 0j)], + [ + qml.PauliX(1) @ qml.PauliZ(2) @ qml.PauliX(3), + qml.PauliX(1) @ qml.PauliZ(2) @ qml.PauliY(3), + qml.PauliY(1) @ qml.PauliZ(2) @ qml.PauliX(3), + qml.PauliY(1) @ qml.PauliZ(2) @ qml.PauliY(3), + ], + ), + ), + ] + + # can't be tested with conversion to operators yet, because the resulting operators + # are too complicated for qml.equal to successfully compare + FERMI_WORDS_AND_OPS_EXTENDED_LEGACY = [ + ( + FermiWord({(0, 3): "+", (1, 0): "-", (2, 2): "+", (3, 1): "-"}), + # obtained with openfermion using: jordan_wigner(FermionOperator('3^ 0 2^ 1', 1)) + ( + [ + (-0.0625 + 0j), + 0.0625j, + 0.0625j, + (0.0625 + 0j), + -0.0625j, + (-0.0625 + 0j), + (-0.0625 + 0j), + 0.0625j, + -0.0625j, + (-0.0625 + 0j), + (-0.0625 + 0j), + 0.0625j, + (0.0625 + 0j), + -0.0625j, + -0.0625j, + (-0.0625 + 0j), + ], + [ + qml.PauliX(0) @ qml.PauliX(1) @ qml.PauliX(2) @ qml.PauliX(3), + qml.PauliX(0) @ qml.PauliX(1) @ qml.PauliX(2) @ qml.PauliY(3), + qml.PauliX(0) @ qml.PauliX(1) @ qml.PauliY(2) @ qml.PauliX(3), + qml.PauliX(0) @ qml.PauliX(1) @ qml.PauliY(2) @ qml.PauliY(3), + qml.PauliX(0) @ qml.PauliY(1) @ qml.PauliX(2) @ qml.PauliX(3), + qml.PauliX(0) @ qml.PauliY(1) @ qml.PauliX(2) @ qml.PauliY(3), + qml.PauliX(0) @ qml.PauliY(1) @ qml.PauliY(2) @ qml.PauliX(3), + qml.PauliX(0) @ qml.PauliY(1) @ qml.PauliY(2) @ qml.PauliY(3), + qml.PauliY(0) @ qml.PauliX(1) @ qml.PauliX(2) @ qml.PauliX(3), + qml.PauliY(0) @ qml.PauliX(1) @ qml.PauliX(2) @ qml.PauliY(3), + qml.PauliY(0) @ qml.PauliX(1) @ qml.PauliY(2) @ qml.PauliX(3), + qml.PauliY(0) @ qml.PauliX(1) @ qml.PauliY(2) @ qml.PauliY(3), + qml.PauliY(0) @ qml.PauliY(1) @ qml.PauliX(2) @ qml.PauliX(3), + qml.PauliY(0) @ qml.PauliY(1) @ qml.PauliX(2) @ qml.PauliY(3), + qml.PauliY(0) @ qml.PauliY(1) @ qml.PauliY(2) @ qml.PauliX(3), + qml.PauliY(0) @ qml.PauliY(1) @ qml.PauliY(2) @ qml.PauliY(3), + ], + ), + ), + ( + FermiWord({(0, 3): "-", (1, 0): "+", (2, 2): "-", (3, 1): "+"}), + # obtained with openfermion using: jordan_wigner(FermionOperator('3 0^ 2 1^')) + ( + [ + (-0.0625 + 0j), + -0.0625j, + -0.0625j, + (0.0625 + 0j), + 0.0625j, + (-0.0625 + 0j), + (-0.0625 + 0j), + -0.0625j, + 0.0625j, + (-0.0625 + 0j), + (-0.0625 + 0j), + -0.0625j, + (0.0625 + 0j), + 0.0625j, + 0.0625j, + (-0.0625 + 0j), + ], + [ + qml.PauliX(0) @ qml.PauliX(1) @ qml.PauliX(2) @ qml.PauliX(3), + qml.PauliX(0) @ qml.PauliX(1) @ qml.PauliX(2) @ qml.PauliY(3), + qml.PauliX(0) @ qml.PauliX(1) @ qml.PauliY(2) @ qml.PauliX(3), + qml.PauliX(0) @ qml.PauliX(1) @ qml.PauliY(2) @ qml.PauliY(3), + qml.PauliX(0) @ qml.PauliY(1) @ qml.PauliX(2) @ qml.PauliX(3), + qml.PauliX(0) @ qml.PauliY(1) @ qml.PauliX(2) @ qml.PauliY(3), + qml.PauliX(0) @ qml.PauliY(1) @ qml.PauliY(2) @ qml.PauliX(3), + qml.PauliX(0) @ qml.PauliY(1) @ qml.PauliY(2) @ qml.PauliY(3), + qml.PauliY(0) @ qml.PauliX(1) @ qml.PauliX(2) @ qml.PauliX(3), + qml.PauliY(0) @ qml.PauliX(1) @ qml.PauliX(2) @ qml.PauliY(3), + qml.PauliY(0) @ qml.PauliX(1) @ qml.PauliY(2) @ qml.PauliX(3), + qml.PauliY(0) @ qml.PauliX(1) @ qml.PauliY(2) @ qml.PauliY(3), + qml.PauliY(0) @ qml.PauliY(1) @ qml.PauliX(2) @ qml.PauliX(3), + qml.PauliY(0) @ qml.PauliY(1) @ qml.PauliX(2) @ qml.PauliY(3), + qml.PauliY(0) @ qml.PauliY(1) @ qml.PauliY(2) @ qml.PauliX(3), + qml.PauliY(0) @ qml.PauliY(1) @ qml.PauliY(2) @ qml.PauliY(3), + ], + ), + ), + ( + FermiWord({(0, 3): "-", (1, 0): "+", (2, 2): "-", (3, 1): "+"}), + # obtained with openfermion using: jordan_wigner(FermionOperator('3 0^ 2 1^')) + ( + [ + (-0.0625 + 0j), + -0.0625j, + -0.0625j, + (0.0625 + 0j), + 0.0625j, + (-0.0625 + 0j), + (-0.0625 + 0j), + -0.0625j, + 0.0625j, + (-0.0625 + 0j), + (-0.0625 + 0j), + -0.0625j, + (0.0625 + 0j), + 0.0625j, + 0.0625j, + (-0.0625 + 0j), + ], + [ + qml.PauliX(0) @ qml.PauliX(1) @ qml.PauliX(2) @ qml.PauliX(3), + qml.PauliX(0) @ qml.PauliX(1) @ qml.PauliX(2) @ qml.PauliY(3), + qml.PauliX(0) @ qml.PauliX(1) @ qml.PauliY(2) @ qml.PauliX(3), + qml.PauliX(0) @ qml.PauliX(1) @ qml.PauliY(2) @ qml.PauliY(3), + qml.PauliX(0) @ qml.PauliY(1) @ qml.PauliX(2) @ qml.PauliX(3), + qml.PauliX(0) @ qml.PauliY(1) @ qml.PauliX(2) @ qml.PauliY(3), + qml.PauliX(0) @ qml.PauliY(1) @ qml.PauliY(2) @ qml.PauliX(3), + qml.PauliX(0) @ qml.PauliY(1) @ qml.PauliY(2) @ qml.PauliY(3), + qml.PauliY(0) @ qml.PauliX(1) @ qml.PauliX(2) @ qml.PauliX(3), + qml.PauliY(0) @ qml.PauliX(1) @ qml.PauliX(2) @ qml.PauliY(3), + qml.PauliY(0) @ qml.PauliX(1) @ qml.PauliY(2) @ qml.PauliX(3), + qml.PauliY(0) @ qml.PauliX(1) @ qml.PauliY(2) @ qml.PauliY(3), + qml.PauliY(0) @ qml.PauliY(1) @ qml.PauliX(2) @ qml.PauliX(3), + qml.PauliY(0) @ qml.PauliY(1) @ qml.PauliX(2) @ qml.PauliY(3), + qml.PauliY(0) @ qml.PauliY(1) @ qml.PauliY(2) @ qml.PauliX(3), + qml.PauliY(0) @ qml.PauliY(1) @ qml.PauliY(2) @ qml.PauliY(3), + ], + ), + ), + ( + FermiWord({(0, 0): "-", (1, 0): "+", (2, 2): "+", (3, 1): "-"}), + # obtained with openfermion using: jordan_wigner(FermionOperator('0 0^ 2^ 1')) + ( + [ + (0.125 + 0j), + -0.125j, + 0.125j, + (0.125 + 0j), + (0.125 + 0j), + -0.125j, + 0.125j, + (0.125 + 0j), + ], + [ + qml.PauliZ(0) @ qml.PauliX(1) @ qml.PauliX(2), + qml.PauliZ(0) @ qml.PauliX(1) @ qml.PauliY(2), + qml.PauliZ(0) @ qml.PauliY(1) @ qml.PauliX(2), + qml.PauliZ(0) @ qml.PauliY(1) @ qml.PauliY(2), + qml.PauliX(1) @ qml.PauliX(2), + qml.PauliX(1) @ qml.PauliY(2), + qml.PauliY(1) @ qml.PauliX(2), + qml.PauliY(1) @ qml.PauliY(2), + ], + ), + ), + ] + + +@pytest.mark.usefixtures("use_new_opmath") @pytest.mark.parametrize("fermionic_op, result", FERMI_WORDS_AND_OPS + FERMI_WORDS_AND_OPS_EXTENDED) def test_jordan_wigner_fermi_word_ps(fermionic_op, result): """Test that the jordan_wigner function returns the correct qubit operator.""" @@ -364,6 +694,24 @@ def test_jordan_wigner_fermi_word_ps(fermionic_op, result): assert qubit_op == expected_op +@pytest.mark.usefixtures("use_legacy_opmath") +@pytest.mark.parametrize( + "fermionic_op, result", FERMI_WORDS_AND_OPS_LEGACY + FERMI_WORDS_AND_OPS_EXTENDED_LEGACY +) +def test_jordan_wigner_fermi_word_ps_legacy(fermionic_op, result): + """Test that the jordan_wigner function returns the correct qubit operator.""" + # convert FermiWord to PauliSentence and simplify + qubit_op = jordan_wigner(fermionic_op, ps=True) + qubit_op.simplify() + + # get expected op as PauliSentence and simplify + expected_op = pauli_sentence(qml.Hamiltonian(result[0], result[1])) + expected_op.simplify() + + assert qubit_op == expected_op + + +@pytest.mark.usefixtures("use_new_opmath") # TODO: if qml.equal is extended to compare layers of nested ops, also test with FERMI_WORDS_AND_OPS_EXTENDED @pytest.mark.parametrize("fermionic_op, result", FERMI_WORDS_AND_OPS) def test_jordan_wigner_fermi_word_operation(fermionic_op, result): @@ -377,6 +725,20 @@ def test_jordan_wigner_fermi_word_operation(fermionic_op, result): assert qml.equal(qubit_op.simplify(), expected_op.simplify()) +@pytest.mark.usefixtures("use_legacy_opmath") +# TODO: if qml.equal is extended to compare layers of nested ops, also test with FERMI_WORDS_AND_OPS_EXTENDED +@pytest.mark.parametrize("fermionic_op, result", FERMI_WORDS_AND_OPS_LEGACY) +def test_jordan_wigner_fermi_word_operation_legacy(fermionic_op, result): + wires = fermionic_op.wires or [0] + + qubit_op = jordan_wigner(fermionic_op) + + expected_op = pauli_sentence(qml.Hamiltonian(result[0], result[1])) + expected_op = expected_op.operation(wires) + + assert qml.equal(qubit_op.simplify(), expected_op.simplify()) + + def test_jordan_wigner_for_identity(): """Test that the jordan_wigner function returns the correct qubit operator for Identity.""" assert qml.equal(jordan_wigner(FermiWord({})), qml.Identity(0)) diff --git a/tests/fermi/test_parity_mapping.py b/tests/fermi/test_parity_mapping.py index eafe7c1ed4b..007444dd6ce 100644 --- a/tests/fermi/test_parity_mapping.py +++ b/tests/fermi/test_parity_mapping.py @@ -437,7 +437,422 @@ def test_error_is_raised_for_dimension_mismatch(): ), ] +with qml.operation.disable_new_opmath_cm(): + FERMI_WORDS_AND_OPS_LEGACY = [ + ( + FermiWord({(0, 0): "+"}), + 1, + # trivial case of a creation operator with one qubit, 0^ -> (X_0 - iY_0) / 2 : Same as Jordan-Wigner + ([0.5, -0.5j], [qml.PauliX(0), qml.PauliY(0)]), + ), + ( + FermiWord({(0, 0): "-"}), + 1, + # trivial case of an annihilation operator with one qubit , 0 -> (X_0 + iY_0) / 2 : Same as Jordan-Wigner + ([(0.5 + 0j), (0.0 + 0.5j)], [qml.PauliX(0), qml.PauliY(0)]), + ), + ( + FermiWord({(0, 0): "+"}), + 2, + # trivial case of a creation operator with two qubits, 0^ -> (X_0 @ X_1 - iY_0 @ X_1) / 2 + ([0.5, -0.5j], [qml.PauliX(0) @ qml.PauliX(1), qml.PauliY(0) @ qml.PauliX(1)]), + ), + ( + FermiWord({(0, 0): "-"}), + 2, + # trivial case of an annihilation operator with two qubits , 0 -> (X_0 @ X_1 + iY_0 @ X_1) / 2 + ( + [(0.5 + 0j), (0.0 + 0.5j)], + [qml.PauliX(0) @ qml.PauliX(1), qml.PauliY(0) @ qml.PauliX(1)], + ), + ), + ( + FermiWord({(0, 0): "+", (1, 0): "-"}), + 4, + # obtained with openfermion using: binary_code_transform(FermionOperator('0^ 0'), parity_code(n_qubits)) for n_qubits = 4 + # reformatted the original openfermion output: (0.5+0j) [] + (-0.5+0j) [Z0] + ([(0.5 + 0j), (-0.5 + 0j)], [qml.Identity(0), qml.PauliZ(0)]), + ), + ( + FermiWord({(0, 0): "-", (1, 0): "+"}), + 4, + # obtained with openfermion using: binary_code_transform(FermionOperator('0 0^'), parity_code(n_qubits)) for n_qubits = 4 + # reformatted the original openfermion output: (0.5+0j) [] + (0.5+0j) [Z0] + ([(0.5 + 0j), (0.5 + 0j)], [qml.Identity(0), qml.PauliZ(0)]), + ), + ( + FermiWord({(0, 0): "-", (1, 1): "+"}), + 4, + # obtained with openfermion using: binary_code_transform(FermionOperator('0 1^'), parity_code(n_qubits)) for n_qubits = 4 + # reformatted the original openfermion output: + # (-0.25+0j) [X0] + + # 0.25 [X0 Z1] + + # (-0-0.25j) [Y0] + + # 0.25j [Y0 Z1] + ( + [(-0.25 + 0j), 0.25, (-0 - 0.25j), (0.25j)], + [ + qml.PauliX(0), + qml.PauliX(0) @ qml.PauliZ(1), + qml.PauliY(0), + qml.PauliY(0) @ qml.PauliZ(1), + ], + ), + ), + ( + FermiWord({(0, 3): "+", (1, 0): "-"}), + 4, + # obtained with openfermion using: binary_code_transform(FermionOperator('3^ 0'), parity_code(n_qubits)) for n_qubits = 4 + # reformatted the original openfermion output + # -0.25 [X0 X1 X2 Z3] + + # 0.25j [X0 X1 Y2] + + # (-0-0.25j) [Y0 X1 X2 Z3] + + # -0.25 [Y0 X1 Y2] + ( + [(-0.25 + 0j), 0.25j, (-0 - 0.25j), -0.25], + [ + qml.PauliX(0) @ qml.PauliX(1) @ qml.PauliX(2) @ qml.PauliZ(3), + qml.PauliX(0) @ qml.PauliX(1) @ qml.PauliY(2), + qml.PauliY(0) @ qml.PauliX(1) @ qml.PauliX(2) @ qml.PauliZ(3), + qml.PauliY(0) @ qml.PauliX(1) @ qml.PauliY(2), + ], + ), + ), + ( + FermiWord({(0, 5): "+", (1, 5): "-", (2, 5): "+", (3, 5): "-"}), + 6, + # obtained with openfermion using: binary_code_transform(FermionOperator('5^ 5 5^ 5'), parity_code(n_qubits)) with 6 qubits + ( + [(0.5 + 0j), (-0.5 + 0j)], + [qml.Identity(0), qml.PauliZ(4) @ qml.PauliZ(5)], + ), + ), + ( + FermiWord({(0, 3): "+", (1, 3): "-", (2, 3): "+", (3, 1): "-"}), + 6, + # obtained with openfermion using: binary_code_transform(FermionOperator('3^ 3 3^ 1'), parity_code(n_qubits)) with 6 qubits + # -0.25 [Z0 X1 X2 Z3] + + # 0.25j [Z0 X1 Y2] + + # (-0-0.25j) [Y1 X2 Z3] + + # -0.25 [Y1 Y2] + ( + [-0.25, 0.25j, -0.25j, -0.25], + [ + qml.PauliZ(0) @ qml.PauliX(1) @ qml.PauliX(2) @ qml.PauliZ(3), + qml.PauliZ(0) @ qml.PauliX(1) @ qml.PauliY(2), + qml.PauliY(1) @ qml.PauliX(2) @ qml.PauliZ(3), + qml.PauliY(1) @ qml.PauliY(2), + ], + ), + ), + ( + FermiWord({(0, 1): "+", (1, 0): "-", (2, 1): "+", (3, 1): "-"}), + 6, + # obtained with openfermion using: binary_code_transform(FermionOperator('1^ 0 1^ 1'), parity_code(n_qubits)) with 6 qubits + ([0], [qml.Identity(0)]), + ), + ] + + FERMI_OPS_COMPLEX_LEGACY = [ + ( + FermiWord({(0, 2): "-", (1, 0): "+", (2, 3): "+"}), + 4, + # obtained with openfermion using: binary_code_transform(FermionOperator('2 0^ 3^'), parity_code(n_qubits)) for n_qubits = 4 + # reformatted the original openfermion output + # (-0-0.125j) [X0 X1 Z2 Y3] + + # 0.125 [X0 X1 X3] + + # 0.125j [X0 Y1 Z2 X3] + + # 0.125 [X0 Y1 Y3] + + # -0.125 [Y0 X1 Z2 Y3] + + # (-0-0.125j) [Y0 X1 X3] + + # 0.125 [Y0 Y1 Z2 X3] + + # (-0-0.125j) [Y0 Y1 Y3] + ( + [(-0 - 0.125j), 0.125, 0.125j, 0.125, -0.125, -0.125j, 0.125, -0.125j], + [ + qml.PauliX(0) @ qml.PauliX(1) @ qml.PauliZ(2) @ qml.PauliY(3), + qml.PauliX(0) @ qml.PauliX(1) @ qml.PauliX(3), + qml.PauliX(0) @ qml.PauliY(1) @ qml.PauliZ(2) @ qml.PauliX(3), + qml.PauliX(0) @ qml.PauliY(1) @ qml.PauliY(3), + qml.PauliY(0) @ qml.PauliX(1) @ qml.PauliZ(2) @ qml.PauliY(3), + qml.PauliY(0) @ qml.PauliX(1) @ qml.PauliX(3), + qml.PauliY(0) @ qml.PauliY(1) @ qml.PauliZ(2) @ qml.PauliX(3), + qml.PauliY(0) @ qml.PauliY(1) @ qml.PauliY(3), + ], + ), + ), + ( + FermiWord({(0, 0): "-", (1, 3): "+"}), + 4, + # obtained with openfermion using: binary_code_transform(FermionOperator('0 3^'), parity_code(n_qubits)) for n_qubits = 4 + # reformatted the original openfermion output + # 0.25 [X0 X1 X2 Z3] + + # (-0-0.25j) [X0 X1 Y2] + + # 0.25j [Y0 X1 X2 Z3] + + # 0.25 [Y0 X1 Y2] + ( + [0.25, -0.25j, 0.25j, 0.25], + [ + qml.PauliX(0) @ qml.PauliX(1) @ qml.PauliX(2) @ qml.PauliZ(3), + qml.PauliX(0) @ qml.PauliX(1) @ qml.PauliY(2), + qml.PauliY(0) @ qml.PauliX(1) @ qml.PauliX(2) @ qml.PauliZ(3), + qml.PauliY(0) @ qml.PauliX(1) @ qml.PauliY(2), + ], + ), + ), + ( + FermiWord({(0, 3): "+", (1, 1): "+", (2, 3): "-", (3, 1): "-"}), + 6, + # obtained with openfermion using: binary_code_transform(FermionOperator('3^ 1^ 3 1'), parity_code(n_qubits)) with 6 qubits + # -0.25 [] + + # 0.25 [Z0 Z1] + + # -0.25 [Z0 Z1 Z2 Z3] + + # 0.25 [Z2 Z3] + # reformatted the original openfermion output + ( + [(-0.25 + 0j), (0.25 + 0j), (-0.25 + 0j), (0.25 + 0j)], + [ + qml.Identity(0), + qml.PauliZ(0) @ qml.PauliZ(1), + qml.PauliZ(0) @ qml.PauliZ(1) @ qml.PauliZ(2) @ qml.PauliZ(3), + qml.PauliZ(2) @ qml.PauliZ(3), + ], + ), + ), + ( + FermiWord({(0, 1): "+", (1, 4): "-", (2, 3): "-", (3, 4): "+"}), + 6, + # obtained with openfermion using: binary_code_transform(FermionOperator('1^ 4 3 4^'), parity_code(n_qubits)) with 6 qubits + # reformatted the original openfermion output + # 0.125 [Z0 X1 X2 Z3] + + # 0.125 [Z0 X1 X2 Z4] + + # 0.125j [Z0 X1 Y2] + + # 0.125j [Z0 X1 Y2 Z3 Z4] + + # (-0-0.125j) [Y1 X2 Z3] + + # (-0-0.125j) [Y1 X2 Z4] + + # 0.125 [Y1 Y2] + + # 0.125 [Y1 Y2 Z3 Z4] + ( + [0.125, 0.125, 0.125j, 0.125j, -0.125j, -0.125j, 0.125, 0.125], + [ + qml.PauliZ(0) @ qml.PauliX(1) @ qml.PauliX(2) @ qml.PauliZ(3), + qml.PauliZ(0) @ qml.PauliX(1) @ qml.PauliX(2) @ qml.PauliZ(4), + qml.PauliZ(0) @ qml.PauliX(1) @ qml.PauliY(2), + qml.PauliZ(0) @ qml.PauliX(1) @ qml.PauliY(2) @ qml.PauliZ(3) @ qml.PauliZ(4), + qml.PauliY(1) @ qml.PauliX(2) @ qml.PauliZ(3), + qml.PauliY(1) @ qml.PauliX(2) @ qml.PauliZ(4), + qml.PauliY(1) @ qml.PauliY(2), + qml.PauliY(1) @ qml.PauliY(2) @ qml.PauliZ(3) @ qml.PauliZ(4), + ], + ), + ), + ( + FermiWord({(0, 3): "+", (1, 1): "-", (2, 3): "+", (3, 1): "-"}), + 6, + # obtained with openfermion using: binary_code_transform(FermionOperator('3^ 1 3^ 1'), parity_code(n_qubits)) with 6 qubits + ([0], [qml.Identity(3)]), + ), + ( + FermiWord({(0, 1): "+", (1, 0): "+", (2, 4): "-", (3, 5): "-"}), + 6, + # obtained with openfermion using: binary_code_transform(FermionOperator('1^ 0^ 4 5^'), parity_code(n_qubits)) with 6 qubits + # 0.0625 [X0 Z1 Z3 X4 Z5] + + # 0.0625j [X0 Z1 Z3 Y4] + + # 0.0625 [X0 Z1 X4] + + # 0.0625j [X0 Z1 Y4 Z5] + + # 0.0625 [X0 Z3 X4 Z5] + + # 0.0625j [X0 Z3 Y4] + + # 0.0625 [X0 X4] + + # 0.0625j [X0 Y4 Z5] + + # (-0-0.0625j) [Y0 Z1 Z3 X4 Z5] + + # 0.0625 [Y0 Z1 Z3 Y4] + + # (-0-0.0625j) [Y0 Z1 X4] + + # 0.0625 [Y0 Z1 Y4 Z5] + + # (-0-0.0625j) [Y0 Z3 X4 Z5] + + # 0.0625 [Y0 Z3 Y4] + + # (-0-0.0625j) [Y0 X4] + + # 0.0625 [Y0 Y4 Z5]) + ( + [ + 0.0625, + 0.0625j, + 0.0625, + 0.0625j, + 0.0625, + 0.0625j, + 0.0625, + 0.0625j, + -0.0625j, + 0.0625, + -0.0625j, + 0.0625, + -0.0625j, + 0.0625, + -0.0625j, + 0.0625, + ], + [ + qml.PauliX(0) @ qml.PauliZ(1) @ qml.PauliZ(3) @ qml.PauliX(4) @ qml.PauliZ(5), + qml.PauliX(0) @ qml.PauliZ(1) @ qml.PauliZ(3) @ qml.PauliY(4), + qml.PauliX(0) @ qml.PauliZ(1) @ qml.PauliX(4), + qml.PauliX(0) @ qml.PauliZ(1) @ qml.PauliY(4) @ qml.PauliZ(5), + qml.PauliX(0) @ qml.PauliZ(3) @ qml.PauliX(4) @ qml.PauliZ(5), + qml.PauliX(0) @ qml.PauliZ(3) @ qml.PauliY(4), + qml.PauliX(0) @ qml.PauliX(4), + qml.PauliX(0) @ qml.PauliY(4) @ qml.PauliZ(5), + qml.PauliY(0) @ qml.PauliZ(1) @ qml.PauliZ(3) @ qml.PauliX(4) @ qml.PauliZ(5), + qml.PauliY(0) @ qml.PauliZ(1) @ qml.PauliZ(3) @ qml.PauliY(4), + qml.PauliY(0) @ qml.PauliZ(1) @ qml.PauliX(4), + qml.PauliY(0) @ qml.PauliZ(1) @ qml.PauliY(4) @ qml.PauliZ(5), + qml.PauliY(0) @ qml.PauliZ(3) @ qml.PauliX(4) @ qml.PauliZ(5), + qml.PauliY(0) @ qml.PauliZ(3) @ qml.PauliY(4), + qml.PauliY(0) @ qml.PauliX(4), + qml.PauliY(0) @ qml.PauliY(4) @ qml.PauliZ(5), + ], + ), + ), + ( + FermiWord({(0, 1): "-", (1, 0): "+"}), + 4, + # obtained with openfermion using: binary_code_transform(FermionOperator('1 0^'), parity_code(n_qubits)) for n_qubits = 4 + # reformatted the original openfermion output: + # -0.25 [X0] + + # 0.25 [X0 Z1] + + # 0.25j [Y0] + + # (-0-0.25j) [Y0 Z1] + ( + [(-0.25 + 0j), 0.25, 0.25j, (-0 - 0.25j)], + [ + qml.PauliX(0), + qml.PauliX(0) @ qml.PauliZ(1), + qml.PauliY(0), + qml.PauliY(0) @ qml.PauliZ(1), + ], + ), + ), + ( + FermiWord( + {(0, 1): "+", (1, 1): "-", (2, 3): "+", (3, 4): "-", (4, 2): "+", (5, 5): "-"} + ), + 6, + # obtained with openfermion using: binary_code_transform(FermionOperator('1^ 1 3^ 4 2^ 5'), parity_code(n_qubits)) with 6 qubits + # 0.03125 [Z0 Z1 X2 Z3 X4 Z5] + + # 0.03125j [Z0 Z1 X2 Z3 Y4] + + # 0.03125 [Z0 Z1 X2 X4] + + # 0.03125j [Z0 Z1 X2 Y4 Z5] + + # (-0-0.03125j) [Z0 Z1 Y2 Z3 X4] + + # 0.03125 [Z0 Z1 Y2 Z3 Y4 Z5] + + # (-0-0.03125j) [Z0 Z1 Y2 X4 Z5] + + # 0.03125 [Z0 Z1 Y2 Y4] + + # 0.03125 [Z0 X2 Z3 X4] + + # 0.03125j [Z0 X2 Z3 Y4 Z5] + + # 0.03125 [Z0 X2 X4 Z5] + + # 0.03125j [Z0 X2 Y4] + + # (-0-0.03125j) [Z0 Y2 Z3 X4 Z5] + + # 0.03125 [Z0 Y2 Z3 Y4] + + # (-0-0.03125j) [Z0 Y2 X4] + + # 0.03125 [Z0 Y2 Y4 Z5] + + # -0.03125 [Z1 X2 Z3 X4] + + # (-0-0.03125j) [Z1 X2 Z3 Y4 Z5] + + # -0.03125 [Z1 X2 X4 Z5] + + # (-0-0.03125j) [Z1 X2 Y4] + + # 0.03125j [Z1 Y2 Z3 X4 Z5] + + # -0.03125 [Z1 Y2 Z3 Y4] + + # 0.03125j [Z1 Y2 X4] + + # -0.03125 [Z1 Y2 Y4 Z5] + + # -0.03125 [X2 Z3 X4 Z5] + + # (-0-0.03125j) [X2 Z3 Y4] + + # -0.03125 [X2 X4] + + # (-0-0.03125j) [X2 Y4 Z5] + + # 0.03125j [Y2 Z3 X4] + + # -0.03125 [Y2 Z3 Y4 Z5] + + # 0.03125j [Y2 X4 Z5] + + # -0.03125 [Y2 Y4] + ( + [ + 0.03125, + 0.03125j, + 0.03125, + 0.03125j, + -0.03125j, + 0.03125, + -0.03125j, + 0.03125, + 0.03125, + 0.03125j, + 0.03125, + 0.03125j, + -0.03125j, + 0.03125, + -0.03125j, + 0.03125, + -0.03125, + -0.03125j, + -0.03125, + -0.03125j, + 0.03125j, + -0.03125, + 0.03125j, + -0.03125, + -0.03125, + -0.03125j, + -0.03125, + -0.03125j, + 0.03125j, + -0.03125, + 0.03125j, + -0.03125, + ], + [ + qml.PauliZ(0) + @ qml.PauliZ(1) + @ qml.PauliX(2) + @ qml.PauliZ(3) + @ qml.PauliX(4) + @ qml.PauliZ(5), + qml.PauliZ(0) @ qml.PauliZ(1) @ qml.PauliX(2) @ qml.PauliZ(3) @ qml.PauliY(4), + qml.PauliZ(0) @ qml.PauliZ(1) @ qml.PauliX(2) @ qml.PauliX(4), + qml.PauliZ(0) @ qml.PauliZ(1) @ qml.PauliX(2) @ qml.PauliY(4) @ qml.PauliZ(5), + qml.PauliZ(0) @ qml.PauliZ(1) @ qml.PauliY(2) @ qml.PauliZ(3) @ qml.PauliX(4), + qml.PauliZ(0) + @ qml.PauliZ(1) + @ qml.PauliY(2) + @ qml.PauliZ(3) + @ qml.PauliY(4) + @ qml.PauliZ(5), + qml.PauliZ(0) @ qml.PauliZ(1) @ qml.PauliY(2) @ qml.PauliX(4) @ qml.PauliZ(5), + qml.PauliZ(0) @ qml.PauliZ(1) @ qml.PauliY(2) @ qml.PauliY(4), + qml.PauliZ(0) @ qml.PauliX(2) @ qml.PauliZ(3) @ qml.PauliX(4), + qml.PauliZ(0) @ qml.PauliX(2) @ qml.PauliZ(3) @ qml.PauliY(4) @ qml.PauliZ(5), + qml.PauliZ(0) @ qml.PauliX(2) @ qml.PauliX(4) @ qml.PauliZ(5), + qml.PauliZ(0) @ qml.PauliX(2) @ qml.PauliY(4), + qml.PauliZ(0) @ qml.PauliY(2) @ qml.PauliZ(3) @ qml.PauliX(4) @ qml.PauliZ(5), + qml.PauliZ(0) @ qml.PauliY(2) @ qml.PauliZ(3) @ qml.PauliY(4), + qml.PauliZ(0) @ qml.PauliY(2) @ qml.PauliX(4), + qml.PauliZ(0) @ qml.PauliY(2) @ qml.PauliY(4) @ qml.PauliZ(5), + qml.PauliZ(1) @ qml.PauliX(2) @ qml.PauliZ(3) @ qml.PauliX(4), + qml.PauliZ(1) @ qml.PauliX(2) @ qml.PauliZ(3) @ qml.PauliY(4) @ qml.PauliZ(5), + qml.PauliZ(1) @ qml.PauliX(2) @ qml.PauliX(4) @ qml.PauliZ(5), + qml.PauliZ(1) @ qml.PauliX(2) @ qml.PauliY(4), + qml.PauliZ(1) @ qml.PauliY(2) @ qml.PauliZ(3) @ qml.PauliX(4) @ qml.PauliZ(5), + qml.PauliZ(1) @ qml.PauliY(2) @ qml.PauliZ(3) @ qml.PauliY(4), + qml.PauliZ(1) @ qml.PauliY(2) @ qml.PauliX(4), + qml.PauliZ(1) @ qml.PauliY(2) @ qml.PauliY(4) @ qml.PauliZ(5), + qml.PauliX(2) @ qml.PauliZ(3) @ qml.PauliX(4) @ qml.PauliZ(5), + qml.PauliX(2) @ qml.PauliZ(3) @ qml.PauliY(4), + qml.PauliX(2) @ qml.PauliX(4), + qml.PauliX(2) @ qml.PauliY(4) @ qml.PauliZ(5), + qml.PauliY(2) @ qml.PauliZ(3) @ qml.PauliX(4), + qml.PauliY(2) @ qml.PauliZ(3) @ qml.PauliY(4) @ qml.PauliZ(5), + qml.PauliY(2) @ qml.PauliX(4) @ qml.PauliZ(5), + qml.PauliY(2) @ qml.PauliY(4), + ], + ), + ), + ] + +@pytest.mark.usefixtures("use_new_opmath") @pytest.mark.parametrize("fermionic_op, n_qubits, result", FERMI_WORDS_AND_OPS + FERMI_OPS_COMPLEX) def test_parity_transform_fermi_word_ps(fermionic_op, n_qubits, result): """Test that the parity_transform function returns the correct qubit operator.""" @@ -452,6 +867,24 @@ def test_parity_transform_fermi_word_ps(fermionic_op, n_qubits, result): assert qubit_op == expected_op +@pytest.mark.usefixtures("use_legacy_opmath") +@pytest.mark.parametrize( + "fermionic_op, n_qubits, result", FERMI_WORDS_AND_OPS_LEGACY + FERMI_OPS_COMPLEX_LEGACY +) +def test_parity_transform_fermi_word_ps_legacy(fermionic_op, n_qubits, result): + """Test that the parity_transform function returns the correct qubit operator.""" + # convert FermiWord to PauliSentence and simplify + qubit_op = parity_transform(fermionic_op, n_qubits, ps=True) + qubit_op.simplify() + + # get expected op as PauliSentence and simplify + expected_op = pauli_sentence(qml.Hamiltonian(result[0], result[1])) + expected_op.simplify() + + assert qubit_op == expected_op + + +@pytest.mark.usefixtures("use_new_opmath") @pytest.mark.parametrize("fermionic_op, n_qubits, result", FERMI_WORDS_AND_OPS) def test_parity_transform_fermi_word_operation(fermionic_op, n_qubits, result): wires = fermionic_op.wires or [0] @@ -464,6 +897,19 @@ def test_parity_transform_fermi_word_operation(fermionic_op, n_qubits, result): assert qml.equal(qubit_op.simplify(), expected_op.simplify()) +@pytest.mark.usefixtures("use_legacy_opmath") +@pytest.mark.parametrize("fermionic_op, n_qubits, result", FERMI_WORDS_AND_OPS_LEGACY) +def test_parity_transform_fermi_word_operation_legacy(fermionic_op, n_qubits, result): + wires = fermionic_op.wires or [0] + + qubit_op = parity_transform(fermionic_op, n_qubits) + + expected_op = pauli_sentence(qml.Hamiltonian(result[0], result[1])) + expected_op = expected_op.operation(wires) + + assert qml.equal(qubit_op.simplify(), expected_op.simplify()) + + def test_parity_transform_for_identity(): """Test that the parity_transform function returns the correct qubit operator for Identity.""" assert qml.equal(parity_transform(FermiWord({}), 2), qml.Identity(0)) From 6977fffa6b055e3b3263b275703718aa88a4463a Mon Sep 17 00:00:00 2001 From: lillian542 Date: Mon, 15 Apr 2024 23:58:55 -0400 Subject: [PATCH 55/59] update vqe tests --- tests/test_vqe.py | 67 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/tests/test_vqe.py b/tests/test_vqe.py index aa78b7ff6f2..84248d35f3d 100644 --- a/tests/test_vqe.py +++ b/tests/test_vqe.py @@ -64,6 +64,18 @@ def res(params): (qml.PauliX(0) @ qml.PauliZ(1), qml.PauliY(0) @ qml.PauliZ(1), qml.PauliZ(1)), ] +with qml.operation.disable_new_opmath_cm(): + OBSERVABLES_LEGACY = [ + (qml.PauliZ(0), qml.PauliY(0), qml.PauliZ(1)), + (qml.PauliX(0) @ qml.PauliZ(1), qml.PauliY(0) @ qml.PauliZ(1), qml.PauliZ(1)), + (qml.Hermitian(H_TWO_QUBITS, [0, 1]),), + ] + + OBSERVABLES_NO_HERMITIAN_LEGACY = [ + (qml.PauliZ(0), qml.PauliY(0), qml.PauliZ(1)), + (qml.PauliX(0) @ qml.PauliZ(1), qml.PauliY(0) @ qml.PauliZ(1), qml.PauliZ(1)), + ] + hamiltonians_with_expvals = [ ((-0.6,), (qml.PauliZ(0),), [-0.6 * 1.0]), ((1.0,), (qml.PauliX(0),), [0.0]), @@ -269,6 +281,7 @@ def get_device(wires=1): class TestVQE: """Test the core functionality of the VQE module""" + @pytest.mark.usefixtures("use_new_opmath") @pytest.mark.parametrize("ansatz, params", CIRCUITS) @pytest.mark.parametrize("coeffs, observables", list(zip(COEFFS, OBSERVABLES))) def test_cost_evaluate(self, params, ansatz, coeffs, observables): @@ -279,6 +292,18 @@ def test_cost_evaluate(self, params, ansatz, coeffs, observables): assert expval(params).dtype == np.float64 assert np.shape(expval(params)) == () # expval should be scalar + @pytest.mark.usefixtures("use_legacy_opmath") + @pytest.mark.parametrize("ansatz, params", CIRCUITS) + @pytest.mark.parametrize("coeffs, observables", list(zip(COEFFS, OBSERVABLES_LEGACY))) + def test_cost_evaluate_legacy(self, params, ansatz, coeffs, observables): + """Tests that the cost function evaluates properly""" + hamiltonian = qml.Hamiltonian(coeffs, observables) + dev = qml.device("default.qubit", wires=3) + expval = generate_cost_fn(ansatz, hamiltonian, dev) + assert expval(params).dtype == np.float64 + assert np.shape(expval(params)) == () # expval should be scalar + + @pytest.mark.usefixtures("use_new_opmath") @pytest.mark.parametrize( "coeffs, observables, expected", hamiltonians_with_expvals + zero_hamiltonians_with_expvals ) @@ -289,6 +314,15 @@ def test_cost_expvals(self, coeffs, observables, expected): cost = generate_cost_fn(lambda params, **kwargs: None, hamiltonian, dev) assert cost([]) == sum(expected) + @pytest.mark.usefixtures("use_legacy_opmath") + @pytest.mark.parametrize("coeffs, observables, expected", hamiltonians_with_expvals) + def test_cost_expvals_legacy(self, coeffs, observables, expected): + """Tests that the cost function returns correct expectation values""" + dev = qml.device("default.qubit", wires=2) + hamiltonian = qml.Hamiltonian(coeffs, observables) + cost = generate_cost_fn(lambda params, **kwargs: None, hamiltonian, dev) + assert cost([]) == sum(expected) + # pylint: disable=protected-access @pytest.mark.torch @pytest.mark.slow @@ -738,6 +772,7 @@ class TestNewVQE: """Test the new VQE syntax of passing the Hamiltonian as an observable.""" # pylint: disable=cell-var-from-loop + @pytest.mark.usefixtures("use_new_opmath") @pytest.mark.parametrize("ansatz, params", CIRCUITS) @pytest.mark.parametrize("observables", OBSERVABLES_NO_HERMITIAN) def test_circuits_evaluate(self, ansatz, observables, params, tol): @@ -768,6 +803,38 @@ def separate_circuit(): assert np.isclose(res, res_expected, atol=tol) + # pylint: disable=cell-var-from-loop + @pytest.mark.usefixtures("use_legacy_opmath") + @pytest.mark.parametrize("ansatz, params", CIRCUITS) + @pytest.mark.parametrize("observables", OBSERVABLES_NO_HERMITIAN_LEGACY) + def test_circuits_evaluate_legacy(self, ansatz, observables, params, tol): + """Tests simple VQE evaluations.""" + coeffs = [1.0] * len(observables) + dev = qml.device("default.qubit", wires=3) + H = qml.Hamiltonian(coeffs, observables) + + # pass H directly + @qml.qnode(dev) + def circuit(): + ansatz(params, wires=range(3)) + return qml.expval(H) + + res = circuit() + + res_expected = [] + for obs in observables: + + @qml.qnode(dev) + def separate_circuit(): + ansatz(params, wires=range(3)) + return qml.expval(obs) + + res_expected.append(separate_circuit()) + + res_expected = np.sum([c * r for c, r in zip(coeffs, res_expected)]) + + assert np.isclose(res, res_expected, atol=tol) + def test_acting_on_subcircuit(self, tol): """Tests a VQE circuit where the observable does not act on all wires.""" dev = qml.device("default.qubit", wires=3) From e6c59f6bdc9110153e267572c2dfa9617900ad7c Mon Sep 17 00:00:00 2001 From: lillian542 Date: Tue, 16 Apr 2024 00:38:02 -0400 Subject: [PATCH 56/59] update default_qubit test --- tests/devices/default_qubit/test_default_qubit.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/devices/default_qubit/test_default_qubit.py b/tests/devices/default_qubit/test_default_qubit.py index a4990949bc7..6ffb8a88c9e 100644 --- a/tests/devices/default_qubit/test_default_qubit.py +++ b/tests/devices/default_qubit/test_default_qubit.py @@ -2058,6 +2058,9 @@ def test_differentiate_jitted_qnode(self, measurement_func): """Test that a jitted qnode can be correctly differentiated""" import jax + if measurement_func is qml.var and not qml.operation.active_new_opmath(): + pytest.skip(reason="Variance for this test circuit not supported with legacy opmath") + dev = DefaultQubit() def qfunc(x, y): From 1f4e1d7d99efe18eb37a6f525b56ec4bb74fd0e7 Mon Sep 17 00:00:00 2001 From: lillian542 Date: Tue, 16 Apr 2024 10:16:01 -0400 Subject: [PATCH 57/59] update device tests --- tests/test_device.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/test_device.py b/tests/test_device.py index aee0e32ddda..18eef9b5b36 100644 --- a/tests/test_device.py +++ b/tests/test_device.py @@ -306,6 +306,7 @@ def test_check_validity_on_valid_queue(self, mock_device_supporting_paulis): # Raises an error if queue or observables are invalid dev.check_validity(queue, observables) + @pytest.mark.usefixtures("use_new_opmath") def test_check_validity_containing_prod(self, mock_device_supporting_prod): """Tests that the function Device.check_validity works with Prod""" @@ -323,6 +324,7 @@ def test_check_validity_containing_prod(self, mock_device_supporting_prod): dev.check_validity(queue, observables) + @pytest.mark.usefixtures("use_new_opmath") def test_prod_containing_unsupported_nested_observables(self, mock_device_supporting_prod): """Tests that the observables nested within Prod are checked for validity""" From 13defd52a6db6c35bb3499d38cffb7fded226d23 Mon Sep 17 00:00:00 2001 From: lillian542 Date: Tue, 16 Apr 2024 12:03:33 -0400 Subject: [PATCH 58/59] trigger ci From f18265c0c6414bea2ef53679e07acbcebd734c02 Mon Sep 17 00:00:00 2001 From: lillian542 <38584660+lillian542@users.noreply.github.com> Date: Wed, 17 Apr 2024 10:53:52 -0400 Subject: [PATCH 59/59] Update workflow to test on master and not run on every PR --- .github/workflows/legacy_op_math.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/legacy_op_math.yml b/.github/workflows/legacy_op_math.yml index d428eb4485c..13dd9ee6e82 100644 --- a/.github/workflows/legacy_op_math.yml +++ b/.github/workflows/legacy_op_math.yml @@ -3,7 +3,6 @@ name: Legacy opmath tests on: schedule: - cron: "0 0 2 * *" - pull_request: # this should be removed so it only runs on the schedule before merging workflow_dispatch: jobs: @@ -12,6 +11,6 @@ jobs: secrets: codecov_token: ${{ secrets.CODECOV_TOKEN }} with: - branch: ${{ github.ref }} # this should be set back to master before merging + branch: 'master' run_lightened_ci: false disable_new_opmath: "True"