Skip to content

Commit 9742ad9

Browse files
chaeyeunparkmaliasadimlxdAmintorDusko
authored
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 <[email protected]> * 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 <[email protected]> * Update docstring * Update pennylane_lightning/src/tests/Test_Measures_Sparse.cpp Co-authored-by: Amintor Dusko <[email protected]> * Apply suggestions from review * Auto update version * Update KernelMap * Update pennylane_lightning/src/tests/TestKernels.hpp Co-authored-by: Amintor Dusko <[email protected]> * 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 <[email protected]> * Apply suggestions from a code review * Apply suggestions from code review Co-authored-by: Amintor Dusko <[email protected]> * 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 <[email protected]> * Fix docstring * Fix doc * Auto update version * Update pennylane_lightning/src/algorithms/StateVecAdjDiff.hpp Co-authored-by: Lee James O'Riordan <[email protected]> * 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 <[email protected]> Co-authored-by: Lee James O'Riordan <[email protected]> Co-authored-by: Amintor Dusko <[email protected]>
1 parent a6f4c99 commit 9742ad9

40 files changed

+4001
-1859
lines changed

.github/CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
* Add a new dispatch mechanism for future kernels.
99
[(#291)](https://github.com/PennyLaneAI/pennylane-lightning/pull/291)
1010

11+
* Support qml.state() in vjp and Hamiltonian in adjoint jacobian.
12+
[(#294)](https://github.com/PennyLaneAI/pennylane-lightning/pull/294)
13+
1114
### Breaking changes
1215

1316
* Codebase is now moving to C++20. The default compiler for Linux is now GCC10.

.gitignore

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ doc/_build/
33
PennyLane_Lightning.egg-info/
44
build/
55
Build/
6-
BuildBench/
76
BuildGBench/
87
BuildTests/
8+
BuildTidy/
99
dist/
1010
tests/__pycache__/
1111
.idea

Makefile

+3-3
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ docs:
5858
clean-docs:
5959
$(MAKE) -C doc clean
6060

61-
.PHONY : test-builtin test-suite test-python coverage test-cpp
61+
.PHONY : test-builtin test-suite test-python coverage test-cpp test-cpp-no-omp test-cpp-blas test-cpp-kokkos
6262
test-builtin:
6363
$(PYTHON) -I $(TESTRUNNER)
6464

@@ -86,9 +86,9 @@ test-cpp-blas:
8686
cmake --build ./BuildTests --target runner
8787
cmake --build ./BuildTests --target test
8888

89-
test-cpp-omp:
89+
test-cpp-no-omp:
9090
rm -rf ./BuildTests
91-
cmake $(LIGHTNING_CPP_DIR) -BBuildTests -DBUILD_TESTS=ON -DENABLE_OPENMP=ON
91+
cmake $(LIGHTNING_CPP_DIR) -BBuildTests -DBUILD_TESTS=ON -DENABLE_OPENMP=OFF
9292
cmake --build ./BuildTests --target runner
9393
cmake --build ./BuildTests --target test
9494

doc/conf.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ def __getattr__(cls, name):
120120
# TIP: if using the sphinx-bootstrap-theme, you need
121121
# "treeViewIsBootstrap": True,
122122
"exhaleExecutesDoxygen": True,
123-
"exhaleDoxygenStdin": ("INPUT = " + " ".join(CPP_FILES) + " " "EXCLUDE_SYMBOLS = std::* "),
123+
"exhaleDoxygenStdin": ("INPUT = " + " ".join(CPP_FILES) + "\nEXCLUDE_SYMBOLS = std::* "),
124124
"afterTitleDescription": inspect.cleandoc(
125125
"""
126126
The Pennylane Lightning C++ API is intended to be called from Python through Pybind11. Direct use of the C++ API is currently unsupported and is provided for reference only.

pennylane_lightning/_serialize.py

+72-48
Original file line numberDiff line numberDiff line change
@@ -35,85 +35,109 @@
3535
try:
3636
from .lightning_qubit_ops import (
3737
StateVectorC64,
38-
ObsStructC64,
3938
StateVectorC128,
40-
ObsStructC128,
39+
)
40+
from .lightning_qubit_ops.adjoint_diff import (
41+
NamedObsC64,
42+
NamedObsC128,
43+
HermitianObsC64,
44+
HermitianObsC128,
45+
TensorProdObsC64,
46+
TensorProdObsC128,
47+
HamiltonianC64,
48+
HamiltonianC128,
49+
OpsStructC64,
50+
OpsStructC128,
4151
)
4252
except ImportError:
4353
pass
4454

4555

46-
def _obs_has_kernel(obs: Observable) -> bool:
56+
def _obs_has_kernel(ob: Observable) -> bool:
4757
"""Returns True if the input observable has a supported kernel in the C++ backend.
4858
4959
Args:
50-
obs (Observable): the input observable
60+
ob (Observable): the input observable
5161
5262
Returns:
5363
bool: indicating whether ``obs`` has a dedicated kernel in the backend
5464
"""
55-
if is_pauli_word(obs):
65+
if is_pauli_word(ob):
5666
return True
57-
if isinstance(obs, (Hadamard, Projector)):
67+
if isinstance(ob, (Hadamard, Projector)):
5868
return True
59-
if isinstance(obs, Tensor):
60-
return all(_obs_has_kernel(o) for o in obs.obs)
69+
if isinstance(ob, Tensor):
70+
return all(_obs_has_kernel(o) for o in ob.obs)
6171
return False
6272

6373

64-
def _serialize_obs(tape: QuantumTape, wires_map: dict, use_csingle: bool = False) -> List:
65-
"""Serializes the observables of an input tape.
66-
67-
Args:
68-
tape (QuantumTape): the input quantum tape
69-
wires_map (dict): a dictionary mapping input wires to the device's backend wires
70-
use_csingle (bool): whether to use np.complex64 instead of np.complex128
71-
72-
Returns:
73-
list(ObsStructC128 or ObsStructC64): A list of observable objects compatible with the C++ backend
74-
"""
75-
obs = []
74+
def _serialize_named_hermitian_ob(o, wires_map: dict, use_csingle: bool):
75+
"""Serializes an observable (Named or Hermitian)"""
76+
assert not isinstance(o, Tensor)
7677

7778
if use_csingle:
7879
ctype = np.complex64
79-
obs_py = ObsStructC64
80+
named_obs = NamedObsC64
81+
hermitian_obs = HermitianObsC64
8082
else:
8183
ctype = np.complex128
82-
obs_py = ObsStructC128
84+
named_obs = NamedObsC128
85+
hermitian_obs = HermitianObsC128
8386

84-
for o in tape.observables:
85-
is_tensor = isinstance(o, Tensor)
87+
wires_list = o.wires.tolist()
88+
wires = [wires_map[w] for w in wires_list]
89+
if _obs_has_kernel(o):
90+
return named_obs(o.name, wires)
91+
return hermitian_obs(qml.matrix(o).ravel().astype(ctype), wires)
8692

87-
wires = []
8893

89-
if is_tensor:
90-
for o_ in o.obs:
91-
wires_list = o_.wires.tolist()
92-
w = [wires_map[w] for w in wires_list]
93-
wires.append(w)
94-
else:
95-
wires_list = o.wires.tolist()
96-
w = [wires_map[w] for w in wires_list]
97-
wires.append(w)
94+
def _serialize_tensor_ob(ob, wires_map: dict, use_csingle: bool):
95+
"""Serialize a tensor observable"""
96+
assert isinstance(ob, Tensor)
9897

99-
name = o.name if is_tensor else [o.name]
98+
if use_csingle:
99+
tensor_obs = TensorProdObsC64
100+
else:
101+
tensor_obs = TensorProdObsC128
100102

101-
params = []
103+
return tensor_obs([_serialize_ob(o, wires_map, use_csingle) for o in ob.obs])
102104

103-
if not _obs_has_kernel(o):
104-
if is_tensor:
105-
for o_ in o.obs:
106-
if not _obs_has_kernel(o_):
107-
params.append(qml.matrix(o_).ravel().astype(ctype))
108-
else:
109-
params.append([])
110-
else:
111-
params.append(qml.matrix(o).ravel().astype(ctype))
112105

113-
ob = obs_py(name, params, wires)
114-
obs.append(ob)
106+
def _serialize_hamiltonian(ob, wires_map: dict, use_csingle: bool):
107+
if use_csingle:
108+
rtype = np.float32
109+
hamiltonian_obs = HamiltonianC64
110+
else:
111+
rtype = np.float64
112+
hamiltonian_obs = HamiltonianC128
113+
114+
coeffs = np.array(ob.coeffs).astype(rtype)
115+
terms = [_serialize_ob(t, wires_map, use_csingle) for t in ob.ops]
116+
return hamiltonian_obs(coeffs, terms)
117+
118+
119+
def _serialize_ob(ob, wires_map, use_csingle):
120+
if isinstance(ob, Tensor):
121+
return _serialize_tensor_ob(ob, wires_map, use_csingle)
122+
elif ob.name == "Hamiltonian":
123+
return _serialize_hamiltonian(ob, wires_map, use_csingle)
124+
else:
125+
return _serialize_named_hermitian_ob(ob, wires_map, use_csingle)
126+
127+
128+
def _serialize_observables(tape: QuantumTape, wires_map: dict, use_csingle: bool = False) -> List:
129+
"""Serializes the observables of an input tape.
130+
131+
Args:
132+
tape (QuantumTape): the input quantum tape
133+
wires_map (dict): a dictionary mapping input wires to the device's backend wires
134+
use_csingle (bool): whether to use np.complex64 instead of np.complex128
135+
136+
Returns:
137+
list(ObsStructC128 or ObsStructC64): A list of observable objects compatible with the C++ backend
138+
"""
115139

116-
return obs
140+
return [_serialize_ob(ob, wires_map, use_csingle) for ob in tape.observables]
117141

118142

119143
def _serialize_ops(

pennylane_lightning/_version.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,4 @@
1616
Version number (major.minor.patch[-label])
1717
"""
1818

19-
__version__ = "0.24.0-dev15"
19+
__version__ = "0.24.0-dev16"

0 commit comments

Comments
 (0)