60 const MatrixXd& matGain,
61 const MatrixXd& matData,
62 const MatrixXd& matNoiseCov,
65 double gammaThreshold)
67 const int nChannels =
static_cast<int>(matGain.rows());
68 const int nSources =
static_cast<int>(matGain.cols());
69 const int nTimes =
static_cast<int>(matData.cols());
72 MatrixXd matNoiseCovInv = matNoiseCov.ldlt().solve(MatrixXd::Identity(nChannels, nChannels));
75 VectorXd vecGamma = VectorXd::Ones(nSources);
76 VectorXd vecGammaOld = vecGamma;
79 std::vector<int> activeIdx(nSources);
80 std::iota(activeIdx.begin(), activeIdx.end(), 0);
83 MatrixXd matX = MatrixXd::Zero(nSources, nTimes);
85 int actualIterations = 0;
87 for (
int iter = 0; iter < nIterations; ++iter) {
88 actualIterations = iter + 1;
90 const int nActive =
static_cast<int>(activeIdx.size());
95 MatrixXd matG_active(nChannels, nActive);
96 VectorXd vecGamma_active(nActive);
97 for (
int i = 0; i < nActive; ++i) {
98 matG_active.col(i) = matGain.col(activeIdx[i]);
99 vecGamma_active(i) = vecGamma(activeIdx[i]);
104 MatrixXd matCm = matG_active * vecGamma_active.asDiagonal() * matG_active.transpose() + matNoiseCov;
107 MatrixXd matCmInvM = matCm.ldlt().solve(matData);
110 MatrixXd matX_active = vecGamma_active.asDiagonal() * matG_active.transpose() * matCmInvM;
114 for (
int i = 0; i < nActive; ++i) {
115 matX.row(activeIdx[i]) = matX_active.row(i);
119 vecGammaOld = vecGamma;
120 for (
int i = 0; i < nActive; ++i) {
121 int srcIdx = activeIdx[i];
122 vecGamma(srcIdx) = matX_active.row(i).squaredNorm() /
static_cast<double>(nTimes);
126 std::vector<int> newActive;
127 newActive.reserve(nActive);
128 for (
int i = 0; i < nActive; ++i) {
129 int srcIdx = activeIdx[i];
130 if (vecGamma(srcIdx) >= gammaThreshold) {
131 newActive.push_back(srcIdx);
133 vecGamma(srcIdx) = 0.0;
136 activeIdx = newActive;
139 double maxGammaOld = std::max(vecGammaOld.cwiseAbs().maxCoeff(), 1e-10);
140 double maxRelChange = 0.0;
141 for (
int idx : activeIdx) {
142 double relChange = std::abs(vecGamma(idx) - vecGammaOld(idx)) / maxGammaOld;
143 maxRelChange = std::max(maxRelChange, relChange);
145 if (maxRelChange < tolerance)
155 QVector<int> finalActive;
156 for (
int i = 0; i < nSources; ++i) {
157 if (vecGamma(i) >= gammaThreshold) {
158 finalActive.append(i);
164 const int nActiveFinal = finalActive.size();
165 MatrixXd matActiveSol(nActiveFinal, nTimes);
166 VectorXi vecActiveVerts(nActiveFinal);
167 for (
int i = 0; i < nActiveFinal; ++i) {
168 matActiveSol.row(i) = matX.row(finalActive[i]);
169 vecActiveVerts(i) = finalActive[i];
176 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)