#pragma once #include #include #include #include #include "factorial.hpp" template void setJ(Scalar z, Eigen::Tensor& J, const std::array& is, std::index_sequence) { J(std::get(is)...) = z; } template Eigen::Tensor initializeJ(unsigned N, std::index_sequence) { std::array Ns; std::fill_n(Ns.begin(), p, N); return Eigen::Tensor(std::get(Ns)...); } template void populateCouplings(Eigen::Tensor& J, unsigned N, unsigned l, std::array is, Distribution d, Generator& r) { if (l == 0) { Scalar z = d(r); do { setJ(z, J, is, std::make_index_sequence

()); } 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 js = is; js[p - l] = i; populateCouplings(J, N, l - 1, js, d, r); } } } template Eigen::Tensor generateCouplings(unsigned N, Distribution d, Generator& r) { Eigen::Tensor J = initializeJ(N, std::make_index_sequence

()); std::array is; populateCouplings(J, N, p, is, d, r); return J; } template Eigen::Matrix contractDown(const Eigen::Tensor& J, const Eigen::Matrix& z) { return Eigen::Map>(J.data(), z.size(), z.size()); } template Eigen::Matrix contractDown(const Eigen::Tensor& J, const Eigen::Matrix& z) { Eigen::Tensor zT = Eigen::TensorMap>(z.data(), {z.size()}); std::array, 1> ip = {Eigen::IndexPair(0, 0)}; Eigen::Tensor Jz = J.contract(zT, ip); return contractDown(Jz, z); }