#pragma once #include #include #include #include "factorial.hpp" template using Vector = Eigen::Matrix; template using Matrix = Eigen::Matrix; template using Tensor = Eigen::Tensor; template Tensor initializeJHelper(unsigned N, std::index_sequence) { std::array Ns; std::fill_n(Ns.begin(), p, N); return Tensor(std::get(Ns)...); } template Tensor initializeJ(unsigned N) { return initializeJHelper(N, std::make_index_sequence

()); } template void setJHelper(Tensor& J, const std::array& ind, Scalar val, std::index_sequence) { J(std::get(ind)...) = val; } template void setJ(Tensor& J, std::array ind, Scalar val) { do { setJHelper(J, ind, val, std::make_index_sequence

()); } while (std::next_permutation(ind.begin(), ind.end())); } template Scalar getJHelper(const Tensor& J, const std::array& ind, std::index_sequence) { return J(std::get(ind)...); } template Scalar getJ(const Tensor& J, const std::array& ind) { return getJHelper(J, ind, std::make_index_sequence

()); } template void iterateOverHelper(Tensor& J, std::function&, std::array)>& f, unsigned l, std::array is) { if (l == 0) { f(J, is); } else { unsigned iMin; if (l == p) { iMin = 0; } else { iMin = is[p - l - 1]; } for (unsigned i = iMin; i < J.dimension(p - 1); i++) { std::array js = is; js[p - l] = i; iterateOverHelper(J, f, l - 1, js); } } } template void iterateOver(Tensor& J, std::function&, std::array)>& f) { std::array is; iterateOverHelper(J, f, p, is); } template Tensor generateCouplings(unsigned N, Distribution d, Generator& r) { Tensor J = initializeJ(N); std::function&, std::array)> setRandom = [&d, &r] (Tensor& JJ, std::array ind) { setJ(JJ, ind, d(r)); }; iterateOver(J, setRandom); return J; } template Tensor generateRealPSpinCouplings(unsigned N, Generator& r) { Real σp = sqrt(factorial(p) / ((Real)2 * pow(N, p - 1))); return generateCouplings(N, std::normal_distribution(0, σp), r); } template Tensor contractDown(const Tensor& J, const Vector& z) { return J; } const std::array, 1> ip00 = {Eigen::IndexPair(0, 0)}; template Tensor contractDown(const Tensor& J, const Vector& z) { Tensor zT = Eigen::TensorMap>(z.data(), {z.size()}); Tensor Jz = J.contract(zT, ip00); return contractDown(Jz, z); }