16 template <
typename IntIterator>
17 void right_partition(IntIterator begin, IntIterator end, IntIterator all_begin,
49 template <
typename IntIterator>
50 void left_partition(IntIterator begin, IntIterator end, IntIterator all_begin,
54 const auto k = end - begin;
55 const auto n = *(end - 1);
62 auto& rightmost = *(end - 1);
63 auto& leftmost = *(end - 2);
65 const size_t rightmost_index = (end - 1) - all_begin;
66 const size_t leftmost_index = (end - 2) - all_begin;
68 while (rightmost > 0) {
71 change_indices.emplace_back(rightmost_index, leftmost_index);
75 auto& rightmost = *(end - 1);
76 auto& leftmost = *begin;
77 auto& leftmost_next = *(begin + 1);
79 const size_t rightmost_index = (end - 1) - all_begin;
80 const size_t leftmost_index = begin - all_begin;
81 const size_t leftmost_next_index = (begin + 1) - all_begin;
84 left_partition(begin + 1, end, all_begin, all_end, change_indices);
87 change_indices.emplace_back(leftmost_next_index, leftmost_index);
96 change_indices.emplace_back(rightmost_index, leftmost_index);
133 template <
typename IntIterator>
138 const auto k = end - begin;
139 const auto n = *begin;
145 auto& leftmost = *begin;
146 auto& rightmost = *(begin + 1);
148 const size_t leftmost_index = begin - all_begin;
149 const size_t rightmost_index = (begin + 1) - all_begin;
151 while (leftmost > 0) {
154 change_indices.emplace_back(leftmost_index, rightmost_index);
158 auto& leftmost = *begin;
159 auto& rightmost = *(end - 1);
160 auto& rightmost_prev = *(end - 2);
162 const size_t leftmost_index = begin - all_begin;
163 const size_t rightmost_index = (end - 1) - all_begin;
164 const size_t rightmost_prev_index = (end - 2) - all_begin;
170 change_indices.emplace_back(rightmost_prev_index, rightmost_index);
172 if (rightmost == n) {
176 left_partition(begin, end - 1, all_begin, all_end, change_indices);
179 change_indices.emplace_back(leftmost_index, rightmost_index);
181 if (rightmost == n) {
218 template <
typename Function,
typename Tuple,
size_t... I>
219 auto call(Function f, Tuple t, std::index_sequence<I...> seq) {
220 return f(std::get<I>(t)...);
244 template <
typename Function,
typename Tuple>
auto call(Function f, Tuple t) {
245 static constexpr
auto size = std::tuple_size<Tuple>::value;
246 return call(f, t, std::make_index_sequence<size>{});
272 auto x =
static_cast<size_t>(S.dimension(0));
273 auto y =
static_cast<size_t>(S.dimension(1));
274 auto z =
static_cast<size_t>(S.dimension(2));
276 T sum = 0, squared_sum = 0;
277 #pragma omp parallel for schedule(static) reduction(+:sum,squared_sum) 278 for (
size_t i = 0; i < x; ++i) {
279 for (
size_t j = 0; j < y; ++j) {
280 for (
size_t k = 0; k < z; ++k) {
282 squared_sum += S(i, j, k) * S(i, j, k);
291 double frob_norm =
std::sqrt(squared_sum);
294 return (axis_mult - sum / frob_norm) / (axis_mult - 1);
320 template <
typename Scalar,
int N>
322 NormType type = NormType::L1,
double eps = 1e-50) {
323 static_assert(N >= 1,
"Tensor must be at least 1 dimensional");
324 BNMF_ASSERT(axis < N,
"Normalization axis must be less than N");
327 auto input_dims = input.dimensions();
328 Eigen::array<long, N - 1> output_dims;
329 for (
size_t i = 0, j = 0; i < N; ++i) {
331 output_dims[j] = input_dims[i];
339 Eigen::ThreadPoolDevice thread_dev(&tp,
344 tensor_t<Scalar, N - 1> norms(output_dims);
349 norms.device(thread_dev) = input.abs().sum(reduction_dim);
351 norms = input.abs().sum(reduction_dim);
356 norms.device(thread_dev) = input.square().sum(reduction_dim);
358 norms = input.square().sum(reduction_dim);
363 norms.device(thread_dev) = input.abs().maximum(reduction_dim);
365 norms = input.abs().maximum(reduction_dim);
371 Scalar* norms_begin = norms.data();
372 #pragma omp parallel for schedule(static) 373 for (
long i = 0; i < norms.size(); ++i) {
374 norms_begin[i] += eps;
378 int axis_dims = input.dimensions()[axis];
379 #pragma omp parallel for schedule(static) 380 for (
int i = 0; i < axis_dims; ++i) {
381 input.chip(i, axis) /= norms;
397 template <
typename Scalar,
int N>
400 double eps = 1e-50) {
446 const Real a = x + 1;
447 const Real b = x + 2;
448 const Real c = x + 3;
449 const Real d = x + 4;
450 const Real e = x + 5;
451 const Real ab = a * b;
452 const Real cd = c * d;
453 const Real ex = e * x;
455 extra = ((a + b) * cd * ex + ab * d * ex + ab * c * ex + ab * cd * x +
460 const Real a = x + 1;
461 const Real b = x + 2;
462 const Real c = x + 3;
463 const Real d = x + 4;
464 const Real ab = a * b;
465 const Real cd = c * d;
466 const Real dx = d * x;
469 ((a + b) * c * dx + ab * dx + ab * c * x + ab * cd) / (ab * cd * x);
472 const Real a = x + 1;
473 const Real b = x + 2;
474 const Real c = x + 3;
475 const Real ab = a * b;
476 const Real cx = c * x;
478 extra = ((a + b) * cx + (c + x) * ab) / (ab * cx);
481 const Real a = x + 1;
482 const Real b = x + 2;
483 const Real ab = a * b;
485 extra = ((a + b) * x + ab) / (ab * x);
488 const Real a = x + 1;
490 extra = (a + x) / (a * x);
509 std::log(x) + (-360360 * x13 - 60060 * x12 + 6006 * x10 - 2860 * x8 +
510 3003 * x6 - 5460 * x4 + 15202 * x2 - 60060) /
559 template <
typename Integer>
562 BNMF_ASSERT(k > 0,
"k must be greater than 0 in util::all_partitions");
563 BNMF_ASSERT(n > 0,
"n must be greater than 0 in util::all_partitions");
611 template <
typename Integer>
621 size_t decr_idx, incr_idx;
622 for (
const auto& change_idx : part_change_vec) {
623 std::tie(decr_idx, incr_idx) = change_idx;
624 --partition[decr_idx];
625 ++partition[incr_idx];
void right_partition(IntIterator begin, IntIterator end, IntIterator all_begin, IntIterator all_end, std::vector< std::pair< size_t, size_t >> &change_indices)
Partition the number stored at the beginning of the given sequence towards the end of the sequence by...
Definition: util.hpp:134
Eigen::Tensor< Scalar, N, Eigen::RowMajor > tensor_t
Tensor type used in the computations.
Definition: defs.hpp:52
NormType
Type of the norm to be used by bnmf_algs::util::normalize and bnmf_algs::util::normalized.
Definition: util.hpp:301
T hardware_concurrency(T...args)
Eigen::array< size_t, N > shape
Shape of vectors, matrices, tensors, etc.
Definition: defs.hpp:66
void normalize(tensor_t< Scalar, N > &input, size_t axis, NormType type=NormType::L1, double eps=1e-50)
Normalize a tensor in-place along the given axis.
Definition: util.hpp:321
double sparseness(const tensor_t< T, 3 > &S)
Compute the sparseness of the given 3D tensor.
Definition: util.hpp:270
Real psi_appr(Real x)
Calculate digamma function approximately using the first 8 terms of the asymptotic expansion of digam...
Definition: util.hpp:440
void left_partition(IntIterator begin, IntIterator end, IntIterator all_begin, IntIterator all_end, std::vector< std::pair< size_t, size_t >> &change_indices)
Partition the number stored at the end of the given sequence towards the beginning of the sequence by...
Definition: util.hpp:50
auto call(Function f, Tuple t)
Forward the elements of a tuple to a function and return the result.
Definition: util.hpp:244
std::vector< std::vector< Integer > > all_partitions(Integer n, Integer k)
Compute all possible k length partitions of given number n.
Definition: util.hpp:612
std::vector< std::pair< size_t, size_t > > partition_change_indices(Integer n, Integer k)
Compute the sequence of indices to be incremented and decremented to generate all partitions of numbe...
Definition: util.hpp:560
Main namespace for bnmf-algs library.
Definition: alloc_model_funcs.hpp:12
tensor_t< Scalar, N > normalized(const tensor_t< Scalar, N > &input, size_t axis, NormType type=NormType::L1, double eps=1e-50)
Return a normalized copy of a tensor along the given axis.
Definition: util.hpp:398