Program Listing for File any.hpp¶
↰ Return to documentation for file (SeQuant/core/irreps/any.hpp)
#ifndef SEQUANT_CORE_IRREPS_ANY_HPP
#define SEQUANT_CORE_IRREPS_ANY_HPP
#include <SeQuant/core/irreps/algebra.hpp>
#include <SeQuant/core/irreps/propagation.hpp>
#include <SeQuant/core/utility/exception.hpp>
#include <concepts>
#include <functional>
#include <memory>
#include <string>
#include <string_view>
#include <type_traits>
#include <utility>
namespace sequant {
class Tensor;
class Variable;
class AnyIrrep {
public:
template <typename Irrep>
requires(!std::same_as<std::remove_cvref_t<Irrep>, AnyIrrep>)
explicit AnyIrrep(Irrep irrep)
: m_impl(std::make_unique<Model<std::remove_cvref_t<Irrep>>>(
std::move(irrep))) {}
AnyIrrep(const AnyIrrep &other);
AnyIrrep(AnyIrrep &&other) noexcept;
AnyIrrep &operator=(const AnyIrrep &other);
AnyIrrep &operator=(AnyIrrep &&other) noexcept;
~AnyIrrep();
[[nodiscard]] std::string to_string() const;
template <typename Irrep>
[[nodiscard]] const Irrep *as() const {
const auto *model = dynamic_cast<const Model<Irrep> *>(m_impl.get());
return model ? &model->value : nullptr;
}
friend bool operator==(const AnyIrrep &lhs, const AnyIrrep &rhs);
private:
struct Concept {
virtual ~Concept() = default;
virtual std::unique_ptr<Concept> clone() const = 0;
virtual std::string to_string() const = 0;
virtual bool equals(const Concept &other) const = 0;
};
template <typename Irrep>
struct Model final : Concept {
explicit Model(Irrep value) : value(std::move(value)) {}
std::unique_ptr<Concept> clone() const override {
return std::make_unique<Model>(value);
}
std::string to_string() const override { return irrep_to_string(value); }
bool equals(const Concept &other) const override {
const auto *model = dynamic_cast<const Model *>(&other);
return model && model->value == value;
}
Irrep value;
};
std::unique_ptr<Concept> m_impl;
};
class AnyIrrepSet {
public:
AnyIrrepSet();
template <typename Irrep>
AnyIrrepSet(IrrepSet<Irrep> set)
: m_impl(std::make_unique<Model<Irrep>>(std::move(set))) {}
AnyIrrepSet(const AnyIrrepSet &other);
AnyIrrepSet(AnyIrrepSet &&other) noexcept;
AnyIrrepSet &operator=(const AnyIrrepSet &other);
AnyIrrepSet &operator=(AnyIrrepSet &&other) noexcept;
~AnyIrrepSet();
[[nodiscard]] bool is_any() const;
[[nodiscard]] bool empty() const;
[[nodiscard]] std::size_t size() const;
AnyIrrepSet &unite(const AnyIrrepSet &other);
[[nodiscard]] std::string to_string() const;
void for_each(const std::function<void(const AnyIrrep &)> &f) const;
template <typename Irrep>
[[nodiscard]] const IrrepSet<Irrep> *as() const {
const auto *model = dynamic_cast<const Model<Irrep> *>(m_impl.get());
return model ? &model->set : nullptr;
}
friend bool operator==(const AnyIrrepSet &lhs, const AnyIrrepSet &rhs);
private:
struct Concept {
virtual ~Concept() = default;
virtual std::unique_ptr<Concept> clone() const = 0;
virtual bool is_any() const = 0;
virtual bool empty() const = 0;
virtual std::size_t size() const = 0;
virtual std::string to_string() const = 0;
virtual bool equals(const Concept &other) const = 0;
virtual bool unite(const Concept &other) = 0;
virtual void for_each(
const std::function<void(const AnyIrrep &)> &f) const = 0;
};
template <typename Irrep>
struct Model final : Concept {
explicit Model(IrrepSet<Irrep> set) : set(std::move(set)) {}
std::unique_ptr<Concept> clone() const override {
return std::make_unique<Model>(set);
}
bool is_any() const override { return set.is_any(); }
bool empty() const override { return set.empty(); }
std::size_t size() const override { return set.size(); }
std::string to_string() const override { return sequant::to_string(set); }
bool equals(const Concept &other) const override {
const auto *model = dynamic_cast<const Model *>(&other);
return model && model->set == set;
}
bool unite(const Concept &other) override {
const auto *model = dynamic_cast<const Model *>(&other);
if (!model) {
return false;
}
set.unite(model->set);
return true;
}
void for_each(
const std::function<void(const AnyIrrep &)> &f) const override {
for (const Irrep ¤t : set) {
f(AnyIrrep(current));
}
}
IrrepSet<Irrep> set;
};
std::unique_ptr<Concept> m_impl;
};
class AnyIrrepContext {
public:
using set_type = AnyIrrepSet;
template <IrrepAlgebra A>
AnyIrrepContext(IrrepContext<A> ctx)
: m_impl(std::make_unique<Model<A>>(std::move(ctx))) {}
AnyIrrepContext(const AnyIrrepContext &other);
AnyIrrepContext(AnyIrrepContext &&other) noexcept;
AnyIrrepContext &operator=(const AnyIrrepContext &other);
AnyIrrepContext &operator=(AnyIrrepContext &&other) noexcept;
~AnyIrrepContext();
[[nodiscard]] AnyIrrepSet irreps_of(const Tensor &tensor) const;
[[nodiscard]] AnyIrrepSet irreps_of(const Variable &variable) const;
[[nodiscard]] AnyIrrepSet totally_symmetric() const;
[[nodiscard]] bool is_totally_symmetric(const AnyIrrepSet &set) const;
[[nodiscard]] AnyIrrepSet empty_set() const;
[[nodiscard]] AnyIrrepSet any_set() const;
[[nodiscard]] AnyIrrep canonical_irrep(std::string_view name) const;
[[nodiscard]] AnyIrrepSet product(const AnyIrrepSet &lhs,
const AnyIrrepSet &rhs) const;
[[nodiscard]] AnyIrrepSet conjugate(const AnyIrrepSet &set) const;
template <IrrepAlgebra A>
[[nodiscard]] const IrrepContext<A> *as() const {
const auto *model = dynamic_cast<const Model<A> *>(m_impl.get());
return model ? &model->ctx : nullptr;
}
private:
struct Concept {
virtual ~Concept() = default;
virtual std::unique_ptr<Concept> clone() const = 0;
virtual AnyIrrepSet irreps_of(const Tensor &tensor) const = 0;
virtual AnyIrrepSet irreps_of(const Variable &variable) const = 0;
virtual AnyIrrepSet totally_symmetric() const = 0;
virtual bool is_totally_symmetric(const AnyIrrepSet &set) const = 0;
virtual AnyIrrepSet empty_set() const = 0;
virtual AnyIrrepSet any_set() const = 0;
virtual AnyIrrep canonical_irrep(std::string_view name) const = 0;
virtual AnyIrrepSet product(const AnyIrrepSet &lhs,
const AnyIrrepSet &rhs) const = 0;
virtual AnyIrrepSet conjugate(const AnyIrrepSet &set) const = 0;
};
template <IrrepAlgebra A>
struct Model final : Concept {
using Set = typename IrrepContext<A>::set_type;
using Irrep = typename IrrepContext<A>::irrep_type;
explicit Model(IrrepContext<A> ctx) : ctx(std::move(ctx)) {}
std::unique_ptr<Concept> clone() const override {
return std::make_unique<Model>(ctx);
}
AnyIrrepSet irreps_of(const Tensor &tensor) const override {
return ctx.irreps_of(tensor);
}
AnyIrrepSet irreps_of(const Variable &variable) const override {
return ctx.irreps_of(variable);
}
AnyIrrepSet totally_symmetric() const override {
return ctx.totally_symmetric();
}
bool is_totally_symmetric(const AnyIrrepSet &set) const override {
return ctx.is_totally_symmetric(typed(set));
}
AnyIrrepSet empty_set() const override { return ctx.empty_set(); }
AnyIrrepSet any_set() const override { return ctx.any_set(); }
AnyIrrep canonical_irrep(std::string_view name) const override {
return AnyIrrep(ctx.canonical_irrep(name));
}
AnyIrrepSet product(const AnyIrrepSet &lhs,
const AnyIrrepSet &rhs) const override {
return ctx.product(typed(lhs), typed(rhs));
}
AnyIrrepSet conjugate(const AnyIrrepSet &set) const override {
return ctx.conjugate(typed(set));
}
static Set typed(const AnyIrrepSet &set) {
if (const Set *typed_set = set.as<Irrep>()) {
return *typed_set;
}
if (set.empty()) {
// Empty set of yet-unknown type
return {};
}
throw Exception("IRREP set " + set.to_string() +
" is of a type incompatible with the IRREP context");
}
IrrepContext<A> ctx;
};
std::unique_ptr<Concept> m_impl;
};
static_assert(IrrepPropagationContext<AnyIrrepContext>);
} // namespace sequant
#endif // SEQUANT_CORE_IRREPS_ANY_HPP