50namespace triqs::operators {
58 using utility::real_or_complex;
121 auto compare_indices = [](
indices_t const &a,
indices_t const &b) -> std::strong_ordering {
122 for (
size_t i = 0; i < std::min(a.size(), b.size()); ++i) {
124 if (a[i].index() != b[i].index())
return a[i].index() <=> b[i].index();
126 auto cmp = std::visit(
127 [](
auto const &x,
auto const &y) -> std::strong_ordering {
128 if constexpr (std::is_same_v<std::decay_t<
decltype(x)>, std::decay_t<
decltype(y)>>) {
129 if (x == y)
return std::strong_ordering::equal;
130 return x < y ? std::strong_ordering::less : std::strong_ordering::greater;
132 return std::strong_ordering::equal;
135 if (cmp != std::strong_ordering::equal)
return cmp;
137 return a.size() <=> b.size();
171 std::ostream &
operator<<(std::ostream &os, canonical_ops_t
const &op);
251 static_assert(std::is_constructible_v<scalar_t, S>);
262 if (!
is_zero(x)) monomials_.insert({{}, x});
273 if (!
is_zero(x)) monomials_.emplace(std::move(monomial), x);
290 static_assert(std::is_constructible_v<scalar_t, S>);
307 for (
auto const &m : monomials_)
308 for (
auto const &c_cdag_op : m.first) fops.insert_from_indices_t(c_cdag_op.indices);
323 res.monomials_.insert({m,
scalar_t(1)});
329 struct C2PY_IGNORE _cdress {
332 _cdress(
typename monomials_map_t::const_iterator _it) : monomial(_it->first), coef(_it->second) {}
333 operator std::pair<std::vector<std::pair<bool, indices_t>>, scalar_t>()
const {
334 std::vector<std::pair<bool, indices_t>> tmp_monomial;
335 tmp_monomial.reserve(monomial.size());
336 for (
auto cop : monomial) tmp_monomial.emplace_back(cop.dagger, cop.indices);
337 return {tmp_monomial, coef};
363 auto term_is_zero = [precision](
auto const &term) {
367 return std::all_of(this->
begin(), this->
end(), term_is_zero);
374 [[nodiscard]]
bool is_zero()
const {
return monomials_.empty(); }
382 for (
auto &m : res.monomials_) m.second = -m.second;
399 bool is_new_monomial{};
400 typename monomials_map_t::iterator it;
401 std::tie(it, is_new_monomial) = monomials_.insert(std::make_pair(
monomial_t(0), a));
402 if (!is_new_monomial) {
404 erase_zero_monomial(monomials_, it);
435 for (
auto &m : monomials_) m.second *= a;
528 bool is_new_monomial{};
529 typename monomials_map_t::iterator it;
530 for (
auto const &m : op.monomials_) {
531 std::tie(it, is_new_monomial) = monomials_.insert(m);
532 if (!is_new_monomial) {
533 it->second += m.second;
534 erase_zero_monomial(monomials_, it);
552 bool is_new_monomial{};
553 typename monomials_map_t::iterator it;
554 for (
auto const &m : op.monomials_) {
555 std::tie(it, is_new_monomial) = monomials_.insert(std::make_pair(m.first, -m.second));
556 if (!is_new_monomial) {
557 it->second -= m.second;
558 erase_zero_monomial(monomials_, it);
582 for (
auto const &m : monomials_)
583 for (
auto const &op_m : op.monomials_) {
585 product_m.reserve(m.first.size() + op_m.first.size());
586 for (
auto const &tmp_op : m.first) product_m.push_back(tmp_op);
587 for (
auto const &tmp_op : op_m.first) product_m.push_back(tmp_op);
588 normalize_and_insert(product_m, m.second * op_m.second, tmp_map);
590 std::swap(monomials_, tmp_map);
637 for (
auto it = m.rbegin(); it != m.rend(); ++it) res.push_back(_dagger(*it));
654 for (
auto const &x : op) res.monomials_.insert({_dagger(x.monomial), conj(x.coef)});
676 for (
auto const &x : op) {
677 auto c = f(x.monomial, x.coef);
678 if (!
is_zero(
c)) res.monomials_.insert({x.monomial,
c});
697 if (op.monomials_.size() != 0) {
698 bool print_plus =
false;
699 for (
auto const &m : op.monomials_) {
700 os << (print_plus ?
" + " :
"") << m.second;
722 [[nodiscard]]
static std::string
hdf5_format() {
return "Operator"; }
770 h5_read(g, name, op_real_cplx, fops);
771 op = std::move(op_real_cplx);
785 for (
int n = 1;
n < m.size(); ++
n) {
786 canonical_ops_t &prev_index = m[
n - 1];
787 canonical_ops_t &cur_index = m[
n];
788 if (prev_index == cur_index)
return;
789 if (prev_index > cur_index) {
792 canonical_ops_t cur_index_flipped_type(cur_index);
793 cur_index_flipped_type.dagger = !cur_index_flipped_type.dagger;
794 if (prev_index == cur_index_flipped_type) {
796 new_m.reserve(m.size() - 2);
797 std::copy(m.begin(), m.begin() +
n - 1, std::back_inserter(new_m));
798 std::copy(m.begin() +
n + 1, m.end(), std::back_inserter(new_m));
799 normalize_and_insert(new_m, coeff, target);
802 std::swap(prev_index, cur_index);
806 }
while (is_swapped);
810 bool is_new_monomial{};
811 typename monomials_map_t::iterator it;
812 std::tie(it, is_new_monomial) = target.insert(std::make_pair(std::move(m), coeff));
813 if (!is_new_monomial) {
815 erase_zero_monomial(target, it);
820 static void erase_zero_monomial(
monomials_map_t &m,
typename monomials_map_t::iterator &it) {
822 if (
is_zero(it->second)) m.erase(it);
841 template <
typename T1,
typename T2>
843 if (!(op1 - op2).is_almost_zero(precision))
TRIQS_RUNTIME_ERROR <<
"Error in operators::assert_operators_are_close: Terms are different";
857 return transform(op, [](
monomial_t const &, T a_i) {
874 return transform(op, [](
monomial_t const &, T a_i) {
936template <>
struct std::hash<triqs::operators::canonical_ops_t> {
938 std::size_t h = std::hash<bool>{}(
c.dagger);
939 for (
auto const &idx :
c.indices) {
940 std::visit(triqs::utility::overloaded{[&](std::array<long, 3>
const &a) {
941 for (
long x : a) h += std::hash<long>{}(x);
943 [&](
auto const &v) { h += std::hash<std::decay_t<
decltype(v)>>{}(v); }},
const_view_type operator()() const
Make a const view of *this.
Class representing a fundamental operator set.
triqs::hilbert_space::indices_t indices_t
Index type to represent a single .
Generic many-body operator.
many_body_operator_generic operator-() const
Unary minus operator to negate the current many-body operator .
many_body_operator_generic(scalar_t const &x)
Construct a many-body operator .
friend many_body_operator_generic operator*(many_body_operator_generic lhs, many_body_operator_generic const &rhs)
Product of two many-body operators and (Fock-space operator product).
friend void h5_read(h5::group g, std::string const &name, many_body_operator &op, hilbert_space::fundamental_operator_set &fops)
Read a triqs::operators::many_body_operator together with a triqs::hilbert_space::fundamental_operato...
void deserialize(auto &ar)
Deserialize the many-body operator from a generic archive.
hilbert_space::fundamental_operator_set make_fundamental_operator_set() const
Create a minimal fundamental operator set with all single particle state indices that appear in the ...
friend many_body_operator_generic operator-(many_body_operator_generic op, scalar_t a)
Subtract a scalar from a many-body operator .
many_body_operator_generic(scalar_t const &x, monomial_t monomial)
Construct a many-body operator .
friend many_body_operator_generic operator-(scalar_t a, many_body_operator_generic const &op)
Subtract a many-body operator from a scalar .
many_body_operator_generic & operator-=(many_body_operator_generic const &op)
Subtraction assignment operator to subtract the many-body operator from the current many-body operat...
many_body_operator_generic(many_body_operator_generic< S > const &p)
Construct a many-body operator from another many-body operator with a different coefficient type.
const_iterator end() const noexcept
Get a const iterator past the end of the map that contains the monomials and their coefficients.
friend std::ostream & operator<<(std::ostream &os, many_body_operator_generic const &op)
Write a triqs::operators::many_body_operator_generic to a std::ostream.
bool operator==(many_body_operator_generic const &op) const
Equality operator to compare two many-body operators.
many_body_operator_generic & operator/=(scalar_t a)
Division assignment operator to divide the current many-body operator by a scalar .
friend void h5_write(h5::group g, std::string const &name, many_body_operator_generic const &op)
Write a triqs::operators::many_body_operator_generic to HDF5.
many_body_operator_generic imag() const
many_body_operator_generic()=default
Default constructor creates a zero many-body operator, i.e. with no terms.
friend many_body_operator_generic dagger(many_body_operator_generic const &op)
Compute the Hermitian conjugate (dagger) of the many-body operator .
many_body_operator_generic & operator+=(many_body_operator_generic const &op)
Addition assignment operator to add the many-body operator to the current many-body operator .
friend many_body_operator_generic operator+(many_body_operator_generic lhs, many_body_operator_generic const &rhs)
Sum of two many-body operators and .
bool is_almost_zero(double precision=1e-10) const
Check if the current operator is close to zero.
friend many_body_operator_generic operator+(scalar_t a, many_body_operator_generic op)
Add a many-body operator to a scalar .
many_body_operator_generic & operator+=(scalar_t a)
Addition assignment operator to add a scalar to the current many-body operator .
friend many_body_operator_generic transform(many_body_operator_generic const &op, F &&f)
Transform the coefficients of an operator using a callable object.
many_body_operator_generic & operator=(many_body_operator_generic< S > const &p)
Assignment operator from a many-body operator with a different coefficient type.
const_iterator cend() const noexcept
Get a const iterator past the end of the map that contains the monomials and their coefficients.
const_iterator cbegin() const noexcept
Get a const iterator to the beginning of the map that contains the monomials and their coefficients.
static many_body_operator_generic make_canonical(bool is_dag, indices_t indices)
Create a many-body operator that represents a single canonical operator or .
friend many_body_operator_generic operator/(many_body_operator_generic op, scalar_t a)
Divide a many-body operator by a scalar .
many_body_operator_generic real() const
void serialize(auto &ar) const
Serialize the many-body operator to a generic archive.
friend many_body_operator_generic operator*(scalar_t a, many_body_operator_generic op)
Multiply a many-body operator by a scalar on the left.
std::map< monomial_t, scalar_t > monomials_map_t
friend void h5_read(h5::group g, std::string const &name, many_body_operator_generic &op)
Read a triqs::operators::many_body_operator_generic from HDF5.
many_body_operator_generic & operator*=(scalar_t a)
Multiplication assignment operator to multiply the current many-body operator by a scalar .
many_body_operator_generic & operator-=(scalar_t a)
Subtraction assignment operator to subtract a scalar from the current many-body operator .
utility::dressed_iterator< typename monomials_map_t::const_iterator, _cdress > const_iterator
const_iterator begin() const noexcept
Get a const iterator to the beginning of the map that contains the monomials and their coefficients.
static std::string hdf5_format()
HDF5 format tag of the many-body operator.
bool is_zero() const
Check if the current operator is exactly zero.
friend void h5_write(h5::group g, std::string const &name, many_body_operator const &op, hilbert_space::fundamental_operator_set const &fops)
Write a triqs::operators::many_body_operator together with a triqs::hilbert_space::fundamental_operat...
friend many_body_operator_generic operator+(many_body_operator_generic op, scalar_t a)
Add a scalar to a many-body operator .
friend many_body_operator_generic operator-(many_body_operator_generic lhs, many_body_operator_generic const &rhs)
Difference of two many-body operators and .
friend many_body_operator_generic operator*(many_body_operator_generic op, scalar_t a)
Multiply a many-body operator by a scalar on the right.
monomials_map_t const & get_monomials() const
Get the map/dictionary of monomials and their coefficients.
many_body_operator_generic & operator*=(many_body_operator_generic const &op)
Multiplication assignment operator to multiply the current many-body operator by another many-body o...
Type that can represent either a real or a complex number.
STL-compatible iterator wrapper that dresses an underlying iterator with a user-defined view type.
many_body_operator_generic< T > real(many_body_operator_generic< T > const &op)
Get a copy of the given operator with the imaginary parts of all monomial coefficients set to zero.
many_body_operator_generic< T > n(IndexTypes... indices)
Create a number operator .
many_body_operator_generic< double > many_body_operator_real
Many-body operator with real coefficients (see triqs::operators::many_body_operator_generic).
void assert_operators_are_close(many_body_operator_generic< T1 > const &op1, many_body_operator_generic< T2 > const &op2, double precision)
Assert that two many-body operators are close to each other within a given precision.
bool is_op_hermitian(many_body_operator_generic< T > const &op, double tolerance=0.0)
Check if a many-body operator is Hermitian within a given precision.
many_body_operator_generic< real_or_complex > many_body_operator
Many-body operator with real or complex coefficients (see triqs::operators::many_body_operator_generi...
std::vector< canonical_ops_t > monomial_t
Type used to represent a monomial of canonical second quantization operators.
many_body_operator_generic< std::complex< double > > many_body_operator_complex
Many-body operator with complex coefficients (see triqs::operators::many_body_operator_generic).
many_body_operator_generic< T > imag(many_body_operator_generic< T > const &op)
Get a copy of the given operator with the real parts of all monomial coefficients set to zero.
bool operator<(monomial_t const &m1, monomial_t const &m2)
Less-than comparison operator for triqs::operators::monomial_t.
many_body_operator_generic< T > c_dag(IndexTypes... indices)
Create a creation operator .
many_body_operator_generic< T > c(IndexTypes... indices)
Create an annihilation operator .
std::ostream & operator<<(std::ostream &sout, canonical_ops_t const &op)
Write a triqs::operators::canonical_ops_t to a std::ostream.
hilbert_space::fundamental_operator_set::indices_t indices_t
Elevate triqs::hilbert_space::indices_t to the triqs::operators namespace.
#define TRIQS_RUNTIME_ERROR
Throw a triqs::runtime_error with the current source location.
I real(I const &x)
Real part of an integral value.
I imag(I const &x)
Imaginary part of an integral value.
I conj(I const &x)
Complex conjugate of an integral value.
bool is_zero(I const &x)
Exact zero check for integral values.
Provides a fundamental operator set class.
Numeric helpers overloaded for various types.
Second quantization creation/annihilation operator.
indices_t indices
Single particle state index .
void deserialize(auto &ar)
Deserialize the canonical operator from a generic archive.
auto operator<=>(canonical_ops_t const &b) const
Three-way comparison operator for canonical operators.
void serialize(auto &ar) const
Serialize the canonical operator to a generic archive.
bool dagger
True for creation ( ), false for annihilation ( ) operators.
bool operator==(canonical_ops_t const &b) const
Equality operator for canonical operators.
STL-compatible iterator that wraps an underlying iterator and dereferences to a user-supplied dressin...
Provides a type that decides at runtime whether it is real or complex.
Small helpers for working with std::variant types.