Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 0 additions & 28 deletions SeQuant/core/algorithm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,34 +138,6 @@ bool next_permutation_parity(int& parity, BidirIt first, BidirIt last,
}
}

///
/// Given a size of a container @c n, returns a range of bitsets. The bitsets
/// represent the sieve that can be used to construct the subsequences of the
/// size-n container.
///
inline auto subset_indices(size_t n) {
using ranges::views::iota;
using ranges::views::transform;
return iota(size_t{1}, size_t(1 << n)) |
transform([n](auto i) { return boost::dynamic_bitset<>(n, i); });
}

///
/// Given an iterable @c it and a bitset @c bs, select the elements in the
/// iterable that correspond to an 'on' bit.
///
template <typename Iterable>
auto subsequence(Iterable const& it, boost::dynamic_bitset<> const& bs) {
using ranges::views::filter;
using ranges::views::iota;
using ranges::views::transform;
using ranges::views::zip;

auto bits = iota(size_t{0}) | transform([&bs](auto i) { return bs.at(i); });
return zip(it, bits) | filter([](auto&& kv) { return std::get<1>(kv); }) |
transform([](auto&& kv) { return std::get<0>(kv); });
}

///
/// All elements in the vector belong to the integral range [-1,N)
/// where N is the length of the [Expr] (ie. the iterable of expressions)
Expand Down
18 changes: 18 additions & 0 deletions SeQuant/core/meta.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <memory>
#include <range/v3/range/access.hpp>
#include <range/v3/range/traits.hpp>
#include <ranges>
#include <type_traits>

namespace sequant {
Expand Down Expand Up @@ -506,6 +507,23 @@ struct std_array_size<std::array<T, N>>
template <typename T>
constexpr inline std::size_t std_array_size_v = std_array_size<T>::value;

///
/// True if @tparam Rng is a range whose value type is convertible
/// to @tparam V .
///
template <typename Rng, typename V>
concept range_of = std::ranges::range<Rng> &&
std::is_convertible_v<std::ranges::range_value_t<Rng>, V>;

///
/// True if @tparam Rng is a range whose value type is convertible
/// to @tparam V and the size (std::ranges::distance) is known in constant time.
///
/// @see https://en.cppreference.com/w/cpp/ranges/sized_range.html
///
template <typename Rng, typename V>
concept sized_range_of = std::ranges::sized_range<Rng> && range_of<Rng, V>;

} // namespace meta
} // namespace sequant

Expand Down
40 changes: 40 additions & 0 deletions SeQuant/core/utility/indices.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,46 @@ auto get_ket_idx(T&& container)
}
}

auto subexpr_index_counts(meta::sized_range_of<Tensor> auto const& tnsrs) {
size_t const N = ranges::distance(tnsrs);
container::vector<container::map<Index, size_t, Index::FullLabelCompare>>
result((1 << N));
for (auto i = 1; i < result.size(); ++i) {
auto bs = boost::dynamic_bitset<>(N, i);
for (auto b = 0; b < N; ++b)
if (bs[b])
for (auto&& ix : ranges::at(tnsrs, b).indices())
if (auto [it, yn] = result[i].try_emplace(ix, 1); !yn) //
++(it->second);
}
return result;
}

template <meta::sized_range_of<Tensor> Rng, meta::range_of<Index> Ixs>
auto subexpr_target_indices(Rng const& tnsrs, Ixs const& tixs) {
using IndexSet = container::set<Index, Index::FullLabelCompare>;
size_t const N = ranges::distance(tnsrs);
container::vector<IndexSet> result((1 << N));

if (result.empty()) return result;

for (auto i = 0; i < N; ++i) {
auto&& ixs = ranges::at(tnsrs, i).indices();
result[(1 << i)] = IndexSet(ranges::begin(ixs), ranges::end(ixs));
}

*result.rbegin() = IndexSet(ranges::begin(tixs), ranges::end(tixs));

auto counts = subexpr_index_counts(tnsrs);

for (auto i = 0; i < result.size(); ++i)
for (auto&& [k, v] : counts[i])
if (v == 1 || (v > 0 && counts.at(counts.size() - i - 1).contains(k)))
result[i].emplace(k);

return result;
}

} // namespace sequant

#endif // SEQUANT_CORE_UTILITY_INDICES_HPP