Skip to content

Commit

Permalink
Copy Catalyst plugin files for LQ
Browse files Browse the repository at this point in the history
  • Loading branch information
rauletorresc committed Oct 24, 2024
1 parent 156a035 commit bc743f0
Show file tree
Hide file tree
Showing 8 changed files with 1,384 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ set_property(TARGET lightning_qubit PROPERTY POSITION_INDEPENDENT_CODE ON)
###############################################################################
set(COMPONENT_SUBDIRS algorithms
bindings
catalyst
gates
measurements
observables
Expand Down
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()
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
Loading

0 comments on commit bc743f0

Please sign in to comment.