41 #ifndef BPP_NUMERIC_MATRIX_MATRIXTOOLS_H
42 #define BPP_NUMERIC_MATRIX_MATRIXTOOLS_H
47 #include "../../Io/OutputStream.h"
48 #include "../VectorTools.h"
71 template<
class MatrixA,
class MatrixO>
72 static void copy(
const MatrixA& A, MatrixO& O)
74 O.resize(A.getNumberOfRows(), A.getNumberOfColumns());
75 for (
size_t i = 0; i < A.getNumberOfRows(); i++)
77 for (
size_t j = 0; j < A.getNumberOfColumns(); j++)
91 template<
class MatrixA,
class MatrixO>
92 static void copyUp(
const MatrixA& A, MatrixO& O)
94 size_t nr(A.getNumberOfRows()), nc(A.getNumberOfColumns());
96 for (
size_t i = 0; i < nr - 1; i++)
98 for (
size_t j = 0; j < nc; j++)
100 O(i, j) = A(i + 1, j);
103 for (
size_t j = 0; j < nc; j++)
116 template<
class MatrixA,
class MatrixO>
119 size_t nr(A.getNumberOfRows()), nc(A.getNumberOfColumns());
121 for (
size_t i = 1; i < nr; i++)
123 for (
size_t j = 0; j < nc; j++)
125 O(i, j) = A(i - 1, j);
128 for (
size_t j = 0; j < nc; j++)
140 template<
class Matrix>
144 for (
size_t i = 0; i < n; i++)
146 for (
size_t j = 0; j < n; j++)
148 O(i, j) = (i == j) ? 1 : 0;
157 template<
class Scalar>
162 for (
size_t i = 0; i < n; i++)
164 for (
size_t j = 0; j < n; j++) { O(i, j) = (i == j) ? D[i] : 0;}
173 template<
class Scalar>
177 for (
size_t i = 0; i < n; i++)
179 for (
size_t j = 0; j < n; j++) { O(i, j) = (i == j) ? x : 0;}
188 template<
class Scalar>
193 if (nc != nr)
throw DimensionException(
"MatrixTools::diag(). M must be a square matrix.", nr, nc);
195 for (
size_t i = 0; i < nc; i++) { O[i] = M(i, i);}
203 template<
class Matrix,
class Scalar>
220 template<
class Matrix,
class Scalar>
238 template<
class Matrix,
class Scalar>
245 A(i, j) = a * A(i, j) + b;
255 template<
class Scalar>
262 if (ncA != nrB)
throw DimensionException(
"MatrixTools::mult(). nrows B != ncols A.", nrB, ncA);
264 for (
size_t i = 0; i < nrA; i++)
266 for (
size_t j = 0; j < ncB; j++)
269 for (
size_t k = 0; k < ncA; k++)
271 O(i, j) += A(i, k) * B(k, j);
288 template<
class Scalar>
295 if (ncA != nrB)
throw DimensionException(
"MatrixTools::mult(). nrows B != ncols A.", nrB, ncA);
298 for (
size_t i = 0; i < nrA; i++)
300 for (
size_t j = 0; j < ncB; j++)
304 for (
size_t k = 0; k < ncA; k++)
306 O(i, j) += A(i, k) * B(k, j) - iA(i, k) * iB(k, j);
307 iO(i, j) += A(i, k) * iB(k, j) + iA(i, k) * B(k, j);
325 template<
class Scalar>
332 if (ncA != nrB)
throw DimensionException(
"MatrixTools::mult(). nrows B != ncols A.", nrB, ncA);
333 if (ncA != D.size())
throw DimensionException(
"MatrixTools::mult(). Vector size is not equal to matrix size.", D.size(), ncA);
335 for (
size_t i = 0; i < nrA; i++)
337 for (
size_t j = 0; j < ncB; j++)
340 for (
size_t k = 0; k < ncA; k++)
342 O(i, j) += A(i, k) * B(k, j) * D[k];
366 template<
class Scalar>
373 if (ncA != nrB)
throw DimensionException(
"MatrixTools::mult(). nrows B != ncols A.", nrB, ncA);
374 if (ncA != D.size())
throw DimensionException(
"MatrixTools::mult(). Vector size is not equal to matrix size.", D.size(), ncA);
376 Scalar ab, iaib, iab, aib;
378 for (
size_t i = 0; i < nrA; i++)
380 for (
size_t j = 0; j < ncB; j++)
384 for (
size_t k = 0; k < ncA; k++)
386 ab = A(i, k) * B(k, j) - iA(i, k) * iB(k, j);
387 aib = A(i, k) * iB(k, j) + iA(i, k) * B(k, j);
389 O(i, j) += ab * D[k] - aib * iD[k];
390 iO(i, j) += ab * iD[k] + aib * D[k];
412 template<
class Scalar>
419 if (ncA != nrB)
throw DimensionException(
"MatrixTools::mult(). nrows B != ncols A.", nrB, ncA);
420 if (ncA != D.size())
throw DimensionException(
"MatrixTools::mult(). Vector size is not equal to matrix size.", D.size(), ncA);
421 if (ncA != U.size() + 1)
throw DimensionException(
"MatrixTools::mult(). Vector size is not equal to matrix size-1.", U.size(), ncA);
422 if (ncA != L.size() + 1)
throw DimensionException(
"MatrixTools::mult(). Vector size is not equal to matrix size-1.", L.size(), ncA);
424 for (
size_t i = 0; i < nrA; i++)
426 for (
size_t j = 0; j < ncB; j++)
428 O(i, j) = A(i, 0) * D[0] * B(0, j);
430 O(i, j) += A(i, 0) * U[0] * B(1, j);
431 for (
size_t k = 1; k < ncA - 1; k++)
433 O(i, j) += A(i, k) * (L[k - 1] * B(k - 1, j) + D[k] * B(k, j) + U[k] * B(k + 1, j));
436 O(i, j) += A(i, ncA - 1) * L[ncA - 2] * B(ncA - 2, j);
437 O(i, j) += A(i, ncA - 1) * D[ncA - 1] * B(ncA - 1, j);
450 template<
class MatrixA,
class MatrixB>
451 static void add(MatrixA& A,
const MatrixB& B)
453 size_t ncA = A.getNumberOfColumns();
454 size_t nrA = A.getNumberOfRows();
455 size_t nrB = B.getNumberOfRows();
456 size_t ncB = B.getNumberOfColumns();
457 if (ncA > ncB)
throw DimensionException(
"MatrixTools::operator+=(). A and B must have the same number of columns.", ncB, ncA);
458 if (nrA > nrB)
throw DimensionException(
"MatrixTools::operator+=(). A and B must have the same number of rows.", nrB, nrA);
461 for (
size_t i = 0; i < nrA; i++)
463 for (
size_t j = 0; j < ncA; j++)
478 template<
class MatrixA,
class MatrixB,
class Scalar>
479 static void add(MatrixA& A, Scalar& x,
const MatrixB& B)
481 size_t ncA = A.getNumberOfColumns();
482 size_t nrA = A.getNumberOfRows();
483 size_t nrB = B.getNumberOfRows();
484 size_t ncB = B.getNumberOfColumns();
485 if (ncA != ncB)
throw DimensionException(
"MatrixTools::operator+(). A and B must have the same number of columns.", ncB, ncA);
486 if (nrA != nrB)
throw DimensionException(
"MatrixTools::operator+(). A and B must have the same number of rows.", nrB, nrA);
488 for (
size_t i = 0; i < nrA; i++)
490 for (
size_t j = 0; j < ncA; j++)
492 A(i, j) += x * B(i, j);
508 template<
class Matrix>
533 pow(A, (p - 1) / 2, tmp);
550 template<
class Scalar>
557 rightEV = eigen.
getV();
558 inv(rightEV, leftEV);
572 template<
class Scalar>
579 rightEV = eigen.
getV();
580 inv(rightEV, leftEV);
594 template<
class Matrix,
class Scalar>
601 getId<Matrix>(n, vO[0]);
604 for (
size_t i = 1; i < p; i++)
606 mult(vO[i], A, vO[i + 1]);
614 template<
class Matrix>
619 std::vector<size_t> pos(2);
622 double currentMax = std::log(0.);
623 for (
size_t i = 0; i < nrows; i++)
625 for (
size_t j = 0; j < ncols; j++)
627 double currentValue = m(i, j);
629 if (currentValue > currentMax)
633 currentMax = currentValue;
646 template<
class Matrix>
651 std::vector<size_t> pos(2);
654 double currentMin = -std::log(0.);
655 for (
size_t i = 0; i < nrows; i++)
657 for (
size_t j = 0; j < ncols; j++)
659 double currentValue = m(i, j);
660 if (currentValue < currentMin)
664 currentMin = currentValue;
682 Real currentMax = std::log(0.);
683 for (
size_t i = 0; i < nrows; i++)
685 for (
size_t j = 0; j < ncols; j++)
687 Real currentValue = m(i, j);
689 if (currentValue > currentMax)
691 currentMax = currentValue;
708 Real currentMin = -std::log(0.);
709 for (
size_t i = 0; i < nrows; i++)
711 for (
size_t j = 0; j < ncols; j++)
713 Real currentValue = m(i, j);
714 if (currentValue < currentMin)
716 currentMin = currentValue;
729 template<
class Matrix>
733 out <<
"[" << std::endl;
739 out << m(i, j) <<
", ";
743 out <<
"]" << std::endl;
754 template<
class Matrix>
767 out << m(i, j) <<
", ";
781 template<
class Matrix>
782 static void printForR(
const Matrix& m,
const std::string& variableName =
"x", std::ostream& out = std::cout)
785 out << variableName <<
"<-matrix(c(";
798 out <<
"), nrow=" << m.
getNumberOfRows() <<
", byrow=TRUE)" << std::endl;
809 static void print(
const std::vector<Real>& v, std::ostream& out = std::cout)
811 out << v.size() << std::endl;
813 for (
size_t i = 0; i < v.size() - 1; i++)
817 if (v.size() > 0) out << v[v.size() - 1];
818 out <<
"]" << std::endl;
825 template<
class Matrix>
834 template<
class Scalar>
841 return lu.
solve(I, O);
853 template<
class Scalar>
865 template<
class MatrixA,
class MatrixO>
868 O.resize(A.getNumberOfColumns(), A.getNumberOfRows());
869 for (
size_t i = 0; i < A.getNumberOfColumns(); i++)
871 for (
size_t j = 0; j < A.getNumberOfRows(); j++)
882 template<
class MatrixA>
885 if (A.getNumberOfColumns() != A.getNumberOfRows())
888 for (
size_t i = 0; i < A.getNumberOfColumns(); i++)
890 for (
size_t j = i + 1; j < A.getNumberOfRows(); j++)
892 if (A(i, j) != A(j, i))
911 template<
class Scalar>
920 scale(O, 1. /
static_cast<double>(n));
922 for (
size_t i = 0; i < r; i++)
924 for (
size_t j = 0; j < n; j++)
926 mean(i, 0) += A(i, j);
928 mean(i, 0) /=
static_cast<double>(n);
933 mult(mean, tMean, meanMat);
946 template<
class Scalar>
955 O.
resize(nrA * nrB, ncA * ncB);
957 for (
size_t ia = 0; ia < nrA; ia++)
959 for (
size_t ja = 0; ja < ncA; ja++)
961 Scalar aij = A(ia, ja);
962 for (
size_t ib = 0; ib < nrB; ib++)
964 for (
size_t jb = 0; jb < ncB; jb++)
966 O(ia * nrB + ib, ja * ncB + jb) = aij * B(ib, jb);
983 template<
class Scalar>
990 O.
resize(nrA * dim, ncA * dim);
992 for (
size_t ia = 0; ia < nrA; ia++)
994 for (
size_t ja = 0; ja < ncA; ja++)
996 Scalar aij = A(ia, ja);
997 for (
size_t ib = 0; ib < dim; ib++)
999 for (
size_t jb = 0; jb < dim; jb++)
1001 O(ia * dim + ib, ja * dim + jb) = aij * ((ib == jb) ? v : 0);
1019 template<
class Scalar>
1028 O.
resize(nrA * nrB, ncA * ncB);
1030 for (
size_t ia = 0; ia < nrA; ia++)
1032 for (
size_t ja = 0; ja < ncA; ja++)
1034 const Scalar& aij = (ia == ja) ? dA : A(ia, ja);
1036 for (
size_t ib = 0; ib < nrB; ib++)
1038 for (
size_t jb = 0; jb < ncB; jb++)
1040 O(ia * nrB + ib, ja * ncB + jb) = aij * ((ib == jb) ? dB : B(ib, jb));
1054 template<
class Scalar>
1061 if (nrA != nrB)
throw DimensionException(
"MatrixTools::hadamardMult(). nrows A != nrows B.", nrA, nrB);
1062 if (ncA != ncB)
throw DimensionException(
"MatrixTools::hadamardMult(). ncols A != ncols B.", ncA, ncB);
1064 for (
size_t i = 0; i < nrA; i++)
1066 for (
size_t j = 0; j < ncA; j++)
1068 O(i, j) = A(i, j) * B(i, j);
1083 template<
class Scalar>
1090 if (nrA != nrB)
throw DimensionException(
"MatrixTools::hadamardMult(). nrows A != nrows B.", nrA, nrB);
1091 if (ncA != ncB)
throw DimensionException(
"MatrixTools::hadamardMult(). ncols A != ncols B.", ncA, ncB);
1094 for (
size_t i = 0; i < nrA; i++)
1096 for (
size_t j = 0; j < ncA; j++)
1098 O(i, j) = A(i, j) * B(i, j) - iA(i, j) * iB(i, j);
1099 iO(i, j) = iA(i, j) * B(i, j) + A(i, j) * iB(i, j);
1112 template<
class Scalar>
1117 size_t sB = B.size();
1118 if (row ==
true && nrA != sB)
throw DimensionException(
"MatrixTools::hadamardMult(). nrows A != size of B.", nrA, sB);
1119 if (row ==
false && ncA != sB)
throw DimensionException(
"MatrixTools::hadamardMult(). ncols A != size of B.", ncA, sB);
1123 for (
size_t i = 0; i < nrA; i++)
1125 for (
size_t j = 0; j < ncA; j++)
1127 O(i, j) = A(i, j) * B[i];
1133 for (
size_t i = 0; i < nrA; i++)
1135 for (
size_t j = 0; j < ncA; j++)
1137 O(i, j) = A(i, j) * B[j];
1150 template<
class Scalar>
1157 O.
resize(nrA + nrB, ncA + ncB);
1159 for (
size_t ia = 0; ia < nrA; ia++)
1161 for (
size_t ja = 0; ja < ncA; ja++)
1163 O(ia, ja) = A(ia, ja);
1167 for (
size_t ia = 0; ia < nrA; ia++)
1169 for (
size_t jb = 0; jb < ncB; jb++)
1171 O(ia, ncA + jb) = 0;
1175 for (
size_t ib = 0; ib < nrB; ib++)
1177 for (
size_t ja = 0; ja < ncA; ja++)
1179 O(nrA + ib, ja) = 0;
1183 for (
size_t ib = 0; ib < nrB; ib++)
1185 for (
size_t jb = 0; jb < nrB; jb++)
1187 O(nrA + ib, ncA + jb) = B(ib, jb);
1198 template<
class Scalar>
1203 for (
size_t k = 0; k < vA.size(); k++)
1205 nr += vA[k]->getNumberOfRows();
1206 nc += vA[k]->getNumberOfColumns();
1209 for (
size_t k = 0; k < nr; k++)
1211 for (
size_t k2 = 0; k2 < nc; k2++)
1219 for (
size_t k = 0; k < vA.size(); k++)
1226 O(rk + i, ck + j) = (*Ak)(i, j);
1240 template<
class Scalar>
1246 for (
size_t i = 0; i < n; i++)
1249 for (
size_t j = 0; j < m; j++)
1261 template<
class Scalar>
1290 template<
class Scalar>
1292 std::vector<int>& rowSol,
1293 std::vector<int>& colSol,
1294 std::vector<Scalar>& u,
1295 std::vector<Scalar>& v)
1299 throw Exception(
"MatrixTools::lap. Cost matrix should be scare.");
1301 bool unassignedFound;
1303 size_t numFree = 0, previousNumFree, f, k, freeRow;
1305 std::vector<size_t> free(dim);
1306 std::vector<size_t> pred(dim);
1307 size_t j, j1, j2, endOfPath, last, low, up;
1308 std::vector<size_t> colList(dim);
1309 std::vector<short int> matches(dim, 0);
1312 size_t uMin, uSubMin;
1314 std::vector<Scalar> d(dim);
1317 for (j = dim; j > 0; j--)
1320 min = assignCost(0, j - 1);
1322 for (i = 1; i < dim; ++i)
1324 if (assignCost(i, j - 1) <
min)
1326 min = assignCost(i, j - 1);
1332 if (++matches[iMin] == 1)
1335 rowSol[iMin] =
static_cast<int>(j - 1);
1336 colSol[j - 1] =
static_cast<int>(iMin);
1343 for (i = 0; i < dim; i++)
1345 if (matches[i] == 0)
1346 free[numFree++] = i;
1349 if (matches[i] == 1)
1351 j1 =
static_cast<size_t>(rowSol[i]);
1353 for (j = 0; j < dim; j++)
1356 if (assignCost(i, j - 1) - v[j] <
min)
1357 min = assignCost(i, j - 1) - v[j - 1];
1359 v[j1] = v[j1] -
min;
1373 previousNumFree = numFree;
1375 while (k < previousNumFree)
1381 uMin = assignCost(i, 0) - v[0];
1383 uSubMin =
static_cast<size_t>(-std::log(0));
1384 for (j = 1; j < dim; j++)
1386 h = assignCost(i, j) - v[j];
1409 v[j1] = v[j1] - (uSubMin - uMin);
1422 rowSol[i] =
static_cast<int>(j1);
1423 colSol[j1] =
static_cast<int>(i);
1431 free[--k] =
static_cast<size_t>(i0);
1437 free[numFree++] =
static_cast<size_t>(i0);
1442 while (loopcnt < 2);
1445 for (f = 0; f < numFree; f++)
1451 for (j = 0; j < dim; j++)
1453 d[j] = assignCost(freeRow, j) - v[j];
1462 unassignedFound =
false;
1471 min = d[colList[up++]];
1472 for (k = up; k < dim; k++)
1484 colList[k] = colList[up];
1491 for (k = low; k < up; k++)
1493 if (colSol[colList[k]] < 0)
1495 endOfPath = colList[k];
1496 unassignedFound =
true;
1502 if (!unassignedFound)
1507 i =
static_cast<size_t>(colSol[j1]);
1508 h = assignCost(i, j1) - v[j1] -
min;
1510 for (k = up; k < dim; k++)
1513 v2 = assignCost(i, j) - v[j] - h;
1523 unassignedFound =
true;
1529 colList[k] = colList[up];
1538 while (!unassignedFound);
1541 for (k = 0; k <= last; k++)
1544 v[j1] = v[j1] + d[j1] -
min;
1550 i = pred[endOfPath];
1551 colSol[endOfPath] =
static_cast<int>(i);
1553 endOfPath =
static_cast<size_t>(rowSol[i]);
1554 rowSol[i] =
static_cast<int>(j1);
1556 while (i != freeRow);
1561 for (i = 0; i < dim; i++)
1563 j =
static_cast<size_t>(rowSol[i]);
1564 u[i] = assignCost(i, j) - v[j];
1565 lapCost = lapCost + assignCost(i, j);
Exception thrown when a dimension problem occured.
Computes eigenvalues and eigenvectors of a real (non-complex) matrix.
const RowMatrix< Real > & getV() const
Return the eigenvector matrix.
const std::vector< Real > & getRealEigenValues() const
Return the real parts of the eigenvalues.
Exception base class. Overload exception constructor (to control the exceptions mechanism)....
Real det() const
Compute determinant using LU factors.
Real solve(const Matrix< Real > &B, Matrix< Real > &X) const
Solve A*X = B.
The matrix template interface.
virtual size_t getNumberOfColumns() const =0
virtual void resize(size_t nRows, size_t nCols)=0
Resize the matrix.
virtual size_t getNumberOfRows() const =0