Skip to content

Commit

Permalink
implement operators of Operator
Browse files Browse the repository at this point in the history
  • Loading branch information
KowerKoint committed Jan 25, 2024
1 parent e7b08a6 commit 014b0d0
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 20 deletions.
60 changes: 53 additions & 7 deletions qulacs/operator/operator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ Operator::Operator(UINT n_qubits) : _n_qubits(n_qubits) {}

std::string Operator::to_string() const {
std::stringstream ss;
for (auto itr = _operator_list.begin(); itr != _operator_list.end(); ++itr) {
for (auto itr = _terms.begin(); itr != _terms.end(); ++itr) {
ss << itr->get_coef() << " " << itr->get_pauli_string();
if (itr != prev(_operator_list.end())) {
if (itr != prev(_terms.end())) {
ss << " + ";
}
}
Expand All @@ -26,7 +26,7 @@ void Operator::add_operator(PauliOperator&& mpt) {
"Operator::add_operator: target index of pauli_operator is larger than "
"n_qubits");
}
this->_operator_list.emplace_back(std::move(mpt));
this->_terms.emplace_back(std::move(mpt));
}
void Operator::add_random_operator(UINT operator_count) {
for (UINT operator_idx = 0; operator_idx < operator_count; operator_idx++) {
Expand All @@ -39,17 +39,29 @@ void Operator::add_random_operator(UINT operator_count) {
this->add_operator(PauliOperator(target_qubit_list, pauli_id_list, coef));
}
}
void Operator::add_random_operator(UINT operator_count, UINT seed) {
Random random(seed);
for (UINT operator_idx = 0; operator_idx < operator_count; operator_idx++) {
std::vector<UINT> target_qubit_list(_n_qubits), pauli_id_list(_n_qubits);
for (UINT qubit_idx = 0; qubit_idx < _n_qubits; qubit_idx++) {
target_qubit_list[qubit_idx] = qubit_idx;
pauli_id_list[qubit_idx] = random.int32() & 11;
}
Complex coef = random.uniform() * 2. - 1.;
this->add_operator(PauliOperator(target_qubit_list, pauli_id_list, coef));
}
}

Operator Operator::get_dagger() const {
Operator quantum_operator(_n_qubits);
for (const auto& pauli : this->_operator_list) {
for (const auto& pauli : this->_terms) {
quantum_operator.add_operator(pauli.get_dagger());
}
return quantum_operator;
}

void Operator::apply_to_state(StateVector& state_vector) const {
for (const auto& pauli : _operator_list) {
for (const auto& pauli : _terms) {
pauli.apply_to_state(state_vector);
}
}
Expand All @@ -60,7 +72,7 @@ Complex Operator::get_expectation_value(const StateVector& state_vector) const {
"Operator::get_expectation_value: n_qubits of state_vector is too small");
}
Complex res = 0.;
for (const auto& pauli : _operator_list) {
for (const auto& pauli : _terms) {
res += pauli.get_expectation_value(state_vector);
}
return res;
Expand All @@ -78,10 +90,44 @@ Complex Operator::get_transition_amplitude(const StateVector& state_vector_bra,
"small");
}
Complex res;
for (const auto& pauli : _operator_list) {
for (const auto& pauli : _terms) {
res += pauli.get_transition_amplitude(state_vector_bra, state_vector_ket);
}
return res;
}

Operator& Operator::operator*=(Complex coef) {
for (auto& pauli : _terms) pauli *= coef;
return *this;
}
Operator& Operator::operator+=(const Operator& target) {
if (_n_qubits != target._n_qubits) {
throw std::runtime_error("Operator::oeprator+=: n_qubits must be equal");
}
for (const auto& pauli : target._terms) {
add_operator(pauli);
}
return *this;
}
Operator Operator::operator*(const Operator& target) const {
if (_n_qubits != target._n_qubits) {
throw std::runtime_error("Operator::oeprator+=: n_qubits must be equal");
}
Operator ret(_n_qubits);
for (const auto& pauli1 : _terms) {
for (const auto& pauli2 : target._terms) {
ret.add_operator(pauli1 * pauli2);
}
}
return ret;
}
Operator& Operator::operator+=(const PauliOperator& pauli) {
add_operator(pauli);
return *this;
}
Operator& Operator::operator*=(const PauliOperator& pauli) {
for (auto& pauli1 : _terms) pauli1 *= pauli;
return *this;
}

} // namespace qulacs
28 changes: 23 additions & 5 deletions qulacs/operator/operator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,17 @@
namespace qulacs {
class Operator {
public:
Operator(UINT n_qubits);
explicit Operator(UINT n_qubits);

[[nodiscard]] inline bool is_hermitian() { return _is_hermitian; }
[[nodiscard]] inline UINT n_qubits() { return _n_qubits; }
[[nodiscard]] inline const std::vector<PauliOperator>& operator_list() const {
return _operator_list;
}
[[nodiscard]] inline const std::vector<PauliOperator>& terms() const { return _terms; }
[[nodiscard]] std::string to_string() const;

void add_operator(const PauliOperator& mpt);
void add_operator(PauliOperator&& mpt);
void add_random_operator(const UINT operator_count = 1);
void add_random_operator(const UINT operator_count, UINT seed);

[[nodiscard]] Operator get_dagger() const;

Expand All @@ -30,15 +29,34 @@ class Operator {
[[nodiscard]] Complex get_transition_amplitude(const StateVector& state_vector_bra,
const StateVector& state_vector_ket) const;

// not implemented
[[nodiscard]] Complex solve_gound_state_eigenvalue_by_arnoldi_method(const StateVector& state,
UINT iter_count,
Complex mu = 0.) const;
// not implemented
[[nodiscard]] Complex solve_gound_state_eigenvalue_by_power_method(const StateVector& state,
UINT iter_count,
Complex mu = 0.) const;

Operator& operator*=(Complex coef);
Operator operator*(Complex coef) const { return Operator(*this) *= coef; }
inline Operator operator+() const { return *this; }
Operator operator-() const { return *this * -1; }
Operator& operator+=(const Operator& target);
Operator operator+(const Operator& target) const { return Operator(*this) += target; }
Operator& operator-=(const Operator& target) { return *this += -target; }
Operator operator-(const Operator& target) const { return Operator(*this) -= target; }
Operator operator*(const Operator& target) const;
Operator& operator*=(const Operator& target) { return *this = *this * target; }
Operator& operator+=(const PauliOperator& pauli);
Operator operator+(const PauliOperator& pauli) const { return Operator(*this) += pauli; }
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; }

private:
std::vector<PauliOperator> _operator_list;
std::vector<PauliOperator> _terms;
UINT _n_qubits;
bool _is_hermitian;
Random _random;
Expand Down
22 changes: 22 additions & 0 deletions qulacs/util/bit_vector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ class BitVector {

using ConstReference = _Reference<true>;
using Reference = _Reference<false>;

[[nodiscard]] inline ConstReference operator[](int idx) const {
return ConstReference(*this, idx);
}
Expand Down Expand Up @@ -100,6 +101,27 @@ class BitVector {
}
inline BitVector operator-(const BitVector& rhs) const { return BitVector(*this) -= rhs; }

inline auto operator<=>(const BitVector& other) {
UINT sz = std::max(_data.size(), other._data.size());
for (UINT i = sz; i-- != 0;) {
UINT l = i >= _data.size() ? 0ULL : _data[i];
UINT r = i >= other._data.size() ? 0ULL : other._data[i];
if (l < r) return -1;
if (l > r) return 1;
if (i == 0) break;
}
return 0;
}
inline bool operator==(const BitVector& other) {
UINT sz = std::max(_data.size(), other._data.size());
for (UINT i = sz; i-- != 0;) {
UINT l = i >= _data.size() ? 0ULL : _data[i];
UINT r = i >= other._data.size() ? 0ULL : other._data[i];
if (l != r) return false;
}
return true;
}

inline bool empty() const {
return std::ranges::all_of(_data, [](UINT x) { return x == 0; });
}
Expand Down
16 changes: 8 additions & 8 deletions tests/operator/test_pauli_operator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ TEST(PauliOperatorTest, PauliQubitOverflow) {
std::string Pauli_string = "X 0 X 1 X 3";
PauliOperator pauli = PauliOperator(Pauli_string, coef);
StateVector state = StateVector::Haar_random_state(n);
EXPECT_THROW(auto exp = pauli.get_expectation_value(state), std::runtime_error);
EXPECT_THROW((void)pauli.get_expectation_value(state), std::runtime_error);
}

TEST(PauliOperatorTest, BrokenPauliStringA) {
Expand Down Expand Up @@ -78,11 +78,11 @@ struct PauliTestParam {
PauliOperator op2;
PauliOperator expected;

PauliTestParam(const std::string& test_name,
const PauliOperator& op1,
const PauliOperator& op2,
const PauliOperator& expected)
: test_name(test_name), op1(op1), op2(op2), expected(expected) {}
PauliTestParam(const std::string& test_name_,
const PauliOperator& op1_,
const PauliOperator& op2_,
const PauliOperator& expected_)
: test_name(test_name_), op1(op1_), op2(op2_), expected(expected_) {}
};

std::ostream& operator<<(std::ostream& stream, const PauliTestParam& p) {
Expand Down Expand Up @@ -154,12 +154,12 @@ INSTANTIATE_TEST_CASE_P(
PauliOperatorMultiplyTest,
[]() {
double coef = 2.0;
unsigned int MAX_TERM = 100;
UINT MAX_TERM = 100;
std::string pauli_string_x = "";
std::string pauli_string_y = "";
std::string pauli_string_z = "";

for (int i = 0; i < MAX_TERM; i++) {
for (UINT i = 0; i < MAX_TERM; i++) {
pauli_string_x += "X " + std::to_string(i);
pauli_string_y += "Y " + std::to_string(i);
pauli_string_z += "Z " + std::to_string(i);
Expand Down

0 comments on commit 014b0d0

Please sign in to comment.