Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Statevector vjp and support Hamiltonian in adjoint_jacobian #294

Merged
merged 147 commits into from
Jun 16, 2022

Conversation

chaeyeunpark
Copy link
Contributor

@chaeyeunpark chaeyeunpark commented May 12, 2022

Before submitting

Please complete the following checklist when submitting a PR:

  • All new features must include a unit test.
    If you've fixed a bug or added code that should be tested, add a test to the
    tests directory!

  • All new functions and code must be clearly commented and documented.
    If you do make documentation changes, make sure that the docs build and
    render correctly by running make docs.

  • Ensure that the test suite passes, by running make test.

  • Add a new entry to the .github/CHANGELOG.md file, summarizing the
    change, and including a link back to the PR.

  • Ensure that code is properly formatted by running make format.

When all the above are checked, delete everything above the dashed
line and fill in the pull request template.


Context:

Description of the Change: We now have pennylane_lightning.lightning_ops.adj_diff module that handles all observables related to adjoint differentiation method. We also have adjoint-like computation of the statevecor vjp.

Benefits:

Possible Drawbacks:

Related GitHub Issues: Closes #216

@chaeyeunpark chaeyeunpark changed the title [WIP] Statevector vjp and support Hamiltonian in adjoint_jacobian Statevector vjp and support Hamiltonian in adjoint_jacobian Jun 14, 2022
Copy link
Member

@mlxd mlxd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks amazing, great job @chaeyeunpark ! I have nothing else major to add, but a few comments.

The only thing I'd like to see before we get this merged in are some runtime plots comparing the before and after (v0.23.0, v0.24.0-dev, and this).

pennylane_lightning/lightning_qubit.py Show resolved Hide resolved
pennylane_lightning/src/algorithms/StateVecAdjDiff.hpp Outdated Show resolved Hide resolved
Comment on lines +70 to +71
* C++17's std::pmr::polymorphic_allocator substitutes this whole class.
* However, clang (even the latest version 13) does not support pmr yet.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well that is depressing...

Copy link
Contributor Author

@chaeyeunpark chaeyeunpark Jun 14, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Moreover, as we use clang-cl (for Kokkos), we cannot use pmr even for Windows though MSVC supports it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do they have it even in experimental support? We could wrap std::experimental::pmr if so.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's true. Let me add this to my task list.

chaeyeunpark and others added 3 commits June 14, 2022 18:35
@chaeyeunpark
Copy link
Contributor Author

chaeyeunpark commented Jun 16, 2022

I benchmark the performance of adjoint diff with expval(ham). This is the code I used:

import pennylane as qml
import pennylane.numpy as np
from numpy.random import default_rng
import timeit
import sys

rng = default_rng(1337)
num_qubits = 10

def create_random_pauli_prod(num_qubits):
    paulis = [qml.Identity, qml.PauliX, qml.PauliY, qml.PauliZ]
    pindices = rng.integers(0, 3, num_qubits)
    terms = [paulis[pindices[i]](i) for i in range(num_qubits)]
    return qml.operation.Tensor(*terms)

def create_hamiltonian(num_qubits, n_terms):
    ham_coeffs = rng.standard_normal(n_terms)
    ham_terms = [create_random_pauli_prod(num_qubits) for i in range(n_terms)]
    return qml.Hamiltonian(ham_coeffs, ham_terms)

dev = qml.device('lightning.qubit', wires=num_qubits)

def bench_func(n_terms):
    ham = create_hamiltonian(num_qubits, n_terms)
    with qml.tape.QuantumTape() as tape:
        qml.RX(0.23, wires=0)
        qml.CNOT(wires=[0,1])
        qml.RY(0.23, wires=1)
        qml.CNOT(wires=[1,2])
        qml.RZ(0.23, wires=2)
        qml.expval(ham)

    w = tape.get_parameters(tranable_only = True)

    def timing_this():
        weights = rng.random(3)
        weights = np.array(weights)
        w[:3] = weights
        tape.set_parameters(w, trainable_only=True)
        return dev.adjoint_jacobian(tape, np.ones(2**num_qubits, requires_grad=False, dtype=np.complex128))

    return timeit.timeit(timing_this, number=100)

for n_terms in [2**k for k in range(2, 9)]:
    print("{}\t{}".format(n_terms, bench_func(n_terms)))

Using this simple benchmark code, I got

master version
4	19.39245017792564
8	19.997620621928945
16	22.724174362956546
32	26.514014064101502
64	33.93342457001563
128	54.66594595997594
256	104.8523806289304

this PR
4	0.30219985102303326
8	0.20092515798751265
16	0.445317056030035
32	1.591180496965535
64	8.25559274898842
128	19.637774570961483
256	34.774507706053555

The first column is the number of terms in the Hamiltonian.

@chaeyeunpark
Copy link
Contributor Author

I also get slightly faster results for a simple observables:

import pennylane as qml
import pennylane.numpy as np
from numpy.random import default_rng
import timeit
import sys

rng = default_rng(1337)

def bench_func(num_qubits):
    dev = qml.device('lightning.qubit', wires=num_qubits)
    with qml.tape.QuantumTape() as tape:
        qml.RX(0.23, wires=0)
        qml.CNOT(wires=[0,1])
        qml.RY(0.23, wires=1)
        qml.CNOT(wires=[1,2])
        qml.RZ(0.23, wires=2)
        qml.expval(qml.PauliX(0) @ qml.PauliY(1))

    def timing_this():
        weights = rng.random(3)
        weights = np.array(weights)
        tape.set_parameters(weights, trainable_only=True)
        return dev.adjoint_jacobian(tape, np.ones(2**num_qubits, requires_grad=False, dtype=np.complex128))

    return timeit.timeit(timing_this, number=100)

for num_qubits in [4, 6, 8, 10, 12, 14, 16, 18]:
    print("{}\t{}".format(num_qubits, bench_func(num_qubits)))

And the result is:

master:
4	0.4656622860347852
6	0.2100854809395969
8	0.05818713700864464
10	0.6123739270260558
12	0.2523528659949079
14	0.19010203890502453
16	1.332373121054843
18	4.672340785968117

this PR:
4	0.12154659803491086
6	0.06435875396709889
8	0.061190371052362025
10	0.05885270098224282
12	0.17519149102736264
14	0.20414239005185664
16	0.935425164992921
18	4.56479615601711

The first column is the number of qubits.

@mlxd
Copy link
Member

mlxd commented Jun 16, 2022

I also get slightly faster results for a simple observables:

import pennylane as qml
import pennylane.numpy as np
from numpy.random import default_rng
import timeit
import sys

rng = default_rng(1337)

def bench_func(num_qubits):
    dev = qml.device('lightning.qubit', wires=num_qubits)
    with qml.tape.QuantumTape() as tape:
        qml.RX(0.23, wires=0)
        qml.CNOT(wires=[0,1])
        qml.RY(0.23, wires=1)
        qml.CNOT(wires=[1,2])
        qml.RZ(0.23, wires=2)
        qml.expval(qml.PauliX(0) @ qml.PauliY(1))

    def timing_this():
        weights = rng.random(3)
        weights = np.array(weights)
        tape.set_parameters(weights, trainable_only=True)
        return dev.adjoint_jacobian(tape, np.ones(2**num_qubits, requires_grad=False, dtype=np.complex128))

    return timeit.timeit(timing_this, number=100)

for num_qubits in [4, 6, 8, 10, 12, 14, 16, 18]:
    print("{}\t{}".format(num_qubits, bench_func(num_qubits)))

And the result is:

master:
4	0.4656622860347852
6	0.2100854809395969
8	0.05818713700864464
10	0.6123739270260558
12	0.2523528659949079
14	0.19010203890502453
16	1.332373121054843
18	4.672340785968117

this PR:
4	0.12154659803491086
6	0.06435875396709889
8	0.061190371052362025
10	0.05885270098224282
12	0.17519149102736264
14	0.20414239005185664
16	0.935425164992921
18	4.56479615601711

The first column is the number of qubits.

Those numbers are amazing --- excellent work putting this together!

Copy link
Member

@mlxd mlxd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing more to add. Great work, and thanks @chaeyeunpark

Comment on lines 844 to 846
custom_decomps={'DoubleExcitation': qml.DoubleExcitation.compute_decomposition}
dev_lig = qml.device("lightning.qubit", wires=qubits, c_dtype = c_dtype,
custom_decomps=custom_decomps)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
custom_decomps={'DoubleExcitation': qml.DoubleExcitation.compute_decomposition}
dev_lig = qml.device("lightning.qubit", wires=qubits, c_dtype = c_dtype,
custom_decomps=custom_decomps)
dev_lig = qml.device("lightning.qubit", wires=qubits, c_dtype = c_dtype)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This custom decomposition is not necessary anymore.

Copy link
Contributor

@AmintorDusko AmintorDusko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excellent work! You have my 100% OK after the small fix, I suggest.

@chaeyeunpark
Copy link
Contributor Author

Thanks @AmintorDusko and @mlxd for the reviews. I just added one small test. I will merge this PR when Tidy is satisfied with the code.

@chaeyeunpark chaeyeunpark merged commit 9742ad9 into master Jun 16, 2022
@chaeyeunpark chaeyeunpark deleted the statevec_jacobian branch June 16, 2022 22:25
mlxd added a commit that referenced this pull request Jun 17, 2022
* add_isingxy_generator

* Auto update version

* Remove commented lines

* add IsingXY gate to the Python tests

* Statevector vjp and support Hamiltonian in adjoint_jacobian (#294)

* Adding

* Refactoring Algorithms

* Add more test

* Refactor bindings

* Exploring more

* Refactoring JacobianTape...

* C++ test works

* Hamiltonian works in Python

* Refactoring vjp

* Fixing some errors from tests

* Fixing some tests

* New branch from master

* Add tests

* Fix Python test

* Fix test

* Update coverage

* Fix binding dependency

* Fix GBenchmark

* Revert StateVector tests to origin

* Add more tests

* Auto update version

* Fix for tidy

* Update KernelMap

* Fix for codefactor

* Auto update version

* Trigger CI

* Update Memory

* Fix

* Revert single file

* Fix for tidy

* Fixing

* Works

* Works for python tests

* Remove unused file

* Fix some more

* Auto update version

* Trigger CI

* Fix

* Fix for tidy

* Fix for MSVC

* Fix tape trainable_param interface

* Add statevec diff test

* Fixing serialization tests

* Apply suggestions from code reviews

* Update macos target version

* Update MacOS minimum version in CMake

* Update for MacOS

* Revert aligned_alloc for MacOS

* Fix

* Apply suggestions from code review

Co-authored-by: Ali Asadi <ali@xanadu.ai>

* Apply suggestions from code review

* Test passes

* Update

* Fix

* Fix docstring

* Remove unused dir

* Update

* Fix doc

* Remove BUILD_EXAMPLES option from CMake

* Fix

* Update memory

* Memory works

* Try to use std::aligned_alloc for MacOS

* Revert "Try to use std::aligned_alloc for MacOS"

This reverts commit b2b0035.

* Use C aligned_alloc for MacOs

* Fix for tidy

* Revert to posix_malloc in MacOS

* Update pennylane_lightning/src/simulator/KernelMap.hpp

Co-authored-by: Lee James O'Riordan <mlxd@users.noreply.github.com>

* Update docstring

* Update pennylane_lightning/src/tests/Test_Measures_Sparse.cpp

Co-authored-by: Amintor Dusko <87949283+AmintorDusko@users.noreply.github.com>

* Apply suggestions from review

* Auto update version

* Update KernelMap

* Update pennylane_lightning/src/tests/TestKernels.hpp

Co-authored-by: Amintor Dusko <87949283+AmintorDusko@users.noreply.github.com>

* Fix tests

* Add Changelog

* Split and add tests for observables

* Auto update version

* Trigger CI

* Trigger CI

* Fix for tidy

* Fix non-const error from clang

* Fix for tidy

* Apply suggestions from code review

Co-authored-by: Lee James O'Riordan <mlxd@users.noreply.github.com>

* Apply suggestions from a code review

* Apply suggestions from code review

Co-authored-by: Amintor Dusko <87949283+AmintorDusko@users.noreply.github.com>

* Increase coverage a bit

* Fix

* Fix

* Format

* Add C++ tests for LinearAlgebra

* Format

* Use span for statevector

* Add tests for getObsName

* Format

* More format

* Trigger CI

* Fix

* Fix for tidy

* Add more tests for covergage

* More fix for tidy

* Add more tests for observables

* Fix for tidy

* Add python tests; Use std::span

* Add more tests for codecov

* Add more tests for coverage; Update Makefile

* Fix for tidy

* Fix for tidy

* Clarify documentation on statevector diff; Add tests for complex dy for StateVecAdjDiff

* Apply suggestions from code review; Add some tests

* Update tests/test_adjoint_jacobian.py

Co-authored-by: Amintor Dusko <87949283+AmintorDusko@users.noreply.github.com>

* Fix docstring

* Fix doc

* Auto update version

* Update pennylane_lightning/src/algorithms/StateVecAdjDiff.hpp

Co-authored-by: Lee James O'Riordan <mlxd@users.noreply.github.com>

* Fix for invalid trainable_params

* Format

* Fix multithreading hamiltonian expval

* Fix format

* Fix for MacOS?

* Format

* Fix more openmp parallel Hamiltonian computation

* Add complicated Hamiltonian test

* Add changelog

* Apply suggestions from code review

* Fix for tidy

Co-authored-by: Ali Asadi <ali@xanadu.ai>
Co-authored-by: Lee James O'Riordan <mlxd@users.noreply.github.com>
Co-authored-by: Amintor Dusko <87949283+AmintorDusko@users.noreply.github.com>

Co-authored-by: Dev version update bot <chae-yeun@xanadu.ai>
Co-authored-by: Lee James O'Riordan <mlxd@users.noreply.github.com>
Co-authored-by: Ali Asadi <ali@xanadu.ai>
Co-authored-by: Amintor Dusko <87949283+AmintorDusko@users.noreply.github.com>
maliasadi added a commit that referenced this pull request Jun 20, 2022
* Create RC0

* Update contributors

* Update changelog

* Update pennylane_lightning/_version.py

Co-authored-by: Amintor Dusko <87949283+AmintorDusko@users.noreply.github.com>

* Update .github/CHANGELOG.md

Co-authored-by: Chae-Yeun Park <chae-yeun@xanadu.ai>

* Fix macos m1 arm wheel (#306)

* Add IsingXY

* Auto update version

* Trigger CI

* Trigger CI

* Trigger CI

* Trigger CI

* Trigger CI

* Trigger CI

* Trigger CI

* Trigger CI

* make format

* make format

* Delete .DS_Store

.DS_Store deleted

* Delete .DS_Store

* Delete .DS_store

* Delete .DS_Store

* Trigger CI

* fix MacOS ARM64 wheels

* Auto update version

* comment line 66 of wheel_macros_arm64.yml

* uncomment line 66

* Remove space at the end of line 89

Co-authored-by: Dev version update bot <chae-yeun@xanadu.ai>
Co-authored-by: Lee James O'Riordan <mlxd@users.noreply.github.com>

* Trigger docs build

* Fix workflow

* add_isingxy_generator (#307)

* add_isingxy_generator

* Auto update version

* Remove commented lines

* add IsingXY gate to the Python tests

* Statevector vjp and support Hamiltonian in adjoint_jacobian (#294)

* Adding

* Refactoring Algorithms

* Add more test

* Refactor bindings

* Exploring more

* Refactoring JacobianTape...

* C++ test works

* Hamiltonian works in Python

* Refactoring vjp

* Fixing some errors from tests

* Fixing some tests

* New branch from master

* Add tests

* Fix Python test

* Fix test

* Update coverage

* Fix binding dependency

* Fix GBenchmark

* Revert StateVector tests to origin

* Add more tests

* Auto update version

* Fix for tidy

* Update KernelMap

* Fix for codefactor

* Auto update version

* Trigger CI

* Update Memory

* Fix

* Revert single file

* Fix for tidy

* Fixing

* Works

* Works for python tests

* Remove unused file

* Fix some more

* Auto update version

* Trigger CI

* Fix

* Fix for tidy

* Fix for MSVC

* Fix tape trainable_param interface

* Add statevec diff test

* Fixing serialization tests

* Apply suggestions from code reviews

* Update macos target version

* Update MacOS minimum version in CMake

* Update for MacOS

* Revert aligned_alloc for MacOS

* Fix

* Apply suggestions from code review

Co-authored-by: Ali Asadi <ali@xanadu.ai>

* Apply suggestions from code review

* Test passes

* Update

* Fix

* Fix docstring

* Remove unused dir

* Update

* Fix doc

* Remove BUILD_EXAMPLES option from CMake

* Fix

* Update memory

* Memory works

* Try to use std::aligned_alloc for MacOS

* Revert "Try to use std::aligned_alloc for MacOS"

This reverts commit b2b0035.

* Use C aligned_alloc for MacOs

* Fix for tidy

* Revert to posix_malloc in MacOS

* Update pennylane_lightning/src/simulator/KernelMap.hpp

Co-authored-by: Lee James O'Riordan <mlxd@users.noreply.github.com>

* Update docstring

* Update pennylane_lightning/src/tests/Test_Measures_Sparse.cpp

Co-authored-by: Amintor Dusko <87949283+AmintorDusko@users.noreply.github.com>

* Apply suggestions from review

* Auto update version

* Update KernelMap

* Update pennylane_lightning/src/tests/TestKernels.hpp

Co-authored-by: Amintor Dusko <87949283+AmintorDusko@users.noreply.github.com>

* Fix tests

* Add Changelog

* Split and add tests for observables

* Auto update version

* Trigger CI

* Trigger CI

* Fix for tidy

* Fix non-const error from clang

* Fix for tidy

* Apply suggestions from code review

Co-authored-by: Lee James O'Riordan <mlxd@users.noreply.github.com>

* Apply suggestions from a code review

* Apply suggestions from code review

Co-authored-by: Amintor Dusko <87949283+AmintorDusko@users.noreply.github.com>

* Increase coverage a bit

* Fix

* Fix

* Format

* Add C++ tests for LinearAlgebra

* Format

* Use span for statevector

* Add tests for getObsName

* Format

* More format

* Trigger CI

* Fix

* Fix for tidy

* Add more tests for covergage

* More fix for tidy

* Add more tests for observables

* Fix for tidy

* Add python tests; Use std::span

* Add more tests for codecov

* Add more tests for coverage; Update Makefile

* Fix for tidy

* Fix for tidy

* Clarify documentation on statevector diff; Add tests for complex dy for StateVecAdjDiff

* Apply suggestions from code review; Add some tests

* Update tests/test_adjoint_jacobian.py

Co-authored-by: Amintor Dusko <87949283+AmintorDusko@users.noreply.github.com>

* Fix docstring

* Fix doc

* Auto update version

* Update pennylane_lightning/src/algorithms/StateVecAdjDiff.hpp

Co-authored-by: Lee James O'Riordan <mlxd@users.noreply.github.com>

* Fix for invalid trainable_params

* Format

* Fix multithreading hamiltonian expval

* Fix format

* Fix for MacOS?

* Format

* Fix more openmp parallel Hamiltonian computation

* Add complicated Hamiltonian test

* Add changelog

* Apply suggestions from code review

* Fix for tidy

Co-authored-by: Ali Asadi <ali@xanadu.ai>
Co-authored-by: Lee James O'Riordan <mlxd@users.noreply.github.com>
Co-authored-by: Amintor Dusko <87949283+AmintorDusko@users.noreply.github.com>

Co-authored-by: Dev version update bot <chae-yeun@xanadu.ai>
Co-authored-by: Lee James O'Riordan <mlxd@users.noreply.github.com>
Co-authored-by: Ali Asadi <ali@xanadu.ai>
Co-authored-by: Amintor Dusko <87949283+AmintorDusko@users.noreply.github.com>

* Fix docstring

* Update CHANGELOG

* Update doc/conf.py

* Update docs

* Fix Exhale version to 0.3.1

* Update MultiRZ generator

* Update changelog

* Update docs

* Enable KOKKOS

* Update python tests

* Update pennylane_lightning/_version.py

Co-authored-by: Lee James O'Riordan <mlxd@users.noreply.github.com>

Co-authored-by: Amintor Dusko <87949283+AmintorDusko@users.noreply.github.com>
Co-authored-by: Chae-Yeun Park <chae-yeun@xanadu.ai>
Co-authored-by: slshu <31480676+multiphaseCFD@users.noreply.github.com>
Co-authored-by: Lee James O'Riordan <mlxd@users.noreply.github.com>
Co-authored-by: Lee J. O'Riordan <loriordan@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add support for qml.Hamiltonian with lightning.qubit for diff_method='adjoint'
3 participants