在 C++ 中生成随机正交矩阵

计算科学 线性代数 C++ 随机抽样
2021-11-26 17:43:43

我正在寻找一个用于在 C++ 中生成随机 n 维正交矩阵的开源库。

在 python 中, NumPy 包中似乎有这样的函数但是我还没有找到 C++ 中的解决方案。有什么建议?

3个回答

我在你的评论中看到你想要一个统一的抽样。

使用该Eigen库,您可以均匀地随机生成一个单位四元数:

Eigen::Quaterniond q = Eigen::Quaterniond::UnitRandom();

然后将其转换为旋转(正交)矩阵:

Eigen::MatrixXd M = q.toRotationMatrix();

您引用的示例似乎是生成随机 Householder 向量并使用反向累积将它们相乘。

另一个简单的做法是生成一个随机矩阵,然后计算其分解并丢弃因子。您需要的两个 LAPACK 函数是 [geqrf]()和 [orgqr](从隐式反射器形式虽然这比 numpy 算法做更多的工作(大约 2 倍),但实际上对于大 N 可能会更快,因为它将使用 BLAS3 内核(而一对一的反向累积只是 BLAS2)。AA=QRRA=QRQ

很多C++ 代数库,只要找一个恰好包装了这两个函数的库就行了。我碰巧创作/维护了这样一个包含它们的库(myramath),请参阅下面的测试程序以生成随机正交矩阵:

#include <myramath/dense/Matrix.h>
#include <myramath/dense/geqrf.h>
#include <myramath/dense/orgqr.h>

#include <myramath/dense/gemm.h>
#include <myramath/dense/frobenius.h>

#include <iostream>

myra::Matrix<double> rvs(int N)
  {
  auto A = myra::Matrix<double>::random(N,N);
  auto tau = myra::geqrf_inplace(A);
  myra::orgqr_inplace(A,tau);
  return A;
  }

int main()
  {
  // Form Q.
  int N = 10;
  auto Q = rvs(N);
  std::cout << "Q = " << Q << std::endl;
  // Check Q is orthogonal.
  auto I = myra::Matrix<double>::identity(N);
  std::cout << "|Q'Q-I| = " << myra::frobenius(myra::gemm(Q,'T',Q)-I) << std::endl;
  std::cout << "|QQ'-I| = " << myra::frobenius(myra::gemm(Q,Q,'T')-I) << std::endl;
  return 0;
  }

如果矩阵,其条目是从标准正态分布独立生成的值,则是均匀生成的随机正交矩阵。来源X(n×m)X(XX)12

这是一个实现Eigen

#include<iostream>
#include<random>
#include<Eigen/Eigen>
#include<ctime>
using namespace std;
using namespace Eigen;

static default_random_engine e(time(0));
static normal_distribution<double> gaussian(0,1);

MatrixXd randomOrthogonalMatrix(const unsigned long n){
  MatrixXd X = MatrixXd::Zero(n,n).unaryExpr([](double dummy){return gaussian(e);});
  MatrixXd XtX = X.transpose() * X;
  SelfAdjointEigenSolver<MatrixXd> es(XtX);
  MatrixXd S = es.operatorInverseSqrt();
  return X * S;
}

我不是 C++ 的明星,不知道在哪里放置随机生成器。