7 #include <3rd-party/effolkronium/random.hpp>
12 template<
typename Scalar>
19 return effolkronium::random_static::get(
d_);
22 mutable std::normal_distribution<Scalar>
d_;
30 inline auto randnVec(Eigen::Index size,
double mean = 0,
double stddev = 1)
41 inline auto randnMat(Eigen::Index rows, Eigen::Index cols,
double mean = 0,
double stddev = 1)
62 inline Eigen::MatrixXd
randOrtho(Eigen::Index size,
bool special =
false)
65 Eigen::VectorXd buffv(size);
66 Eigen::VectorXd buffw(size);
67 Eigen::MatrixXd Q = Eigen::MatrixXd::Identity(size, size);
69 if(size == 0)
return Q;
72 if(effolkronium::random_static::get<bool>())
74 Q(size - 1, size - 1) = 1;
79 Q(size - 1, size - 1) = -1;
83 for(Eigen::Index i = 2; i <= size; ++i)
85 auto v = buffv.head(i);
86 auto w = buffw.head(i);
92 bool positive = v[0] >= 0;
96 if(i % 2 == 0) positiveDet = !positiveDet;
101 positiveDet = !positiveDet;
107 H = -(Eigen::MatrixXd::Identity(i, i) - 2 * v * v.transpose());
109 H = Eigen::MatrixXd::Identity(i, i) - 2 * v * v.transpose();
111 w = Q.bottomRightCorner(i, i).transpose() * v;
114 Q(size - i, size - i) = -1;
115 Q.bottomRightCorner(i - 1, i - 1) *= -1;
116 Q.bottomRightCorner(i, i).noalias() += 2 * v * w.transpose();
120 Q.bottomRightCorner(i, i).noalias() -= 2 * v * w.transpose();
124 if(special && !positiveDet) Q.col(0) *= -1;
149 inline Eigen::MatrixXd
randn(Eigen::Index rows, Eigen::Index cols, Eigen::Index rank = -1)
151 assert(rank <= rows && rank <= cols &&
"Invalid rank");
152 Eigen::Index p = std::min(rows, cols);
153 if(rank < 0) rank = p;
155 if(rank == 0)
return Eigen::MatrixXd::Zero(rows, cols);
157 if(rank == p)
return randnMat(rows, cols);
159 Eigen::VectorXd s = Eigen::VectorXd::Zero(p);
160 s.head(rank).setRandom();
162 s.head(rank) *= std::sqrt((3. *
static_cast<double>(rows) *
static_cast<double>(cols)) /
static_cast<double>(rank));
164 Eigen::MatrixXd M(rows, cols);
168 M.leftCols(rows).noalias() =
randOrtho(rows) * s.asDiagonal();
169 M.rightCols(cols - rows).setZero();
174 M.topRows(cols).noalias() = s.asDiagonal() *
randOrtho(cols);
175 M.bottomRows(rows - cols).setZero();
189 inline std::pair<Eigen::MatrixXd, Eigen::MatrixXd>
randDependent(Eigen::Index cols,
196 assert(rankA <= rowsA && rankA <= cols);
197 assert(rankB <= rowsB && rankB <= cols);
198 assert(rankAB >= rankA && rankAB >= rankB && rankAB <= rankA + rankB && rankAB <= cols);
200 Eigen::MatrixXd M =
randn(rankA + rankB, cols, rankAB);
201 Eigen::MatrixXd A(rowsA, cols);
202 Eigen::MatrixXd B(rowsB, cols);
205 A = M.topRows(rankA);
207 A.noalias() =
randOrtho(rowsA).leftCols(rankA) * M.topRows(rankA);
210 B = M.bottomRows(rankB);
212 B.noalias() =
randOrtho(rowsB).leftCols(rankB) * M.bottomRows(rankB);