21#include <initializer_list>
27#include <unordered_map>
28#include <unordered_set>
45 this->verify_symmetry();
56 this->canonicalize_sectors();
64 template <std::ranges::input_range Sectors>
65 requires std::constructible_from<BlockSector, std::ranges::range_reference_t<Sectors>>
68 this->append_sectors(std::forward<Sectors>(
sectors));
69 this->canonicalize_sectors();
78 auto size() const ->
std::
size_t {
return sectors_.size(); }
82 auto empty() const ->
bool {
return sectors_.empty(); }
88 return std::accumulate(sectors_.begin(), sectors_.end(), std::size_t{0},
89 [](std::size_t total,
BlockSector const& sector) { return total + sector.dim; });
97 this->verify_symmetry(q);
98 return std::find_if(sectors_.begin(), sectors_.end(), [&](
BlockSector const& sector) { return sector.q == q; }) !=
113 auto begin()
const {
return sectors_.begin(); }
117 auto end()
const {
return sectors_.end(); }
121 auto label() const ->
std::
string const& {
return label_; }
134 void verify_symmetry()
const
138 throw std::invalid_argument(
"BlockSpace requires a valid symmetry");
144 void verify_symmetry(
QNum const& q)
const
148 throw std::invalid_argument(
"BlockSpace sector has the wrong symmetry");
154 void verify_sector(BlockSector
const& sector)
const
156 this->verify_symmetry(sector.q);
159 throw std::invalid_argument(
"BlockSpace sectors must have positive dimension");
166 template <std::ranges::input_range Sectors>
void append_sectors(Sectors&&
sectors)
170 BlockSector sector(std::forward<
decltype(input)>(input));
171 this->verify_sector(sector);
172 sectors_.push_back(std::move(sector));
177 void canonicalize_sectors()
179 std::sort(sectors_.begin(), sectors_.end(),
180 [](BlockSector
const& lhs, BlockSector
const& rhs) { return lhs.q.raw_code() < rhs.q.raw_code(); });
182 auto const duplicate =
183 std::adjacent_find(sectors_.begin(), sectors_.end(),
184 [](BlockSector
const& lhs, BlockSector
const& rhs) { return lhs.q == rhs.q; });
185 if (duplicate != sectors_.end())
187 throw std::invalid_argument(
"BlockSpace sectors must have unique quantum numbers");
192 std::vector<BlockSector> sectors_;
196static_assert(SymmetrySpace<BlockSpace>);
278template <
typename Range>
inline auto unique_qnums(Range
const& range) -> std::vector<QNum>
280 std::unordered_set<QNum> seen;
281 std::vector<QNum> qnums;
282 for (QNum
const& q : range)
284 if (seen.insert(q).second)
289 std::sort(qnums.begin(), qnums.end(), qnum_code_less);
300 auto const qnums = detail::unique_qnums(list);
302 std::unordered_map<QNum, std::size_t> count_by_q;
303 for (
QNum const& q : list)
308 std::vector<BlockSector> sectors;
309 sectors.reserve(qnums.size());
310 for (
QNum const& q : qnums)
312 sectors.push_back({q, count_by_q[q]});
316 std::unordered_map<QNum, std::size_t> index_by_q;
317 for (std::size_t index = 0; index < regular.
size(); ++index)
319 index_by_q.emplace(regular[index].q, index);
322 std::unordered_map<QNum, std::size_t> offset_by_q;
323 std::vector<std::size_t> block_index;
324 std::vector<std::size_t> block_offset;
325 block_index.reserve(list.size());
326 block_offset.reserve(list.size());
328 for (
QNum const& q : list)
330 block_index.push_back(index_by_q.at(q));
331 block_offset.push_back(offset_by_q[q]);
335 return {list, std::move(regular), std::move(block_index), std::move(block_offset)};
343 auto const qnums = detail::unique_qnums(space);
345 std::unordered_map<QNum, std::size_t> count_by_q;
346 for (
QNum const& q : space)
351 std::vector<BlockSector> sectors;
352 sectors.reserve(qnums.size());
353 for (
QNum const& q : qnums)
355 sectors.push_back({q, count_by_q[q]});
357 BlockSpace regular(space.symmetry(), sectors, space.label());
359 std::unordered_map<QNum, std::size_t> index_by_q;
360 for (std::size_t index = 0; index < regular.
size(); ++index)
362 index_by_q.emplace(regular[index].q, index);
365 std::unordered_map<QNum, std::size_t> offset_by_q;
366 std::vector<std::size_t> block_index;
367 std::vector<std::size_t> block_offset;
368 block_index.reserve(space.size());
369 block_offset.reserve(space.size());
371 for (
QNum const& q : space)
373 block_index.push_back(index_by_q.at(q));
374 block_offset.push_back(offset_by_q[q]);
378 return {space, std::move(regular), std::move(block_index), std::move(block_offset)};
386 std::vector<QNum> original_qnums;
387 original_qnums.reserve(space.size());
390 original_qnums.push_back(sector.q);
392 auto const qnums = detail::unique_qnums(original_qnums);
394 std::unordered_map<QNum, std::size_t> dim_by_q;
397 dim_by_q[sector.q] += sector.dim;
400 std::vector<BlockSector> sectors;
401 sectors.reserve(qnums.size());
402 for (
QNum const& q : qnums)
404 sectors.push_back({q, dim_by_q[q]});
406 BlockSpace regular(space.symmetry(), sectors, space.label());
408 std::unordered_map<QNum, std::size_t> index_by_q;
409 for (std::size_t index = 0; index < regular.
size(); ++index)
411 index_by_q.emplace(regular[index].q, index);
414 std::unordered_map<QNum, std::size_t> offset_by_q;
415 std::vector<BlockRangeMapping> block_mapping;
416 block_mapping.reserve(space.size());
419 auto& offset = offset_by_q[sector.q];
420 block_mapping.push_back({index_by_q.at(sector.q), offset, offset + sector.dim});
421 offset += sector.dim;
424 return {space, std::move(regular), std::move(block_mapping)};
Defines one quantum-number sector and its degeneracy dimension.
Immutable coalesced tensor space represented as unique symmetry blocks.
Definition block_space.hpp:38
auto total_dim() const -> std::size_t
Return the total dimension across all blocks.
Definition block_space.hpp:86
BlockSpace(Symmetry sym, std::string label={})
Construct an empty block space tied to one symmetry.
Definition block_space.hpp:43
BlockSpace(Symmetry sym, std::initializer_list< BlockSector > sectors, std::string label={})
Construct a block space from initial blocks.
Definition block_space.hpp:52
auto contains(QNum q) const -> bool
Return whether a block with the given quantum number exists.
Definition block_space.hpp:95
auto empty() const -> bool
Return whether the block space contains no blocks.
Definition block_space.hpp:82
void set_label(std::string label)
Replace the semantic leg label without changing sector structure.
Definition block_space.hpp:125
auto operator==(BlockSpace const &other) const -> bool=default
Compare two block spaces for exact equality.
auto size() const -> std::size_t
Return the number of stored blocks.
Definition block_space.hpp:78
auto operator[](std::size_t index) const -> BlockSector const &
Return indexed block access.
Definition block_space.hpp:105
auto begin() const
Return an iterator to the first block.
Definition block_space.hpp:113
auto symmetry() const -> Symmetry
Return the symmetry shared by all blocks.
Definition block_space.hpp:74
auto sectors() const -> std::span< BlockSector const >
Return the block list as a read-only span.
Definition block_space.hpp:109
auto label() const -> std::string const &
Return the semantic leg label.
Definition block_space.hpp:121
auto end() const
Return an iterator past the last block.
Definition block_space.hpp:117
BlockSpace(Symmetry sym, Sectors &§ors, std::string label={})
Construct a block space from an input range.
Definition block_space.hpp:66
Ordered block space whose quantum-number sectors may repeat.
Definition irregular_space.hpp:30
Ordered local-state space whose quantum numbers may repeat.
Definition local_space.hpp:28
Explicit sparse tensor space represented as quantum numbers with one shared symmetry.
Definition qnum.hpp:102
One irrep label together with the symmetry context needed to interpret it.
Definition qnum.hpp:29
auto symmetry() const -> Symmetry
Return the symmetry context of this quantum number.
Definition qnum.hpp:51
auto valid() const -> bool
Return whether the quantum number carries a valid symmetry context.
Definition qnum.hpp:47
auto raw_code() const -> std::uint64_t
Return the inline packed irrep code.
Definition qnum.hpp:59
Public handle to a canonicalized direct-product symmetry specification.
Definition symmetry.hpp:24
auto valid() const -> bool
Return whether this handle refers to a valid symmetry.
Definition symmetry.hpp:44
Defines immutable ordered block spaces with repeated sectors.
Defines immutable ordered local-state spaces.
Definition async/async.hpp:26
auto to_block_space(QNumList const &list) -> BlockSpace
Return the coalesced block-space representation of a sparse QNumList.
Definition block_space.hpp:430
auto regularize(QNumList const &list) -> QNumListRegularization
Regularize a sparse QNumList into one block per quantum number.
Definition block_space.hpp:298
std::size_t span
Definition presentation.cpp:2017
Defines packed quantum numbers and same-symmetry quantum-number containers.
Defines the common tensor-space concepts.
Destination range of one irregular block after regularization.
Definition block_space.hpp:232
std::size_t first
First offset occupied by the original block.
Definition block_space.hpp:237
std::size_t block_index
Index of the containing block in the regular BlockSpace.
Definition block_space.hpp:234
auto size() const -> std::size_t
Return the number of mapped degeneracy states.
Definition block_space.hpp:244
std::size_t last
One-past-the-end offset occupied by the original block.
Definition block_space.hpp:240
auto operator==(BlockRangeMapping const &other) const -> bool=default
Compare destination block and range.
One symmetry sector inside a block-structured space.
Definition block_sector.hpp:18
Result of regularizing an ordered segmented IrregularSpace.
Definition block_space.hpp:254
std::vector< BlockRangeMapping > block_mapping
Destination block and range for every original block.
Definition block_space.hpp:262
BlockSpace regular
Canonical space with one block per quantum number.
Definition block_space.hpp:259
IrregularSpace original
Original irregular space.
Definition block_space.hpp:256
Result of regularizing an immutable LocalSpace.
Definition block_space.hpp:216
LocalSpace original
Original ordered local space.
Definition block_space.hpp:218
std::vector< std::size_t > block_offset
For each local state, offset inside the containing block.
Definition block_space.hpp:227
BlockSpace regular
Coalesced block space with one block per quantum number.
Definition block_space.hpp:221
std::vector< std::size_t > block_index
For each local state, index of the containing block in regular.
Definition block_space.hpp:224
Result of regularizing a sparse QNumList into a coalesced BlockSpace.
Definition block_space.hpp:200
QNumList original
Original sparse space.
Definition block_space.hpp:202
BlockSpace regular
Coalesced block space with one block per quantum number.
Definition block_space.hpp:205
std::vector< std::size_t > block_index
For each sparse-space entry, index of the containing block in regular.
Definition block_space.hpp:208
std::vector< std::size_t > block_offset
For each sparse-space entry, offset inside the containing block.
Definition block_space.hpp:211