Skip to content

Commit

Permalink
Merge branch 'main' into add-batch-update
Browse files Browse the repository at this point in the history
  • Loading branch information
Glacialte authored Dec 27, 2024
2 parents 6cc4290 + a422e09 commit 250f78a
Show file tree
Hide file tree
Showing 28 changed files with 951 additions and 42 deletions.
5 changes: 3 additions & 2 deletions .devcontainer/cpu/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@
"C_Cpp.default.includePath": [
"scaluq",
"/usr/local/include/kokkos",
"build/_deps/eigen_fetch-src",
"build/_deps/googletest_fetch-src/googletest/include",
"build/_deps/eigen-src",
"build/_deps/googletest-src/googletest/include",
"build/_deps/json-src/include",
"~/.local/lib/python3.10/site-packages/nanobind/include",
"/usr/include/python3.10"
],
Expand Down
1 change: 1 addition & 0 deletions .devcontainer/gpu/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"/usr/local/include/kokkos",
"build/_deps/eigen-src",
"build/_deps/googletest-src/googletest/include",
"build/_deps/json-src/include",
"~/.local/lib/python3.10/site-packages/nanobind/include",
"/usr/include/python3.10"
],
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/install.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ jobs:
cd example_project/
cmake -B build/ -D "CMAKE_C_COMPILER=$CMAKE_C_COMPILER" -D "CMAKE_CXX_COMPILER=$CMAKE_CXX_COMPILER" -D "SCALUQ_USE_CUDA=$SCALUQ_USE_CUDA"
make -C build
if [ "$SCALUQ_USE_CUDA" != 'ON']; then
if [ "$SCALUQ_USE_CUDA" != 'ON' ]; then
build/main
fi
Expand Down
9 changes: 9 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,15 @@ FetchContent_Declare(
)
FetchContent_MakeAvailable(eigen)

# nlohmann_json
FetchContent_Declare(
json
URL https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
)
FetchContent_MakeAvailable(json)
install(DIRECTORY ${json_SOURCE_DIR}/single_include/nlohmann DESTINATION include)

# nanobind
if(SKBUILD)
find_package(Python 3.8
Expand Down
10 changes: 6 additions & 4 deletions example_project/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ endif()
find_package(Kokkos)
find_package(scaluq)
add_executable(main main.cpp)
target_include_directories(main PUBLIC /usr/local/include/scaluq)
target_include_directories(main PUBLIC /usr/local/include/kokkos)
target_include_directories(main PUBLIC /usr/local/include/eigen3)
target_include_directories(main PUBLIC
/usr/local/include/scaluq
/usr/local/include/kokkos
/usr/local/include/eigen3
/usr/local/include/nlohmann
)
target_compile_features(main PUBLIC cxx_std_20)
target_compile_options(main PUBLIC -fopenmp)
target_compile_definitions(main PUBLIC OPENMP)
target_link_libraries(main PUBLIC scaluq::scaluq)

3 changes: 2 additions & 1 deletion exe/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ function(exe name)
scaluq
Eigen3::Eigen
Kokkos::kokkos
nlohmann_json::nlohmann_json
GTest::gtest_main
)
if (SCALUQ_USE_TEST)
target_link_libraries(${name} PRIVATE GTest::gtest_main)
endif(SCALUQ_USE_TEST)
target_include_directories(${name} PRIVATE ${PROJECT_SOURCE_DIR}/include)
endfunction()

# exe({file}) を追加すると、{file}.cpp をコンパイルして実行ファイルを build/exe/{file} として生成する
exe(main)
157 changes: 150 additions & 7 deletions exe/main.cpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
#include <cstdint>
#include <iostream>
#include <scaluq/circuit/circuit.hpp>
#include <scaluq/gate/gate_factory.hpp>
#include <scaluq/operator/operator.hpp>
#include <scaluq/state/state_vector.hpp>
#include <scaluq/all.hpp>

using namespace scaluq;
using namespace nlohmann;

int main() {
scaluq::initialize(); // must be called before using any scaluq methods
{
const std::uint64_t n_qubits = 3;
scaluq::StateVector state = scaluq::StateVector<double>::Haar_random_state(n_qubits, 0);
std::uint64_t n_qubits = 3;
scaluq::StateVector<double> state(n_qubits);
state.load({0, 1, 2, 3, 4, 5, 6, 7});
Json j = state;
std::cout << j << std::endl;
state = j;
std::cout << state << std::endl;

scaluq::Circuit<double> circuit(n_qubits);
Expand All @@ -24,5 +28,144 @@ int main() {
auto value = observable.get_expectation_value(state);
std::cout << value << std::endl;
}
scaluq::finalize(); // must be called last
{
std::uint64_t n_qubits = 2, batch_size = 2;
scaluq::StateVectorBatched<double> states(batch_size, n_qubits);
states.set_Haar_random_state(batch_size, n_qubits, false);
Json j = states;
std::cout << j << std::endl;
states = j;
std::cout << states << std::endl;
}
{
double coef = 2.0;
std::string pauli_string = "X 0 Z 1 Y 2";
PauliOperator<double> pauli(pauli_string, coef);
Json j = pauli;
std::cout << j << std::endl;
pauli = j;
}
{
std::uint64_t n_qubits = 3;
Operator<double> op(n_qubits);
op.add_operator({0b001, 0b010, Complex<double>(2)});
op.add_operator({"X 2 Y 1", 1});
Json j = op;
std::cout << j << std::endl;
op = j;
}
{
std::cout << Json(gate::I<double>()) << std::endl;
std::cout << Json(gate::X<double>(2, {0, 3})) << std::endl;
std::cout << Json(gate::Y<double>(2, {0, 3})) << std::endl;
std::cout << Json(gate::Z<double>(2, {0, 3})) << std::endl;
std::cout << Json(gate::H<double>(2, {0, 3})) << std::endl;
std::cout << Json(gate::S<double>(2, {0, 3})) << std::endl;
std::cout << Json(gate::Sdag<double>(2, {0, 3})) << std::endl;
std::cout << Json(gate::T<double>(2, {0, 3})) << std::endl;
std::cout << Json(gate::Tdag<double>(2, {0, 3})) << std::endl;
std::cout << Json(gate::SqrtX<double>(2, {0, 3})) << std::endl;
std::cout << Json(gate::SqrtXdag<double>(2, {0, 3})) << std::endl;
std::cout << Json(gate::SqrtY<double>(2, {0, 3})) << std::endl;
std::cout << Json(gate::SqrtYdag<double>(2, {0, 3})) << std::endl;
std::cout << Json(gate::RX<double>(2, 0.5, {0, 3})) << std::endl;
std::cout << Json(gate::RY<double>(2, 0.5, {0, 3})) << std::endl;
std::cout << Json(gate::RZ<double>(2, 0.5, {0, 3})) << std::endl;
std::cout << Json(gate::U1<double>(2, 0.5, {0, 3})) << std::endl;
std::cout << Json(gate::U2<double>(2, 0.5, 0.3, {0, 3})) << std::endl;
std::cout << Json(gate::U3<double>(2, 0.5, 0.3, 0.1, {0, 3})) << std::endl;
std::cout << Json(gate::Swap<double>(1, 2, {0, 3})) << std::endl;

PauliOperator<double> pauli("X 2 Y 1");
std::cout << Json(gate::Pauli<double>(pauli)) << std::endl;
std::cout << Json(gate::PauliRotation<double>(pauli, 0.5)) << std::endl;

std::cout << Json(gate::OneTargetMatrix<double>(2, {0, 1, 2, 3})) << std::endl;
std::cout << Json(gate::TwoTargetMatrix<double>(
2, 3, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}))
<< std::endl;

auto probgate =
gate::Probablistic<double>({.1, .9}, {gate::X<double>(0), gate::I<double>()});
std::cout << Json(probgate) << std::endl;

std::cout << Json(gate::ParamRX<double>(2, 1.5, {0, 3})) << std::endl;
std::cout << Json(gate::ParamRY<double>(2, 1.5, {0, 3})) << std::endl;
std::cout << Json(gate::ParamRZ<double>(2, 1.5, {0, 3})) << std::endl;
std::cout << Json(gate::ParamPauliRotation<double>(pauli, 0.5)) << std::endl;

auto paramprobgate = gate::ParamProbablistic<double>(
{.1, .9}, {gate::ParamRX<double>(0), gate::I<double>()});
std::cout << Json(paramprobgate) << std::endl;
}
{
auto x = gate::X<double>(1, {2});
Json j = x;
std::cout << j << std::endl;
Gate<double> gate = j;
std::cout << gate << std::endl;
}
{
auto x = gate::RX<double>(1, 0.5, {2});
Json j = x;
std::cout << j << std::endl;
Gate<double> gate = j;
std::cout << gate << std::endl;
}
{
auto x = gate::Swap<double>(1, 3, {2});
Json j = x;
std::cout << j << std::endl;
Gate<double> gate = j;
std::cout << gate << std::endl;
}
{
auto x = gate::OneTargetMatrix<double>(1, {2., 3., 0., 10.}, {0, 3});
Json j = x;
std::cout << j << std::endl;
Gate<double> gate = j;
std::cout << gate << std::endl;
}
{
PauliOperator<double> pauli("X 2 Y 1");
auto x = gate::PauliRotation<double>(pauli, 1.5, {0, 3});
Json j = x;
std::cout << j << std::endl;
Gate<double> gate = j;
std::cout << gate << std::endl;
}
{
auto probgate =
gate::Probablistic<double>({.1, .9}, {gate::X<double>(0, {2, 3}), gate::I<double>()});
Json j = probgate;
std::cout << j << std::endl;
Gate<double> gate = j;
std::cout << gate << std::endl;
}
{
auto x = gate::ParamRX<double>(1, {2});
Json j = x;
std::cout << j << std::endl;
ParamGate<double> gate = j;
std::cout << gate << std::endl;
}
{
auto paramprobgate = gate::ParamProbablistic<double>(
{.1, .9}, {gate::ParamRX<double>(0), gate::I<double>()});
Json j = paramprobgate;
std::cout << j << std::endl;
ParamGate<double> gate = j;
std::cout << gate << std::endl;
}
{
Circuit<double> circuit(10);
circuit.add_gate(gate::X<double>(0, {3}));
circuit.add_param_gate(gate::ParamRX<double>(0, 0.5, {3}), "RX");
Json j = circuit;
std::cout << j << std::endl;
Circuit<double> c = j;
std::cout << Json(c) << std::endl;
}

Kokkos::finalize();
}
27 changes: 21 additions & 6 deletions exe/main.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,26 @@
from scaluq import *
# from scaluq.gate import S
from scaluq.f64 import *

def main():
state = StateVector(2)
swap_gate = gate.Swap(0, 1)
print(state)
print(swap_gate)
state = StateVector(1)
x_gate = gate.X(0, [1])
print(state.to_json())
print(x_gate.to_json())
print(gate.ParamRX(0, 0.5, [1]).to_json())

circuit = Circuit(3)
circuit.add_gate(x_gate)
print(circuit.to_json())

pauli = PauliOperator("X 3 Y 2")

operator = Operator(4)
operator.add_operator(pauli)

print(operator.to_json())

states = StateVectorBatched(3, 3)
print(states.to_json())


if __name__ == "__main__":
main()
41 changes: 38 additions & 3 deletions include/scaluq/circuit/circuit.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,20 @@ template <std::floating_point Fp>
class Circuit {
public:
using GateWithKey = std::variant<Gate<Fp>, std::pair<ParamGate<Fp>, std::string>>;
Circuit() = default;
explicit Circuit(std::uint64_t n_qubits) : _n_qubits(n_qubits) {}

[[nodiscard]] inline std::uint64_t n_qubits() const { return _n_qubits; }
[[nodiscard]] inline const std::vector<GateWithKey>& gate_list() const { return _gate_list; }
[[nodiscard]] inline std::uint64_t n_gates() { return _gate_list.size(); }
[[nodiscard]] inline std::uint64_t n_gates() const { return _gate_list.size(); }
[[nodiscard]] std::set<std::string> key_set() const;
[[nodiscard]] inline const GateWithKey& get_gate_at(std::uint64_t idx) const {
if (idx >= _gate_list.size()) {
throw std::runtime_error("Circuit::get_gate_at(std::uint64_t): index out of bounds");
}
return _gate_list[idx];
}
[[nodiscard]] inline std::optional<std::string> get_param_key_at(std::uint64_t idx) {
[[nodiscard]] inline std::optional<std::string> get_param_key_at(std::uint64_t idx) const {
if (idx >= _gate_list.size()) {
throw std::runtime_error(
"Circuit::get_parameter_key(std::uint64_t): index out of bounds");
Expand Down Expand Up @@ -64,6 +65,30 @@ class Circuit {

Circuit get_inverse() const;

friend void to_json(Json& j, const Circuit& circuit) {
j = Json{{"n_qubits", circuit.n_qubits()}, {"gate_list", Json::array()}};
for (auto&& gate : circuit.gate_list()) {
if (gate.index() == 0)
j["gate_list"].emplace_back(Json{{"gate", std::get<0>(gate)}});
else
j["gate_list"].emplace_back(
Json{{"gate", std::get<1>(gate).first}, {"key", std::get<1>(gate).second}});
}
}

friend void from_json(const Json& j, Circuit& circuit) {
circuit = Circuit(j.at("n_qubits").get<std::uint64_t>());
const Json& tmp_list = j.at("gate_list");
for (const Json& gate_with_key : tmp_list) {
if (gate_with_key.contains("key")) {
circuit.add_param_gate(gate_with_key.at("gate").get<ParamGate<Fp>>(),
gate_with_key.at("key").get<std::string>());
} else {
circuit.add_gate(gate_with_key.at("gate").get<Gate<Fp>>());
}
}
}

private:
std::uint64_t _n_qubits;

Expand Down Expand Up @@ -126,7 +151,17 @@ void bind_circuit_circuit_hpp(nb::module_& m) {
.def("copy", &Circuit<Fp>::copy, "Copy circuit. All the gates inside is copied.")
.def("get_inverse",
&Circuit<Fp>::get_inverse,
"Get inverse of circuit. All the gates are newly created.");
"Get inverse of circuit. All the gates are newly created.")
.def(
"to_json",
[](const Circuit<Fp>& circuit) { return Json(circuit).dump(); },
"Information as json style.")
.def(
"load_json",
[](Circuit<Fp>& circuit, const std::string& str) {
circuit = nlohmann::json::parse(str);
},
"Read an object from the JSON representation of the circuit.");
}
} // namespace internal
#endif
Expand Down
Loading

0 comments on commit 250f78a

Please sign in to comment.