47 const MatrixXd& matGain,
48 const MatrixXd& matData,
49 const MatrixXd& matNoiseCov,
52 double gammaThreshold)
54 const int nChannels =
static_cast<int>(matGain.rows());
55 const int nSources =
static_cast<int>(matGain.cols());
56 const int nTimes =
static_cast<int>(matData.cols());
59 MatrixXd matNoiseCovInv = matNoiseCov.ldlt().solve(MatrixXd::Identity(nChannels, nChannels));
62 VectorXd vecGamma = VectorXd::Ones(nSources);
63 VectorXd vecGammaOld = vecGamma;
66 std::vector<int> activeIdx(nSources);
67 std::iota(activeIdx.begin(), activeIdx.end(), 0);
70 MatrixXd matX = MatrixXd::Zero(nSources, nTimes);
72 int actualIterations = 0;
74 for (
int iter = 0; iter < nIterations; ++iter) {
75 actualIterations = iter + 1;
77 const int nActive =
static_cast<int>(activeIdx.size());
82 MatrixXd matG_active(nChannels, nActive);
83 VectorXd vecGamma_active(nActive);
84 for (
int i = 0; i < nActive; ++i) {
85 matG_active.col(i) = matGain.col(activeIdx[i]);
86 vecGamma_active(i) = vecGamma(activeIdx[i]);
91 MatrixXd matCm = matG_active * vecGamma_active.asDiagonal() * matG_active.transpose() + matNoiseCov;
94 MatrixXd matCmInvM = matCm.ldlt().solve(matData);
97 MatrixXd matX_active = vecGamma_active.asDiagonal() * matG_active.transpose() * matCmInvM;
101 for (
int i = 0; i < nActive; ++i) {
102 matX.row(activeIdx[i]) = matX_active.row(i);
106 vecGammaOld = vecGamma;
107 for (
int i = 0; i < nActive; ++i) {
108 int srcIdx = activeIdx[i];
109 vecGamma(srcIdx) = matX_active.row(i).squaredNorm() /
static_cast<double>(nTimes);
113 std::vector<int> newActive;
114 newActive.reserve(nActive);
115 for (
int i = 0; i < nActive; ++i) {
116 int srcIdx = activeIdx[i];
117 if (vecGamma(srcIdx) >= gammaThreshold) {
118 newActive.push_back(srcIdx);
120 vecGamma(srcIdx) = 0.0;
123 activeIdx = newActive;
126 double maxGammaOld = std::max(vecGammaOld.cwiseAbs().maxCoeff(), 1e-10);
127 double maxRelChange = 0.0;
128 for (
int idx : activeIdx) {
129 double relChange = std::abs(vecGamma(idx) - vecGammaOld(idx)) / maxGammaOld;
130 maxRelChange = std::max(maxRelChange, relChange);
132 if (maxRelChange < tolerance)
142 QVector<int> finalActive;
143 for (
int i = 0; i < nSources; ++i) {
144 if (vecGamma(i) >= gammaThreshold) {
145 finalActive.append(i);
151 const int nActiveFinal = finalActive.size();
152 MatrixXd matActiveSol(nActiveFinal, nTimes);
153 VectorXi vecActiveVerts(nActiveFinal);
154 for (
int i = 0; i < nActiveFinal; ++i) {
155 matActiveSol.row(i) = matX.row(finalActive[i]);
156 vecActiveVerts(i) = finalActive[i];
163 MatrixXd matResidual = matData - matGain * matX;
static InvGammaMapResult compute(const Eigen::MatrixXd &matGain, const Eigen::MatrixXd &matData, const Eigen::MatrixXd &matNoiseCov, int nIterations=100, double tolerance=1e-6, double gammaThreshold=1e-10)