Skip to content

Commit

Permalink
operator bindings
Browse files Browse the repository at this point in the history
  • Loading branch information
KowerKoint committed Feb 19, 2024
1 parent e89583d commit 53fb076
Show file tree
Hide file tree
Showing 6 changed files with 234 additions and 27 deletions.
7 changes: 2 additions & 5 deletions exe/main.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
from qulacs2023 import *

def main():
a = StateVector.Haar_random_state(3)
print(a)
i = I(0)
i.update_quantum_state(a)
print(a)
a = PauliOperator([0, 60, 2], [2, 3, 1])
print(a.get_XZ_mask_representation())

initialize(InitializationSettings().set_num_threads(8))
main()
Expand Down
84 changes: 67 additions & 17 deletions python/binding.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#include <nanobind/nanobind.h>
#include <nanobind/operators.h>
#include <nanobind/stl/string.h>
#include <nanobind/stl/string_view.h>
#include <nanobind/stl/tuple.h>
#include <nanobind/stl/vector.h>

#include <all.hpp>
Expand Down Expand Up @@ -236,7 +239,8 @@ NB_MODULE(qulacs_core, m) {
"target_qubit_list"_a,
"pauli_id_list"_a,
"coef"_a = 1.)
// cannot capture init<const std::vector<UINT>&, Complex> because num or arguments are same
.def(nb::init<std::string_view, Complex>(), "pauli_string"_a, "coef"_a = 1.)
.def(nb::init<const std::vector<UINT> &, Complex>(), "pauli_id_par_qubit"_a, "coef"_a = 1.)
.def(
"__init__",
[](PauliOperator *t,
Expand All @@ -247,13 +251,13 @@ NB_MODULE(qulacs_core, m) {
const nb::int_ mask(~0ULL);
auto &bit_flip_raw = bit_flip_mask.data_raw();
assert(bit_flip_raw.empty());
while (bit_flip_mask_py) {
while (bit_flip_mask_py > nb::int_(0)) {
bit_flip_raw.push_back((UINT)nb::int_(bit_flip_mask_py & mask));
bit_flip_mask_py >>= nb::int_(64);
}
auto &phase_flip_raw = phase_flip_mask.data_raw();
assert(phase_flip_raw.empty());
while (phase_flip_mask_py) {
while (phase_flip_mask_py > nb::int_(0)) {
phase_flip_raw.push_back((UINT)nb::int_(phase_flip_mask_py & mask));
phase_flip_mask_py >>= nb::int_(64);
}
Expand All @@ -265,18 +269,64 @@ NB_MODULE(qulacs_core, m) {
.def("get_coef", &PauliOperator::get_coef)
.def("get_target_qubit_list", &PauliOperator::get_target_qubit_list)
.def("get_pauli_id_list", &PauliOperator::get_pauli_id_list)
.def("get_XZ_mask_representation", [](const PauliOperator &pauli) {
const auto &[x_mask, z_mask] = pauli.get_XZ_mask_representation();
const auto &x_raw = x_mask.data_raw();
nb::int_ x_mask_py(0);
for (UINT i = 0; i < x_raw.size(); ++i) {
x_mask_py |= nb::int_(x_raw[i]) << nb::int_(64 * i);
}
const auto &z_raw = z_mask.data_raw();
nb::int_ z_mask_py(0);
for (UINT i = 0; i < z_raw.size(); ++i) {
z_mask_py |= nb::int_(z_raw[i]) << nb::int_(64 * i);
}
return std::make_tuple(x_mask_py, z_mask_py);
});
.def("get_XZ_mask_representation",
[](const PauliOperator &pauli) {
const auto &[x_mask, z_mask] = pauli.get_XZ_mask_representation();
const auto &x_raw = x_mask.data_raw();
nb::int_ x_mask_py(0);
for (UINT i = 0; i < x_raw.size(); ++i) {
x_mask_py |= nb::int_(x_raw[i]) << nb::int_(64 * i);
}
const auto &z_raw = z_mask.data_raw();
nb::int_ z_mask_py(0);
for (UINT i = 0; i < z_raw.size(); ++i) {
z_mask_py |= nb::int_(z_raw[i]) << nb::int_(64 * i);
}
return std::make_tuple(x_mask_py, z_mask_py);
})
.def("get_pauli_string", &PauliOperator::get_pauli_string)
.def("get_dagger", &PauliOperator::get_dagger)
.def("get_qubit_count", &PauliOperator::get_qubit_count)
.def("change_coef", &PauliOperator::change_coef)
.def("add_single_pauli", &PauliOperator::add_single_pauli)
.def("apply_to_state", &PauliOperator::apply_to_state)
.def("get_expectation_value", &PauliOperator::get_expectation_value)
.def("get_transition_amplitude", &PauliOperator::get_transition_amplitude)
.def(nb::self * nb::self)
.def(nb::self *= nb::self)
.def(nb::self *= Complex())
.def(nb::self * Complex());

nb::class_<Operator>(m, "Operator")
.def(nb::init<UINT>())
.def("is_hermitian", &Operator::is_hermitian)
.def("n_qubits", &Operator::n_qubits)
.def("terms", &Operator::terms)
.def("to_string", &Operator::to_string)
.def("add_operator", nb::overload_cast<const PauliOperator &>(&Operator::add_operator))
.def("add_random_operator",
nb::overload_cast<UINT>(&Operator::add_random_operator),
"operator_count"_a = 1)
.def("add_random_operator", nb::overload_cast<UINT, UINT>(&Operator::add_random_operator))
.def("optimize", &Operator::optimize)
.def("get_dagger", &Operator::get_dagger)
.def("apply_to_state", &Operator::apply_to_state)
.def("get_expectation_value", &Operator::get_expectation_value)
.def("get_transition_amplitude", &Operator::get_transition_amplitude)
.def(nb::self *= Complex())
.def(nb::self * Complex())
.def(+nb::self)
.def(-nb::self)
.def(nb::self += nb::self)
.def(nb::self + nb::self)
.def(nb::self -= nb::self)
.def(nb::self - nb::self)
.def(nb::self * nb::self)
.def(nb::self *= nb::self)
.def(nb::self += PauliOperator())
.def(nb::self + PauliOperator())
.def(nb::self -= PauliOperator())
.def(nb::self - PauliOperator())
.def(nb::self *= PauliOperator())
.def(nb::self * PauliOperator());
}
80 changes: 78 additions & 2 deletions python/qulacs2023/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,43 @@ class InitializationSettings:
self, arg: bool, /
) -> qulacs2023.qulacs_core.InitializationSettings: ...

class Operator:
"""
None
"""

def __init__(self, arg: int, /) -> None: ...
def add_operator(self, arg: qulacs2023.qulacs_core.PauliOperator, /) -> None: ...
def add_random_operator(self, arg0: int, arg1: int, /) -> None:
"""
add_random_operator(self, arg0: int, arg1: int, /) -> None
"""
...

@overload
def add_random_operator(self, operator_count: int = 1) -> None:
"""
add_random_operator(self, operator_count: int = 1) -> None
"""
...

def apply_to_state(self, arg: qulacs2023.qulacs_core.StateVector, /) -> None: ...
def get_dagger(self) -> qulacs2023.qulacs_core.Operator: ...
def get_expectation_value(
self, arg: qulacs2023.qulacs_core.StateVector, /
) -> complex: ...
def get_transition_amplitude(
self,
arg0: qulacs2023.qulacs_core.StateVector,
arg1: qulacs2023.qulacs_core.StateVector,
/,
) -> complex: ...
def is_hermitian(self) -> bool: ...
def n_qubits(self) -> int: ...
def optimize(self) -> None: ...
def terms(self) -> list[qulacs2023.qulacs_core.PauliOperator]: ...
def to_string(self) -> str: ...

def P0(arg: int, /) -> qulacs2023.qulacs_core.Gate: ...

class P0Gate:
Expand Down Expand Up @@ -217,6 +254,22 @@ class PauliOperator:
None
"""

def __init__(
self, bit_flip_mask: int, phase_flip_mask: int, coef: complex = 1.0
) -> None:
"""
__init__(self, bit_flip_mask: int, phase_flip_mask: int, coef: complex = 1.0) -> None
"""
...

@overload
def __init__(self, coef: complex = 1.0) -> None:
"""
__init__(self, coef: complex = 1.0) -> None
"""
...

@overload
def __init__(
self,
target_qubit_list: list[int],
Expand All @@ -229,15 +282,38 @@ class PauliOperator:
...

@overload
def __init__(self, coef: complex = 1.0) -> None:
def __init__(self, pauli_string: str, coef: complex = 1.0) -> None:
"""
__init__(self, coef: complex = 1.0) -> None
__init__(self, pauli_string: str, coef: complex = 1.0) -> None
"""
...

@overload
def __init__(self, pauli_id_par_qubit: list[int], coef: complex = 1.0) -> None:
"""
__init__(self, pauli_id_par_qubit: list[int], coef: complex = 1.0) -> None
"""
...

def add_single_pauli(self, arg0: int, arg1: int, /) -> None: ...
def apply_to_state(self, arg: qulacs2023.qulacs_core.StateVector, /) -> None: ...
def change_coef(self, arg: complex, /) -> None: ...
def get_XZ_mask_representation(self) -> tuple[int, int]: ...
def get_coef(self) -> complex: ...
def get_dagger(self) -> qulacs2023.qulacs_core.PauliOperator: ...
def get_expectation_value(
self, arg: qulacs2023.qulacs_core.StateVector, /
) -> complex: ...
def get_pauli_id_list(self) -> list[int]: ...
def get_pauli_string(self) -> str: ...
def get_qubit_count(self) -> int: ...
def get_target_qubit_list(self) -> list[int]: ...
def get_transition_amplitude(
self,
arg0: qulacs2023.qulacs_core.StateVector,
arg1: qulacs2023.qulacs_core.StateVector,
/,
) -> complex: ...

def RX(arg0: int, arg1: float, /) -> qulacs2023.qulacs_core.Gate: ...

Expand Down
80 changes: 78 additions & 2 deletions python/qulacs2023/qulacs_core.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,43 @@ class InitializationSettings:
self, arg: bool, /
) -> qulacs2023.qulacs_core.InitializationSettings: ...

class Operator:
"""
None
"""

def __init__(self, arg: int, /) -> None: ...
def add_operator(self, arg: qulacs2023.qulacs_core.PauliOperator, /) -> None: ...
def add_random_operator(self, arg0: int, arg1: int, /) -> None:
"""
add_random_operator(self, arg0: int, arg1: int, /) -> None
"""
...

@overload
def add_random_operator(self, operator_count: int = 1) -> None:
"""
add_random_operator(self, operator_count: int = 1) -> None
"""
...

def apply_to_state(self, arg: qulacs2023.qulacs_core.StateVector, /) -> None: ...
def get_dagger(self) -> qulacs2023.qulacs_core.Operator: ...
def get_expectation_value(
self, arg: qulacs2023.qulacs_core.StateVector, /
) -> complex: ...
def get_transition_amplitude(
self,
arg0: qulacs2023.qulacs_core.StateVector,
arg1: qulacs2023.qulacs_core.StateVector,
/,
) -> complex: ...
def is_hermitian(self) -> bool: ...
def n_qubits(self) -> int: ...
def optimize(self) -> None: ...
def terms(self) -> list[qulacs2023.qulacs_core.PauliOperator]: ...
def to_string(self) -> str: ...

def P0(arg: int, /) -> qulacs2023.qulacs_core.Gate: ...

class P0Gate:
Expand Down Expand Up @@ -217,6 +254,22 @@ class PauliOperator:
None
"""

def __init__(
self, bit_flip_mask: int, phase_flip_mask: int, coef: complex = 1.0
) -> None:
"""
__init__(self, bit_flip_mask: int, phase_flip_mask: int, coef: complex = 1.0) -> None
"""
...

@overload
def __init__(self, coef: complex = 1.0) -> None:
"""
__init__(self, coef: complex = 1.0) -> None
"""
...

@overload
def __init__(
self,
target_qubit_list: list[int],
Expand All @@ -229,15 +282,38 @@ class PauliOperator:
...

@overload
def __init__(self, coef: complex = 1.0) -> None:
def __init__(self, pauli_string: str, coef: complex = 1.0) -> None:
"""
__init__(self, coef: complex = 1.0) -> None
__init__(self, pauli_string: str, coef: complex = 1.0) -> None
"""
...

@overload
def __init__(self, pauli_id_par_qubit: list[int], coef: complex = 1.0) -> None:
"""
__init__(self, pauli_id_par_qubit: list[int], coef: complex = 1.0) -> None
"""
...

def add_single_pauli(self, arg0: int, arg1: int, /) -> None: ...
def apply_to_state(self, arg: qulacs2023.qulacs_core.StateVector, /) -> None: ...
def change_coef(self, arg: complex, /) -> None: ...
def get_XZ_mask_representation(self) -> tuple[int, int]: ...
def get_coef(self) -> complex: ...
def get_dagger(self) -> qulacs2023.qulacs_core.PauliOperator: ...
def get_expectation_value(
self, arg: qulacs2023.qulacs_core.StateVector, /
) -> complex: ...
def get_pauli_id_list(self) -> list[int]: ...
def get_pauli_string(self) -> str: ...
def get_qubit_count(self) -> int: ...
def get_target_qubit_list(self) -> list[int]: ...
def get_transition_amplitude(
self,
arg0: qulacs2023.qulacs_core.StateVector,
arg1: qulacs2023.qulacs_core.StateVector,
/,
) -> complex: ...

def RX(arg0: int, arg1: float, /) -> qulacs2023.qulacs_core.Gate: ...

Expand Down
2 changes: 1 addition & 1 deletion qulacs/operator/operator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class Operator {
Operator& operator-=(const PauliOperator& pauli) { return *this += pauli * -1; }
Operator operator-(const PauliOperator& pauli) const { return Operator(*this) -= pauli; }
Operator& operator*=(const PauliOperator& pauli);
Operator operator*(const PauliOperator& pauli) { return Operator(*this) *= pauli; }
Operator operator*(const PauliOperator& pauli) const { return Operator(*this) *= pauli; }

private:
std::vector<PauliOperator> _terms;
Expand Down
8 changes: 8 additions & 0 deletions qulacs/operator/pauli_operator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@ PauliOperator::PauliOperator(const std::vector<UINT>& target_qubit_list,
}
}

PauliOperator::PauliOperator(const std::vector<UINT>& pauli_id_par_qubit, Complex coef)
: _coef(coef) {
for (UINT target_index = 0; target_index < pauli_id_par_qubit.size(); ++target_index) {
UINT pauli_id = pauli_id_par_qubit[target_index];
if (pauli_id != 0) add_single_pauli(target_index, pauli_id);
}
}

PauliOperator::PauliOperator(const BitVector& bit_flip_mask,
const BitVector& phase_flip_mask,
Complex coef)
Expand Down

0 comments on commit 53fb076

Please sign in to comment.