6#include "storm-config.h"
16TEST(SparseMatrixBuilder, CreationEmpty) {
19 ASSERT_NO_THROW(matrix = matrixBuilder.
build());
26TEST(SparseMatrixBuilder, CreationWithDimensions) {
35 ASSERT_NO_THROW(matrix = matrixBuilder.
build());
42TEST(SparseMatrixBuilder, CreationWithoutNumberOfEntries) {
51 ASSERT_NO_THROW(matrix = matrixBuilder.
build());
58TEST(SparseMatrixBuilder, CreationWithNumberOfRows) {
67 ASSERT_NO_THROW(matrix = matrixBuilder.
build());
74TEST(SparseMatrixBuilder, CreationWithoutDimensions) {
83 ASSERT_NO_THROW(matrix = matrixBuilder.
build());
90TEST(SparseMatrixBuilder, AddNextValue) {
104 ASSERT_NO_THROW(matrixBuilder3.
addNextValue(0, 1, 1.0));
105 ASSERT_NO_THROW(matrixBuilder3.
addNextValue(1, 2, 1.2));
106 ASSERT_NO_THROW(matrixBuilder3.
addNextValue(2, 4, 0.5));
110 ASSERT_NO_THROW(matrixBuilder4.
addNextValue(0, 1, 1.0));
111 ASSERT_NO_THROW(matrixBuilder4.
addNextValue(1, 2, 1.2));
112 ASSERT_NO_THROW(matrixBuilder4.
addNextValue(2, 4, 0.5));
113 ASSERT_NO_THROW(matrixBuilder4.
addNextValue(3, 1, 0.2));
117using RowEntries = std::vector<std::pair<uint64_t, double>>;
122 for (
auto const& entry : matrix.
getRow(row)) {
123 result.emplace_back(entry.getColumn(), entry.getValue());
129TEST(SparseMatrixBuilder, AccumulationModeSetterGetter) {
140TEST(SparseMatrixBuilder, AccumulationSum) {
153 ASSERT_NO_THROW(matrix = builder.
build());
157 EXPECT_EQ((RowEntries{{1, 0.5}, {2, 0.5}}), getRowEntries(matrix, 0));
158 EXPECT_EQ((RowEntries{{0, 0.75}, {2, 0.375}}), getRowEntries(matrix, 1));
161TEST(SparseMatrixBuilder, AccumulationExpectSame) {
177 ASSERT_NO_THROW(matrix = builder.
build());
182 EXPECT_EQ((RowEntries{{1, 0.25}, {2, 0.5}}), getRowEntries(matrix, 0));
183 EXPECT_EQ((RowEntries{{0, 1.0}}), getRowEntries(matrix, 1));
186TEST(SparseMatrixBuilder, AccumulationExpectNone) {
201 ASSERT_NO_THROW(matrix = builder.
build());
203 EXPECT_EQ((RowEntries{{0, 0.25}, {1, 0.25}, {2, 0.5}}), getRowEntries(matrix, 0));
204 EXPECT_EQ((RowEntries{{1, 1.0}}), getRowEntries(matrix, 1));
207TEST(SparseMatrixBuilder, AccumulationDiagonalEntries) {
215 auto matrix = builder.
build();
216 EXPECT_EQ((RowEntries{{0, 0.625}, {1, 0.5}}), getRowEntries(matrix, 0));
227 auto matrix = builder.
build();
228 EXPECT_EQ((RowEntries{{0, 0.5}, {1, 0.5}}), getRowEntries(matrix, 0));
229 EXPECT_EQ((RowEntries{{1, 0.5}}), getRowEntries(matrix, 1));
232 failingBuilder1.setAccumulationMode(AccumulationMode::ExpectSame);
233 ASSERT_NO_THROW(failingBuilder1.addDiagonalEntry(0, 0.5));
247 auto matrix = builder.
build();
248 EXPECT_EQ((RowEntries{{0, 0.5}, {1, 0.5}}), getRowEntries(matrix, 0));
251 failingBuilder1.setAccumulationMode(AccumulationMode::ExpectNone);
252 ASSERT_NO_THROW(failingBuilder1.addDiagonalEntry(0, 0.5));
262TEST(SparseMatrixBuilder, DuplicateEntriesWithoutForcedEntryCount) {
270 ASSERT_NO_THROW(matrix = builder.
build(2, 2));
276 ASSERT_NO_THROW(forcingBuilder.
addNextValue(0, 0, 0.25));
277 ASSERT_NO_THROW(forcingBuilder.
addNextValue(0, 0, 0.25));
278 ASSERT_NO_THROW(forcingBuilder.
addNextValue(1, 1, 0.5));
279 ASSERT_NO_THROW(forcingBuilder.
addNextValue(1, 1, 0.5));
283TEST(SparseMatrixBuilder, OutOfOrderInsertion) {
288 for (uint64_t column = 10; column-- > 0;) {
289 ASSERT_NO_THROW(builder.
addNextValue(0, column, column + 1.0));
290 ASSERT_NO_THROW(orderedBuilder.
addNextValue(0, 9 - column, 10.0 - column));
292 for (uint64_t column : {5, 3, 7, 1, 9, 0, 4}) {
293 ASSERT_NO_THROW(builder.
addNextValue(1, column, column + 1.0));
295 for (uint64_t column : {0, 1, 3, 4, 5, 7, 9}) {
296 ASSERT_NO_THROW(orderedBuilder.
addNextValue(1, column, column + 1.0));
299 EXPECT_EQ(orderedBuilder.
build(3, 10), builder.
build(3, 10));
325 auto matrix = builder.
build();
330 EXPECT_EQ((RowEntries{{1, 2.0}, {2, 3.0}, {3, 4.0}}), getRowEntries(matrix, 0));
331 EXPECT_EQ((RowEntries{}), getRowEntries(matrix, 1));
332 EXPECT_EQ((RowEntries{{0, 1.0}, {2, 3.0}}), getRowEntries(matrix, 2));
333 EXPECT_EQ((RowEntries{}), getRowEntries(matrix, 3));
334 EXPECT_EQ((RowEntries{{1, 2.0}}), getRowEntries(matrix, 4));
338TEST(SparseMatrixBuilder, OutOfOrderInsertionRandomized) {
339 std::mt19937 gen(42);
340 for (uint64_t iteration = 0; iteration < 50; ++iteration) {
341 uint64_t
const numRows = 1 + gen() % 8;
342 uint64_t
const numColumns = 1 + gen() % 50;
343 std::map<std::pair<uint64_t, uint64_t>,
double> expectedEntries;
345 for (uint64_t row = 0; row < numRows; ++row) {
346 uint64_t
const numInsertions = gen() % 120;
347 for (uint64_t i = 0; i < numInsertions; ++i) {
348 uint64_t
const column = gen() % numColumns;
349 double const value = 1.0 + gen() % 8;
350 expectedEntries[{row, column}] += value;
351 ASSERT_NO_THROW(builder.
addNextValue(row, column, value));
355 for (
auto const& [position, value] : expectedEntries) {
356 orderedBuilder.
addNextValue(position.first, position.second, value);
358 auto const expectedMatrix = orderedBuilder.
build(numRows, numColumns);
359 auto const matrix = builder.
build(numRows, numColumns);
360 EXPECT_EQ(expectedMatrix, matrix) <<
"Matrices differ in iteration " << iteration;
361 EXPECT_EQ(expectedEntries.size(), matrix.
getEntryCount()) <<
"Unexpected number of entries in iteration " << iteration;
365TEST(SparseMatrixBuilder, OverriddenDimensionsTooSmall) {
366 auto createBuilder = []() {
384 auto matrix = createBuilder().build(3, 4, 2);
391 auto matrix = createBuilder().build(5, 6, 4);
399 auto matrix = createBuilder().build(0, 0, 0);
414TEST(SparseMatrixBuilder, ContinueFromEmptyMatrix) {
422 auto result = builder.
build();
423 ASSERT_EQ(2ul, result.getRowCount());
424 ASSERT_EQ(3ul, result.getColumnCount());
425 EXPECT_EQ((RowEntries{{1, 0.5}, {2, 0.5}}), getRowEntries(result, 0));
426 EXPECT_EQ((RowEntries{{0, 1.0}}), getRowEntries(result, 1));
429TEST(SparseMatrixBuilder, TrailingEmptyRowGroup) {
431 auto createBuilder = []() {
438 auto matrix = createBuilder().build();
444 EXPECT_EQ(2ul, createBuilder().build(2).getRowCount());
449 ASSERT_NO_THROW(matrixBuilder1.
addNextValue(0, 1, 1.0));
450 ASSERT_NO_THROW(matrixBuilder1.
addNextValue(0, 2, 1.2));
451 ASSERT_NO_THROW(matrixBuilder1.
addNextValue(1, 0, 0.5));
452 ASSERT_NO_THROW(matrixBuilder1.
addNextValue(1, 1, 0.7));
453 ASSERT_NO_THROW(matrixBuilder1.
addNextValue(1, 3, 0.2));
454 ASSERT_NO_THROW(matrixBuilder1.
build());
457 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(0, 1, 1.0));
458 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(0, 2, 1.2));
459 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(1, 0, 0.5));
460 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(1, 1, 0.7));
464 ASSERT_NO_THROW(matrixBuilder3.
addNextValue(0, 1, 1.0));
465 ASSERT_NO_THROW(matrixBuilder3.
addNextValue(0, 2, 1.2));
466 ASSERT_NO_THROW(matrixBuilder3.
addNextValue(1, 0, 0.5));
467 ASSERT_NO_THROW(matrixBuilder3.
addNextValue(1, 1, 0.7));
468 ASSERT_NO_THROW(matrixBuilder3.
addNextValue(1, 3, 0.2));
470 ASSERT_NO_THROW(matrix3 = matrixBuilder3.
build());
476 ASSERT_NO_THROW(matrixBuilder4.
addNextValue(0, 1, 1.0));
477 ASSERT_NO_THROW(matrixBuilder4.
addNextValue(0, 2, 1.2));
478 ASSERT_NO_THROW(matrixBuilder4.
addNextValue(1, 0, 0.5));
479 ASSERT_NO_THROW(matrixBuilder4.
addNextValue(1, 1, 0.7));
480 ASSERT_NO_THROW(matrixBuilder4.
addNextValue(1, 3, 0.2));
482 ASSERT_NO_THROW(matrix4 = matrixBuilder4.
build(4));
488 ASSERT_NO_THROW(matrixBuilder5.
addNextValue(0, 1, 1.0));
489 ASSERT_NO_THROW(matrixBuilder5.
addNextValue(0, 2, 1.2));
490 ASSERT_NO_THROW(matrixBuilder5.
addNextValue(1, 0, 0.5));
491 ASSERT_NO_THROW(matrixBuilder5.
addNextValue(1, 1, 0.7));
492 ASSERT_NO_THROW(matrixBuilder5.
addNextValue(1, 3, 0.2));
494 ASSERT_NO_THROW(matrix5 = matrixBuilder5.
build(0, 6));
500TEST(SparseMatrix, DiagonalEntries) {
505 for (uint64_t i = 0; i < 4; ++i) {
510 ASSERT_NO_THROW(builderCmp.
addNextValue(i, 2, 100.0 + i));
512 ASSERT_NO_THROW(builderCmp.
addNextValue(i, 2, 100.0 + i));
516 auto matrix = builder.
build();
517 auto matrixCmp = builderCmp.
build();
518 EXPECT_EQ(matrix, matrixCmp);
524 for (uint64_t i = 0; i < 4; ++i) {
525 uint64_t row = 3 * i;
528 for (; row < 3 * (i + 1); ++row) {
530 ASSERT_NO_THROW(builder.
addNextValue(row, 2, 100 + row));
533 ASSERT_NO_THROW(builderCmp.
addNextValue(row, 2, 100.0 + row));
535 ASSERT_NO_THROW(builderCmp.
addNextValue(row, 2, 100.0 + row));
540 auto matrix = builder.
build();
541 auto matrixCmp = builderCmp.
build();
542 EXPECT_EQ(matrix, matrixCmp);
548 for (uint64_t i = 0; i < 4; ++i) {
549 uint64_t row = 3 * i;
552 for (; row < 3 * (i + 1); ++row) {
557 ASSERT_NO_THROW(builder.
addNextValue(row, 2, 100 + row));
560 ASSERT_NO_THROW(builderCmp.
addNextValue(row, 2, 100.0 + row));
563 ASSERT_NO_THROW(builderCmp.
addNextValue(row, 2, 100.0 + row));
567 auto matrix = builder.
build();
568 auto matrixCmp = builderCmp.
build();
569 EXPECT_EQ(matrix, matrixCmp);
573TEST(SparseMatrix, CreationWithMovingContents) {
574 std::vector<storm::storage::MatrixEntry<uint_fast64_t, double>> columnsAndValues;
575 columnsAndValues.emplace_back(1, 1.0);
576 columnsAndValues.emplace_back(2, 1.2);
577 columnsAndValues.emplace_back(0, 0.5);
578 columnsAndValues.emplace_back(1, 0.7);
579 columnsAndValues.emplace_back(3, 0.2);
589TEST(SparseMatrix, CopyConstruct) {
598 ASSERT_NO_THROW(matrix = matrixBuilder.
build());
602 ASSERT_TRUE(matrix == copy);
605TEST(SparseMatrix, CopyAssign) {
614 ASSERT_NO_THROW(matrix = matrixBuilder.
build());
618 ASSERT_TRUE(matrix == copy);
621TEST(SparseMatrix, MakeAbsorbing) {
629 ASSERT_NO_THROW(matrix = matrixBuilder.
build());
632 absorbingRows.
set(1);
637 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(0, 1, 1.0));
638 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(0, 2, 1.2));
642 ASSERT_NO_THROW(matrix2 = matrixBuilder2.
build());
644 ASSERT_TRUE(matrix == matrix2);
647TEST(SparseMatrix, MakeRowGroupAbsorbing) {
662 ASSERT_NO_THROW(matrix = matrixBuilder.
build());
665 absorbingRowGroups.
set(1);
671 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(0, 1, 1.0));
672 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(0, 2, 1.2));
673 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(1, 0, 0.5));
674 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(1, 1, 0.7));
679 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(4, 0, 0.1));
680 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(4, 1, 0.2));
681 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(4, 3, 0.3));
683 ASSERT_NO_THROW(matrix2 = matrixBuilder2.
build());
685 ASSERT_TRUE(matrix == matrix2);
688TEST(SparseMatrix, rowGroupIndices) {
703 ASSERT_NO_THROW(matrix = matrixBuilder.
build());
706 std::vector<storm::storage::SparseMatrixIndexType> expected, actual;
707 expected.assign({0, 1});
709 actual.assign(indices.begin(), indices.end());
710 EXPECT_EQ(expected, actual);
711 expected.assign({2, 3});
713 actual.assign(indices.begin(), indices.end());
714 EXPECT_EQ(expected, actual);
715 expected.assign({4});
717 actual.assign(indices.begin(), indices.end());
718 EXPECT_EQ(expected, actual);
721 actual.assign(indices.begin(), indices.end());
722 EXPECT_EQ(expected, actual);
725TEST(SparseMatrix, ConstrainedRowSumVector) {
737 ASSERT_NO_THROW(matrix = matrixBuilder.
build());
740 columnConstraint.
set(1);
741 columnConstraint.
set(3);
745 ASSERT_TRUE(constrainedRowSum == std::vector<double>({1.0, 0.7, 0, 0, 0.5}));
748 ASSERT_NO_THROW(matrixBuilder2.newRowGroup(0));
749 ASSERT_NO_THROW(matrixBuilder2.addNextValue(0, 1, 1.0));
750 ASSERT_NO_THROW(matrixBuilder2.addNextValue(0, 2, 1.2));
751 ASSERT_NO_THROW(matrixBuilder2.addNextValue(1, 0, 0.5));
752 ASSERT_NO_THROW(matrixBuilder2.addNextValue(1, 1, 0.7));
753 ASSERT_NO_THROW(matrixBuilder2.newRowGroup(2));
754 ASSERT_NO_THROW(matrixBuilder2.addNextValue(2, 0, 0.5));
755 ASSERT_NO_THROW(matrixBuilder2.addNextValue(3, 2, 1.1));
756 ASSERT_NO_THROW(matrixBuilder2.addNextValue(3, 3, 1.2));
757 ASSERT_NO_THROW(matrixBuilder2.newRowGroup(4));
758 ASSERT_NO_THROW(matrixBuilder2.addNextValue(4, 0, 0.1));
759 ASSERT_NO_THROW(matrixBuilder2.addNextValue(4, 3, 0.3));
761 ASSERT_NO_THROW(matrix2 = matrixBuilder2.build());
764 rowGroupConstraint.
set(1);
767 columnConstraint2.
set(2);
768 columnConstraint2.
set(3);
772 ASSERT_TRUE(constrainedRowSum2 == std::vector<double>({0, 2.3}));
791 ASSERT_NO_THROW(matrix = matrixBuilder.
build());
798 std::vector<uint_fast64_t> rowGroupIndices = {0, 1, 2, 4, 5};
800 rowGroupConstraint.
set(2);
801 rowGroupConstraint.
set(3);
802 columnConstraint.
set(0);
803 columnConstraint.
set(3);
810 ASSERT_NO_THROW(matrixBuilder3.
addNextValue(0, 0, 0.5));
812 ASSERT_NO_THROW(matrixBuilder3.
addNextValue(2, 0, 0.1));
813 ASSERT_NO_THROW(matrixBuilder3.
addNextValue(2, 1, 0.3));
815 ASSERT_NO_THROW(matrix3 = matrixBuilder3.
build());
817 ASSERT_TRUE(matrix2 == matrix3);
819 std::vector<uint_fast64_t> rowGroupToIndexMapping = {0, 0, 1, 0};
825 ASSERT_NO_THROW(matrixBuilder5.
addNextValue(0, 1, 1.0));
826 ASSERT_NO_THROW(matrixBuilder5.
addNextValue(0, 2, 1.2));
827 ASSERT_NO_THROW(matrixBuilder5.
addNextValue(1, 0, 0.5));
828 ASSERT_NO_THROW(matrixBuilder5.
addNextValue(1, 1, 0.7));
829 ASSERT_NO_THROW(matrixBuilder5.
addNextValue(2, 2, 1.1));
830 ASSERT_NO_THROW(matrixBuilder5.
addNextValue(3, 0, 0.1));
831 ASSERT_NO_THROW(matrixBuilder5.
addNextValue(3, 1, 0.2));
832 ASSERT_NO_THROW(matrixBuilder5.
addNextValue(3, 3, 0.3));
834 ASSERT_NO_THROW(matrix5 = matrixBuilder5.
build());
836 ASSERT_TRUE(matrix4 == matrix5);
839TEST(SparseMatrix, RestrictRows) {
842 ASSERT_NO_THROW(matrixBuilder1.
addNextValue(0, 1, 1.0));
843 ASSERT_NO_THROW(matrixBuilder1.
addNextValue(0, 2, 1.2));
844 ASSERT_NO_THROW(matrixBuilder1.
addNextValue(1, 0, 0.5));
845 ASSERT_NO_THROW(matrixBuilder1.
addNextValue(1, 1, 0.7));
847 ASSERT_NO_THROW(matrixBuilder1.
addNextValue(2, 0, 0.5));
848 ASSERT_NO_THROW(matrixBuilder1.
addNextValue(3, 2, 1.1));
850 ASSERT_NO_THROW(matrixBuilder1.
addNextValue(4, 0, 0.1));
851 ASSERT_NO_THROW(matrixBuilder1.
addNextValue(4, 1, 0.2));
852 ASSERT_NO_THROW(matrixBuilder1.
addNextValue(6, 3, 0.3));
854 ASSERT_NO_THROW(matrix1 = matrixBuilder1.
build());
863 ASSERT_NO_THROW(matrix1Prime = matrix1.
restrictRows(constraint1));
867 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(0, 1, 1.0));
868 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(0, 2, 1.2));
869 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(1, 0, 0.5));
870 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(1, 1, 0.7));
872 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(2, 0, 0.5));
875 ASSERT_NO_THROW(matrix2 = matrixBuilder2.
build());
877 ASSERT_EQ(matrix2, matrix1Prime);
885 ASSERT_NO_THROW(matrix2Prime = matrix2.
restrictRows(constraint2,
true));
889 ASSERT_NO_THROW(matrixBuilder3.
addNextValue(0, 0, 0.5));
890 ASSERT_NO_THROW(matrixBuilder3.
addNextValue(0, 1, 0.7));
892 ASSERT_NO_THROW(matrixBuilder3.
addNextValue(1, 0, 0.5));
894 ASSERT_NO_THROW(matrix3 = matrixBuilder3.
build());
896 ASSERT_EQ(matrix3, matrix2Prime);
904 ASSERT_NO_THROW(matrix3Prime = matrix3.
restrictRows(constraint3,
true));
909 ASSERT_NO_THROW(matrixBuilder4.
addNextValue(0, 0, 0.5));
911 ASSERT_NO_THROW(matrix4 = matrixBuilder4.
build());
913 ASSERT_EQ(matrix4, matrix3Prime);
928 ASSERT_NO_THROW(matrix = matrixBuilder.
build());
934 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(0, 1, 0.5));
935 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(0, 2, 0.5));
936 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(0, 4, 0.1));
937 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(1, 0, 1.0));
938 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(1, 1, 0.7));
939 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(1, 4, 0.2));
940 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(2, 0, 1.2));
941 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(2, 3, 1.1));
942 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(3, 4, 0.3));
944 ASSERT_NO_THROW(matrix2 = matrixBuilder2.
build());
946 ASSERT_TRUE(transposeResult == matrix2);
949TEST(SparseMatrix, EquationSystem) {
956 ASSERT_NO_THROW(matrixBuilder.
addNextValue(2, 2, 0.99));
957 ASSERT_NO_THROW(matrixBuilder.
addNextValue(3, 3, 0.11));
959 ASSERT_NO_THROW(matrix = matrixBuilder.
build());
964 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(0, 0, 1 - 1.1));
965 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(0, 1, -1.2));
966 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(1, 1, 1 - 0.5));
967 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(1, 3, -0.7));
968 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(2, 0, -0.5));
969 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(2, 2, 1 - 0.99));
970 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(3, 3, 1 - 0.11));
972 ASSERT_NO_THROW(matrix2 = matrixBuilder2.
build());
974 ASSERT_TRUE(matrix == matrix2);
977TEST(SparseMatrix, JacobiDecomposition) {
984 ASSERT_NO_THROW(matrixBuilder.
addNextValue(2, 2, 0.99));
985 ASSERT_NO_THROW(matrixBuilder.
addNextValue(3, 3, 0.11));
987 ASSERT_NO_THROW(matrix = matrixBuilder.
build());
990 std::pair<storm::storage::SparseMatrix<double>, std::vector<double>> jacobiDecomposition = matrix.
getJacobiDecomposition();
997 ASSERT_NO_THROW(lu = luBuilder.
build());
999 std::vector<double> dinv = {1 / 1.1, 1 / 0.5, 1 / 0.99, 1 / 0.11};
1000 ASSERT_TRUE(lu == jacobiDecomposition.first);
1001 ASSERT_TRUE(dinv == jacobiDecomposition.second);
1004TEST(SparseMatrix, PointwiseMultiplicationVector) {
1006 ASSERT_NO_THROW(matrixBuilder.
addNextValue(0, 1, 1.0));
1007 ASSERT_NO_THROW(matrixBuilder.
addNextValue(0, 2, 1.2));
1008 ASSERT_NO_THROW(matrixBuilder.
addNextValue(1, 0, 0.5));
1009 ASSERT_NO_THROW(matrixBuilder.
addNextValue(1, 1, 0.7));
1010 ASSERT_NO_THROW(matrixBuilder.
addNextValue(2, 0, 0.5));
1011 ASSERT_NO_THROW(matrixBuilder.
addNextValue(3, 2, 1.1));
1012 ASSERT_NO_THROW(matrixBuilder.
addNextValue(4, 0, 0.1));
1013 ASSERT_NO_THROW(matrixBuilder.
addNextValue(4, 1, 0.2));
1014 ASSERT_NO_THROW(matrixBuilder.
addNextValue(4, 3, 0.3));
1016 ASSERT_NO_THROW(matrix = matrixBuilder.
build());
1019 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(0, 1, 1.0));
1020 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(0, 2, 1.2));
1021 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(1, 0, 0.5));
1022 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(1, 1, 0.7));
1023 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(2, 0, 0.5));
1024 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(3, 2, 1.1));
1025 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(4, 0, 0.1));
1026 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(4, 1, 0.2));
1027 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(4, 3, 0.3));
1029 ASSERT_NO_THROW(matrix2 = matrixBuilder2.
build());
1034 std::vector<double> correctResult = {1.0 * 1.0 + 1.2 * 1.2, 0.5 * 0.5 + 0.7 * 0.7, 0.5 * 0.5, 1.1 * 1.1, 0.1 * 0.1 + 0.2 * 0.2 + 0.3 * 0.3};
1035 ASSERT_TRUE(pointwiseProductRowSums == correctResult);
1038TEST(SparseMatrix, MatrixVectorMultiply) {
1040 ASSERT_NO_THROW(matrixBuilder.
addNextValue(0, 1, 1.0));
1041 ASSERT_NO_THROW(matrixBuilder.
addNextValue(0, 2, 1.2));
1042 ASSERT_NO_THROW(matrixBuilder.
addNextValue(1, 0, 0.5));
1043 ASSERT_NO_THROW(matrixBuilder.
addNextValue(1, 1, 0.7));
1044 ASSERT_NO_THROW(matrixBuilder.
addNextValue(2, 0, 0.5));
1045 ASSERT_NO_THROW(matrixBuilder.
addNextValue(3, 2, 1.1));
1046 ASSERT_NO_THROW(matrixBuilder.
addNextValue(4, 0, 0.1));
1047 ASSERT_NO_THROW(matrixBuilder.
addNextValue(4, 1, 0.2));
1048 ASSERT_NO_THROW(matrixBuilder.
addNextValue(4, 3, 0.3));
1050 ASSERT_NO_THROW(matrix = matrixBuilder.
build());
1052 std::vector<double> x = {1, 0.3, 1.4, 7.1};
1057 std::vector<double> correctResult = {1.0 * 0.3 + 1.2 * 1.4, 0.5 * 1 + 0.7 * 0.3, 0.5 * 1, 1.1 * 1.4, 0.1 * 1 + 0.2 * 0.3 + 0.3 * 7.1};
1059 for (std::size_t index = 0; index < correctResult.size(); ++index) {
1060 ASSERT_NEAR(result[index], correctResult[index], 1e-12);
1066 ASSERT_NO_THROW(matrixBuilder.
addNextValue(0, 1, 1.0));
1067 ASSERT_NO_THROW(matrixBuilder.
addNextValue(0, 2, 1.2));
1068 ASSERT_NO_THROW(matrixBuilder.
addNextValue(1, 0, 0.5));
1069 ASSERT_NO_THROW(matrixBuilder.
addNextValue(1, 1, 0.7));
1070 ASSERT_NO_THROW(matrixBuilder.
addNextValue(2, 0, 0.5));
1071 ASSERT_NO_THROW(matrixBuilder.
addNextValue(3, 2, 1.1));
1072 ASSERT_NO_THROW(matrixBuilder.
addNextValue(4, 0, 0.1));
1073 ASSERT_NO_THROW(matrixBuilder.
addNextValue(4, 1, 0.2));
1074 ASSERT_NO_THROW(matrixBuilder.
addNextValue(4, 3, 0.3));
1076 ASSERT_NO_THROW(matrix = matrixBuilder.
build());
1078 for (
auto const& entry : matrix.
getRow(4)) {
1079 if (entry.getColumn() == 0) {
1080 ASSERT_EQ(0.1, entry.getValue());
1081 }
else if (entry.getColumn() == 1) {
1082 ASSERT_EQ(0.2, entry.getValue());
1083 }
else if (entry.getColumn() == 3) {
1084 ASSERT_EQ(0.3, entry.getValue());
1091 if (it->getColumn() == 0) {
1092 ASSERT_EQ(0.1, it->getValue());
1093 }
else if (it->getColumn() == 1) {
1094 ASSERT_EQ(0.2, it->getValue());
1095 }
else if (it->getColumn() == 3) {
1096 ASSERT_EQ(0.3, it->getValue());
1105 ASSERT_NO_THROW(matrixBuilder.
addNextValue(0, 1, 1.0));
1106 ASSERT_NO_THROW(matrixBuilder.
addNextValue(0, 2, 1.2));
1107 ASSERT_NO_THROW(matrixBuilder.
addNextValue(1, 0, 0.5));
1108 ASSERT_NO_THROW(matrixBuilder.
addNextValue(1, 1, 0.7));
1109 ASSERT_NO_THROW(matrixBuilder.
addNextValue(3, 2, 1.1));
1110 ASSERT_NO_THROW(matrixBuilder.
addNextValue(4, 0, 0.1));
1111 ASSERT_NO_THROW(matrixBuilder.
addNextValue(4, 1, 0.2));
1112 ASSERT_NO_THROW(matrixBuilder.
addNextValue(4, 3, 0.3));
1114 ASSERT_NO_THROW(matrix = matrixBuilder.
build());
1117 ASSERT_EQ(0.1 + 0.2 + 0.3, matrix.
getRowSum(4));
1122 ASSERT_NO_THROW(matrixBuilder.
addNextValue(0, 1, 1.0));
1123 ASSERT_NO_THROW(matrixBuilder.
addNextValue(0, 2, 1.2));
1124 ASSERT_NO_THROW(matrixBuilder.
addNextValue(1, 0, 0.5));
1125 ASSERT_NO_THROW(matrixBuilder.
addNextValue(1, 1, 0.7));
1126 ASSERT_NO_THROW(matrixBuilder.
addNextValue(3, 2, 1.1));
1127 ASSERT_NO_THROW(matrixBuilder.
addNextValue(4, 0, 0.1));
1128 ASSERT_NO_THROW(matrixBuilder.
addNextValue(4, 1, 0.2));
1129 ASSERT_NO_THROW(matrixBuilder.
addNextValue(4, 3, 0.3));
1131 ASSERT_NO_THROW(matrix = matrixBuilder.
build());
1134 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(0, 1, 1.0));
1135 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(1, 0, 0.5));
1136 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(1, 1, 0.7));
1137 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(4, 0, 0.1));
1138 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(4, 1, 0.2));
1140 ASSERT_NO_THROW(matrix2 = matrixBuilder2.
build());
1145 ASSERT_NO_THROW(matrixBuilder3.
addNextValue(0, 3, 1.0));
1146 ASSERT_NO_THROW(matrixBuilder3.
addNextValue(1, 0, 0.5));
1147 ASSERT_NO_THROW(matrixBuilder3.
addNextValue(1, 1, 0.7));
1148 ASSERT_NO_THROW(matrixBuilder3.
addNextValue(4, 0, 0.1));
1149 ASSERT_NO_THROW(matrixBuilder3.
addNextValue(4, 1, 0.2));
1151 ASSERT_NO_THROW(matrix3 = matrixBuilder3.
build());
1159 ASSERT_NO_THROW(matrixBuilder.
addNextValue(0, 1, 1.0));
1160 ASSERT_NO_THROW(matrixBuilder.
addNextValue(0, 2, 1.2));
1161 ASSERT_NO_THROW(matrixBuilder.
addNextValue(1, 0, 0.5));
1162 ASSERT_NO_THROW(matrixBuilder.
addNextValue(1, 1, 0.7));
1163 ASSERT_NO_THROW(matrixBuilder.
addNextValue(3, 2, 1.1));
1164 ASSERT_NO_THROW(matrixBuilder.
addNextValue(4, 0, 0.1));
1165 ASSERT_NO_THROW(matrixBuilder.
addNextValue(4, 1, 0.2));
1166 ASSERT_NO_THROW(matrixBuilder.
addNextValue(4, 3, 0.3));
1168 ASSERT_NO_THROW(matrix = matrixBuilder.
build());
1170 std::vector<uint64_t> inversePermutation = {1, 4, 0, 3, 2};
1182TEST(SparseMatrix, PermuteRowGroupsAndColumns) {
1185 ASSERT_NO_THROW(matrixBuilder.
addNextValue(0, 1, 1.0));
1186 ASSERT_NO_THROW(matrixBuilder.
addNextValue(0, 2, 1.2));
1187 ASSERT_NO_THROW(matrixBuilder.
addNextValue(1, 0, 0.5));
1188 ASSERT_NO_THROW(matrixBuilder.
addNextValue(1, 1, 0.7));
1190 ASSERT_NO_THROW(matrixBuilder.
addNextValue(2, 0, 0.5));
1191 ASSERT_NO_THROW(matrixBuilder.
addNextValue(3, 2, 1.1));
1193 ASSERT_NO_THROW(matrixBuilder.
addNextValue(4, 0, 0.1));
1194 ASSERT_NO_THROW(matrixBuilder.
addNextValue(4, 1, 0.2));
1195 ASSERT_NO_THROW(matrixBuilder.
addNextValue(4, 3, 0.3));
1198 ASSERT_NO_THROW(matrix = matrixBuilder.
build());
1200 std::vector<uint64_t> permutation = {3, 0, 2, 1};
1201 std::vector<uint64_t> invertedPermutation = {1, 3, 2, 0};
1207 ASSERT_NO_THROW(expectedBuilder.
addNextValue(0, 3, 0.5));
1208 ASSERT_NO_THROW(expectedBuilder.
addNextValue(1, 2, 1.1));
1211 ASSERT_NO_THROW(expectedBuilder.
addNextValue(2, 3, 0.1));
1212 ASSERT_NO_THROW(expectedBuilder.
addNextValue(2, 0, 0.2));
1213 ASSERT_NO_THROW(expectedBuilder.
addNextValue(2, 1, 0.3));
1215 ASSERT_NO_THROW(expectedBuilder.
addNextValue(3, 0, 1.0));
1216 ASSERT_NO_THROW(expectedBuilder.
addNextValue(3, 2, 1.2));
1217 ASSERT_NO_THROW(expectedBuilder.
addNextValue(4, 3, 0.5));
1218 ASSERT_NO_THROW(expectedBuilder.
addNextValue(4, 0, 0.7));
1220 ASSERT_NO_THROW(expectedMatrix = expectedBuilder.
build());
1221 EXPECT_EQ(expectedMatrix, matrixPerm);
1223 auto matrixPerm2 = matrixPerm.permuteRowGroupsAndColumns(permutation, invertedPermutation);
1224 EXPECT_EQ(matrix, matrixPerm2);
1227TEST(SparseMatrix, DropZeroEntries) {
1230 ASSERT_NO_THROW(matrixBuilder.
addNextValue(0, 1, 1.0));
1231 ASSERT_NO_THROW(matrixBuilder.
addNextValue(0, 2, 1.2));
1233 ASSERT_NO_THROW(matrixBuilder.
addNextValue(1, 0, 0.5));
1234 ASSERT_NO_THROW(matrixBuilder.
addNextValue(1, 1, 1.1));
1235 ASSERT_NO_THROW(matrixBuilder.
addNextValue(1, 2, 0.5));
1237 ASSERT_NO_THROW(matrixBuilder.
addNextValue(2, 0, 0.1));
1238 ASSERT_NO_THROW(matrixBuilder.
addNextValue(3, 1, 0.2));
1239 ASSERT_NO_THROW(matrixBuilder.
addNextValue(3, 2, 0.3));
1241 ASSERT_NO_THROW(matrix = matrixBuilder.
build());
1244 absorbingRows.
set(0);
1250 ASSERT_NO_THROW(matrixBuilderX.
addNextValue(0, 1, 1.0));
1251 ASSERT_NO_THROW(matrixBuilderX.
addNextValue(0, 2, 1.2));
1253 ASSERT_NO_THROW(matrixBuilderX.
addNextValue(1, 0, 0.5));
1254 ASSERT_NO_THROW(matrixBuilderX.
addNextValue(1, 1, 1.1));
1255 ASSERT_NO_THROW(matrixBuilderX.
addNextValue(1, 2, 0.5));
1257 ASSERT_NO_THROW(matrixBuilderX.
addNextValue(2, 0, 0.1));
1258 ASSERT_NO_THROW(matrixBuilderX.
addNextValue(3, 1, 0.2));
1259 ASSERT_NO_THROW(matrixBuilderX.
addNextValue(3, 2, 0.3));
1261 ASSERT_NO_THROW(matrixX = matrixBuilderX.
build());
1267 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(0, 0, 1.0));
1269 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(1, 0, 0.5));
1270 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(1, 1, 1.1));
1271 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(1, 2, 0.5));
1273 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(2, 0, 0.1));
1274 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(3, 1, 0.2));
1275 ASSERT_NO_THROW(matrixBuilder2.
addNextValue(3, 2, 0.3));
1277 ASSERT_NO_THROW(matrix2 = matrixBuilder2.
build());
1279 ASSERT_TRUE(matrix == matrix2);
1282 ASSERT_TRUE(matrixX == matrix2);
1291 ASSERT_NO_THROW(matrixBuilder3.
addNextValue(0, 0, 1.0));
1293 ASSERT_NO_THROW(matrixBuilder3.
addNextValue(1, 1, 1.0));
1295 ASSERT_NO_THROW(matrixBuilder3.
addNextValue(2, 0, 0.1));
1296 ASSERT_NO_THROW(matrixBuilder3.
addNextValue(3, 1, 0.2));
1297 ASSERT_NO_THROW(matrixBuilder3.
addNextValue(3, 2, 0.3));
1299 ASSERT_NO_THROW(matrix3 = matrixBuilder3.
build());
1301 ASSERT_TRUE(matrix == matrix3);
1304 ASSERT_TRUE(matrixX == matrix3);
1308 absorbingRowGroups.
set(2);
1316 ASSERT_NO_THROW(matrixBuilder4.
addNextValue(0, 0, 1.0));
1318 ASSERT_NO_THROW(matrixBuilder4.
addNextValue(1, 1, 1.0));
1320 ASSERT_NO_THROW(matrixBuilder4.
addNextValue(2, 2, 1.0));
1321 ASSERT_NO_THROW(matrixBuilder4.
addNextValue(3, 2, 1.0));
1323 ASSERT_NO_THROW(matrix4 = matrixBuilder4.
build());
1325 ASSERT_TRUE(matrix == matrix4);
1328 ASSERT_TRUE(matrixX == matrix4);
1332TEST(SparseMatrix, isProbabilistic) {
1342 ASSERT_NO_THROW(matrix = builder.
build());
1346 for (
auto& entry : matrix) {
1352TEST(SparseMatrix, EqualityIgnoresExplicitZeros) {
1358 auto matrix1 = builder1.
build();
1363 auto matrix2 = builder2.
build();
1365 EXPECT_TRUE(matrix1 == matrix2);
1366 EXPECT_TRUE(matrix2 == matrix1);
1367 EXPECT_TRUE(matrix1 == matrix1);
1373 auto matrix3 = builder3.
build();
1374 EXPECT_FALSE(matrix1 == matrix3);
1375 EXPECT_FALSE(matrix3 == matrix2);
1379 auto matrix4 = builder4.
build();
1380 EXPECT_FALSE(matrix4 == matrix2);
1381 EXPECT_FALSE(matrix2 == matrix4);
TEST(SparseMatrixBuilder, CreationEmpty)
A bit vector that is internally represented as a vector of 64-bit values.
void set(uint64_t index, bool value=true)
Sets the given truth value at the given index.
A class that can be used to build a sparse matrix by adding value by value.
AccumulationMode
Specifies how values that are added for the same row and column are combined.
void addNextValue(index_type row, index_type column, value_type const &value)
Sets the matrix entry at the given row and column to the given value.
void newRowGroup(index_type startingRow)
Starts a new row group in the matrix.
index_type getLastColumn() const
Retrieves the most recently used row.
void addDiagonalEntry(index_type row, ValueType const &value)
Makes sure that a diagonal entry will be inserted at the given row.
void setAccumulationMode(AccumulationMode mode)
Sets how values that are added for the same row and column are combined.
SparseMatrix< value_type > build(index_type overriddenRowCount=0, index_type overriddenColumnCount=0, index_type overriddenRowGroupCount=0)
AccumulationMode getAccumulationMode() const
Retrieves how values that are added for the same row and column are combined.
A class that holds a possibly non-square matrix in the compressed row storage format.
void convertToEquationSystem()
Transforms the matrix into an equation system.
const_rows getRow(index_type row) const
Returns an object representing the given row.
SparseMatrix selectRowsFromRowGroups(std::vector< index_type > const &rowGroupToRowIndexMapping, bool insertDiagonalEntries=true) const
Selects exactly one row from each row group of this matrix and returns the resulting matrix.
index_type getEntryCount() const
Returns the number of entries in the matrix.
bool isProbabilistic(ValueType const &tolerance, storm::OptionalRef< std::string > reason={}) const
Checks for each row whether (i) each entry is between zero and one and (ii) all entries sum to one.
void makeRowsAbsorbing(storm::storage::BitVector const &rows, bool dropZeroEntries=false)
This function makes the given rows absorbing.
void multiplyWithVector(std::vector< value_type > const &vector, std::vector< value_type > &result, std::vector< value_type > const *summand=nullptr) const
Multiplies the matrix with the given vector and writes the result to the given result vector.
SparseMatrix getSubmatrix(bool useGroups, storm::storage::BitVector const &rowConstraint, storm::storage::BitVector const &columnConstraint, bool insertDiagonalEntries=false, storm::storage::BitVector const &makeZeroColumns=storm::storage::BitVector()) const
Creates a submatrix of the current matrix by dropping all rows and columns whose bits are not set to ...
const_iterator begin(index_type row) const
Retrieves an iterator that points to the beginning of the given row.
std::vector< value_type > getConstrainedRowSumVector(storm::storage::BitVector const &rowConstraint, storm::storage::BitVector const &columnConstraint) const
Computes a vector whose i-th entry is the sum of the entries in the i-th selected row where only thos...
SparseMatrix permuteRows(std::vector< index_type > const &inversePermutation) const
Permute rows of the matrix according to the vector.
SparseMatrix restrictRows(storm::storage::BitVector const &rowsToKeep, bool allowEmptyRowGroups=false) const
Restrict rows in grouped rows matrix.
value_type getRowSum(index_type row) const
Computes the sum of the entries in a given row.
const_iterator end(index_type row) const
Retrieves an iterator that points past the end of the given row.
SparseMatrix permuteRowGroupsAndColumns(std::vector< index_type > const &inverseRowGroupPermutation, std::vector< index_type > const &columnPermutation) const
Permutes row groups and columns of the matrix according to the given permutations.
index_type getRowGroupCount() const
Returns the number of row groups in the matrix.
void dropZeroEntries()
Removes all zero entries from this.
bool isSubmatrixOf(SparseMatrix< OtherValueType > const &matrix) const
Checks if the current matrix is a submatrix of the given matrix, where a matrix A is called a submatr...
void makeRowGroupsAbsorbing(storm::storage::BitVector const &rowGroupConstraint, bool dropZeroEntries=false)
This function makes the groups of rows given by the bit vector absorbing.
index_type getColumnCount() const
Returns the number of columns of the matrix.
std::pair< storm::storage::SparseMatrix< value_type >, std::vector< value_type > > getJacobiDecomposition() const
Calculates the Jacobi decomposition of this sparse matrix.
void makeRowDirac(index_type row, index_type column, bool dropZeroEntries=false)
This function makes the given row Dirac.
std::vector< ResultValueType > getPointwiseProductRowSumVector(storm::storage::SparseMatrix< OtherValueType > const &otherMatrix) const
Performs a pointwise matrix multiplication of the matrix with the given matrix and returns a vector c...
void makeRowGroupingTrivial()
Makes the row grouping of this matrix trivial.
std::vector< index_type > const & getRowGroupIndices() const
Returns the grouping of rows of this matrix.
std::vector< MatrixEntry< index_type, value_type > >::iterator iterator
std::vector< value_type > getConstrainedRowGroupSumVector(storm::storage::BitVector const &rowGroupConstraint, storm::storage::BitVector const &columnConstraint) const
Computes a vector whose entries represent the sums of selected columns for all rows in selected row g...
storm::storage::SparseMatrix< value_type > transpose(bool joinGroups=false, bool keepZeros=false) const
Transposes the matrix.
index_type getRowCount() const
Returns the number of rows of the matrix.
typename storm::storage::SparseMatrixBuilder< ValueType >::AccumulationMode AccumulationMode
std::vector< index_type > invertPermutation(std::vector< index_type > const &permutation)
Inverts the given permutation.
ValueType abs(ValueType const &number)
ValueType sqrt(ValueType const &number)
#define STORM_SILENT_ASSERT_THROW(statement, expected_exception)