-
Notifications
You must be signed in to change notification settings - Fork 36
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
156a035
commit bc743f0
Showing
8 changed files
with
1,384 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
93 changes: 93 additions & 0 deletions
93
pennylane_lightning/core/src/simulators/lightning_qubit/catalyst/CMakeLists.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
cmake_minimum_required(VERSION 3.20) | ||
|
||
project(lightning_qubit_catalyst LANGUAGES CXX) | ||
|
||
set(LQ_CATALYST_FILES LightningSimulator.cpp CACHE INTERNAL "") | ||
add_library(lightning_qubit_catalyst SHARED ${LQ_CATALYST_FILES}) | ||
|
||
include(FetchContent) | ||
|
||
if(LIGHTNING_CATALYST_SRC_PATH) | ||
if(NOT IS_ABSOLUTE ${LIGHTNING_CATALYST_SRC_PATH}) | ||
message(FATAL_ERROR " LIGHTNING_CATALYST_SRC_PATH=${LIGHTNING_CATALYST_SRC_PATH} must be set to an absolute path") | ||
endif() | ||
if(CATALYST_GIT_TAG) | ||
message(WARN " Setting `LIGHTNING_CATALYST_SRC_PATH=${LIGHTNING_CATALYST_SRC_PATH}` overrides `CATALYST_GIT_TAG=${CATALYST_GIT_TAG}`") | ||
endif() | ||
|
||
# Acquire local git hash and use for CATALYST_GIT_TAG | ||
execute_process(COMMAND git rev-parse --short HEAD | ||
WORKING_DIRECTORY ${LIGHTNING_CATALYST_SRC_PATH} | ||
OUTPUT_VARIABLE CATALYST_GIT_TAG | ||
) | ||
message(INFO " Building against local Catalyst - path: ${LIGHTNING_CATALYST_SRC_PATH} - GIT TAG: ${CATALYST_GIT_TAG}") | ||
|
||
target_include_directories(lightning_qubit_catalyst PUBLIC ${LIGHTNING_CATALYST_SRC_PATH}/runtime/lib/backend/common) | ||
target_include_directories(lightning_qubit_catalyst PUBLIC ${LIGHTNING_CATALYST_SRC_PATH}/runtime/include) | ||
|
||
else() | ||
if(NOT CATALYST_GIT_TAG) | ||
set(CATALYST_GIT_TAG "main" CACHE STRING "GIT_TAG value to build Catalyst") | ||
endif() | ||
message(INFO " Building against Catalyst GIT TAG ${CATALYST_GIT_TAG}") | ||
|
||
# Fetching /lib/backend/common hpp headers | ||
set(LIB_BACKEND_COMMON_HEADERS CacheManager.hpp | ||
QubitManager.hpp | ||
Utils.hpp | ||
) | ||
|
||
foreach(HEADER ${LIB_BACKEND_COMMON_HEADERS}) | ||
string(REGEX REPLACE "\\.[^.]*$" "" HEADER_NAME ${HEADER}) | ||
FetchContent_Declare( | ||
${HEADER_NAME} | ||
URL https://raw.githubusercontent.com/PennyLaneAI/catalyst/${CATALYST_GIT_TAG}/runtime/lib/backend/common/${HEADER} | ||
DOWNLOAD_NO_EXTRACT True | ||
SOURCE_DIR include | ||
) | ||
|
||
FetchContent_MakeAvailable(${HEADER_NAME}) | ||
endforeach() | ||
|
||
# Fetching include hpp headers | ||
set(INCLUDE_HEADERS DataView.hpp | ||
Exception.hpp | ||
QuantumDevice.hpp | ||
RuntimeCAPI.h | ||
Types.h | ||
) | ||
|
||
foreach(HEADER ${INCLUDE_HEADERS}) | ||
string(REGEX REPLACE "\\.[^.]*$" "" HEADER_NAME ${HEADER}) | ||
FetchContent_Declare( | ||
${HEADER_NAME} | ||
URL https://raw.githubusercontent.com/PennyLaneAI/catalyst/${CATALYST_GIT_TAG}/runtime/include/${HEADER} | ||
DOWNLOAD_NO_EXTRACT True | ||
SOURCE_DIR include | ||
) | ||
|
||
FetchContent_MakeAvailable(${HEADER_NAME}) | ||
endforeach() | ||
|
||
target_include_directories(lightning_qubit_catalyst PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/include) | ||
|
||
endif() | ||
|
||
target_include_directories(lightning_qubit_catalyst INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) | ||
target_link_libraries(lightning_qubit_catalyst PUBLIC lightning_compile_options | ||
lightning_external_libs | ||
lightning_base | ||
lightning_gates | ||
lightning_utils | ||
lightning_qubit | ||
lightning_qubit_algorithms | ||
lightning_qubit_gates | ||
lightning_qubit_measurements | ||
lightning_qubit_observables | ||
lightning_qubit_utils | ||
) | ||
|
||
if (BUILD_TESTS) | ||
enable_testing() | ||
add_subdirectory("tests") | ||
endif() |
194 changes: 194 additions & 0 deletions
194
pennylane_lightning/core/src/simulators/lightning_qubit/catalyst/LightningObsManager.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,194 @@ | ||
// Copyright 2022-2023 Xanadu Quantum Technologies Inc. | ||
|
||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
|
||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
|
||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
#pragma once | ||
|
||
#include <array> | ||
#include <stdexcept> | ||
#include <tuple> | ||
#include <utility> | ||
|
||
#include "Exception.hpp" | ||
#include "Types.h" | ||
#include "Utils.hpp" | ||
|
||
#include "ObservablesLQubit.hpp" | ||
#include "StateVectorLQubitDynamic.hpp" | ||
|
||
namespace { | ||
using Pennylane::LightningQubit::StateVectorLQubitDynamic; | ||
using Pennylane::LightningQubit::Observables::HermitianObs; | ||
using Pennylane::LightningQubit::Observables::NamedObs; | ||
using Pennylane::LightningQubit::Observables::TensorProdObs; | ||
using Pennylane::Observables::Observable; | ||
} // namespace | ||
|
||
namespace Catalyst::Runtime::Simulator { | ||
|
||
/** | ||
* @brief The LightningObsManager caches observables of a program at runtime | ||
* and maps each one to a const unique index (`int64_t`) in the scope | ||
* of the global context manager. | ||
*/ | ||
template <typename PrecisionT> class LightningObsManager { | ||
private: | ||
using VectorStateT = StateVectorLQubitDynamic<PrecisionT>; | ||
using ObservablePairType = std::pair<std::shared_ptr<Observable<VectorStateT>>, ObsType>; | ||
std::vector<ObservablePairType> observables_{}; | ||
|
||
public: | ||
LightningObsManager() = default; | ||
~LightningObsManager() = default; | ||
|
||
LightningObsManager(const LightningObsManager &) = delete; | ||
LightningObsManager &operator=(const LightningObsManager &) = delete; | ||
LightningObsManager(LightningObsManager &&) = delete; | ||
LightningObsManager &operator=(LightningObsManager &&) = delete; | ||
|
||
/** | ||
* @brief A helper function to clear constructed observables in the program. | ||
*/ | ||
void clear() { observables_.clear(); } | ||
|
||
/** | ||
* @brief Check the validity of observable keys. | ||
* | ||
* @param obsKeys The vector of observable keys | ||
* @return bool | ||
*/ | ||
[[nodiscard]] auto isValidObservables(const std::vector<ObsIdType> &obsKeys) const -> bool | ||
{ | ||
return std::all_of(obsKeys.begin(), obsKeys.end(), [this](auto i) { | ||
return (i >= 0 && static_cast<size_t>(i) < observables_.size()); | ||
}); | ||
} | ||
|
||
/** | ||
* @brief Get the constructed observable instance. | ||
* | ||
* @param key The observable key | ||
* @return std::shared_ptr<Observable<VectorStateT>> | ||
*/ | ||
[[nodiscard]] auto getObservable(ObsIdType key) -> std::shared_ptr<Observable<VectorStateT>> | ||
{ | ||
RT_FAIL_IF(!isValidObservables({key}), "Invalid observable key"); | ||
return std::get<0>(observables_[key]); | ||
} | ||
|
||
/** | ||
* @brief Get the number of observables. | ||
* | ||
* @return size_t | ||
*/ | ||
[[nodiscard]] auto numObservables() const -> size_t { return observables_.size(); } | ||
|
||
/** | ||
* @brief Create and cache a new NamedObs instance. | ||
* | ||
* @param obsId The named observable id of type ObsId | ||
* @param wires The vector of wires the observable acts on | ||
* @return ObsIdType | ||
*/ | ||
[[nodiscard]] auto createNamedObs(ObsId obsId, const std::vector<size_t> &wires) -> ObsIdType | ||
{ | ||
auto &&obs_str = | ||
std::string(Lightning::lookup_obs<Lightning::simulator_observable_support_size>( | ||
Lightning::simulator_observable_support, obsId)); | ||
|
||
observables_.push_back(std::make_pair( | ||
std::make_shared<NamedObs<VectorStateT>>(obs_str, wires), ObsType::Basic)); | ||
return static_cast<ObsIdType>(observables_.size() - 1); | ||
} | ||
|
||
/** | ||
* @brief Create and cache a new HermitianObs instance. | ||
* | ||
* @param matrix The row-wise Hermitian matrix | ||
* @param wires The vector of wires the observable acts on | ||
* @return ObsIdType | ||
*/ | ||
[[nodiscard]] auto createHermitianObs(const std::vector<std::complex<PrecisionT>> &matrix, | ||
const std::vector<size_t> &wires) -> ObsIdType | ||
{ | ||
observables_.push_back(std::make_pair( | ||
std::make_shared<HermitianObs<VectorStateT>>(HermitianObs<VectorStateT>{matrix, wires}), | ||
ObsType::Basic)); | ||
|
||
return static_cast<ObsIdType>(observables_.size() - 1); | ||
} | ||
|
||
/** | ||
* @brief Create and cache a new TensorProd instance. | ||
* | ||
* @param obsKeys The vector of observable keys | ||
* @return ObsIdType | ||
*/ | ||
[[nodiscard]] auto createTensorProdObs(const std::vector<ObsIdType> &obsKeys) -> ObsIdType | ||
{ | ||
const auto key_size = obsKeys.size(); | ||
const auto obs_size = observables_.size(); | ||
|
||
std::vector<std::shared_ptr<Observable<VectorStateT>>> obs_vec; | ||
obs_vec.reserve(key_size); | ||
|
||
for (const auto &key : obsKeys) { | ||
RT_FAIL_IF(static_cast<size_t>(key) >= obs_size || key < 0, "Invalid observable key"); | ||
|
||
auto &&[obs, type] = observables_[key]; | ||
obs_vec.push_back(obs); | ||
} | ||
|
||
observables_.push_back( | ||
std::make_pair(TensorProdObs<VectorStateT>::create(obs_vec), ObsType::TensorProd)); | ||
|
||
return static_cast<ObsIdType>(obs_size); | ||
} | ||
|
||
/** | ||
* @brief Create and cache a new HamiltonianObs instance. | ||
* | ||
* @param coeffs The vector of coefficients | ||
* @param obsKeys The vector of observable keys | ||
* @return ObsIdType | ||
*/ | ||
[[nodiscard]] auto createHamiltonianObs(const std::vector<PrecisionT> &coeffs, | ||
const std::vector<ObsIdType> &obsKeys) -> ObsIdType | ||
{ | ||
const auto key_size = obsKeys.size(); | ||
const auto obs_size = observables_.size(); | ||
|
||
RT_FAIL_IF(key_size != coeffs.size(), | ||
"Incompatible list of observables and coefficients; " | ||
"Number of observables and number of coefficients must be equal"); | ||
|
||
std::vector<std::shared_ptr<Observable<VectorStateT>>> obs_vec; | ||
obs_vec.reserve(key_size); | ||
|
||
for (auto key : obsKeys) { | ||
RT_FAIL_IF(static_cast<size_t>(key) >= obs_size || key < 0, "Invalid observable key"); | ||
|
||
auto &&[obs, type] = observables_[key]; | ||
obs_vec.push_back(obs); | ||
} | ||
|
||
observables_.push_back(std::make_pair( | ||
std::make_shared<Pennylane::LightningQubit::Observables::Hamiltonian<VectorStateT>>( | ||
Pennylane::LightningQubit::Observables::Hamiltonian<VectorStateT>( | ||
coeffs, std::move(obs_vec))), | ||
ObsType::Hamiltonian)); | ||
|
||
return static_cast<ObsIdType>(obs_size); | ||
} | ||
}; | ||
} // namespace Catalyst::Runtime::Simulator |
Oops, something went wrong.