1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
#pragma once
#include <algorithm>
#include <array>
#include <utility>
#include <eigen3/unsupported/Eigen/CXX11/Tensor>
#include "factorial.hpp"
template <class Scalar, unsigned p, std::size_t... Indices>
Eigen::Tensor<Scalar, p> initializeJ(unsigned N, std::index_sequence<Indices...>) {
std::array<unsigned, p> Ns;
std::fill_n(Ns.begin(), p, N);
return Eigen::Tensor<Scalar, p>(std::get<Indices>(Ns)...);
}
template <class Scalar, unsigned p, class Distribution, class Generator, std::size_t... Indices>
void populateCouplings(Eigen::Tensor<Scalar, p>& J, unsigned N, unsigned l,
std::array<unsigned, p> is, Distribution d, Generator& r,
std::index_sequence<Indices...> ii) {
if (l == 0) {
Scalar z = d(r);
do {
J(std::get<Indices>(is)...) = z;
} while (std::next_permutation(is.begin(), is.end()));
} else {
unsigned iMin;
if (l == p) {
iMin = 0;
} else {
iMin = is[p - l - 1];
}
for (unsigned i = iMin; i < N; i++) {
std::array<unsigned, p> js = is;
js[p - l] = i;
populateCouplings<Scalar, p>(J, N, l - 1, js, d, r, ii);
}
}
}
template <class Scalar, unsigned p, class Distribution, class Generator>
Eigen::Tensor<Scalar, p> generateCouplings(unsigned N, Distribution d, Generator& r) {
Eigen::Tensor<Scalar, p> J = initializeJ<Scalar, p>(N, std::make_index_sequence<p>());
std::array<unsigned, p> is;
populateCouplings<Scalar, p>(J, N, p, is, d, r, std::make_index_sequence<p>());
return J;
}
template <class Scalar>
Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>
contractDown(const Eigen::Tensor<Scalar, 2>& J, const Eigen::Matrix<Scalar, Eigen::Dynamic, 1>& z) {
return Eigen::Map<const Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>>(J.data(), z.size(),
z.size());
}
template <class Scalar, int r>
Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>
contractDown(const Eigen::Tensor<Scalar, r>& J, const Eigen::Matrix<Scalar, Eigen::Dynamic, 1>& z) {
Eigen::Tensor<Scalar, 1> zT =
Eigen::TensorMap<Eigen::Tensor<const Scalar, 1>>(z.data(), {z.size()});
std::array<Eigen::IndexPair<int>, 1> ip = {Eigen::IndexPair<int>(0, 0)};
Eigen::Tensor<Scalar, r - 1> Jz = J.contract(zT, ip);
return contractDown(Jz, z);
}
|