30 : matrix(matrix), originalToSubColumnIndex(matrix.getColumnCount(),
std::numeric_limits<uint64_t>::max()) {
48 template<
typename RowConstra
intType,
typename ColumnConstra
intType>
50 bool const insertDiagonalElement,
52 return build<false>(rowConstraint, columnConstraint, insertDiagonalElement, makeZeroColumns);
64 template<
typename RowConstra
intType,
typename ColumnConstra
intType>
66 bool const insertDiagonalElement,
68 return build<true>(rowGroupConstraint, columnConstraint, insertDiagonalElement, makeZeroColumns);
72 static constexpr uint64_t NotInSubmatrix = std::numeric_limits<uint64_t>::max();
81 template<
typename Constra
intType>
82 static bool isStrictlyAscending(ConstraintType
const& constraint) {
84 uint64_t previous = 0;
85 for (uint64_t index : constraint) {
86 if (!first && index <= previous) {
96 template<
typename Constra
intType>
97 struct ColumnMappingGuard {
98 ColumnMappingGuard(std::vector<uint64_t>& mapping, ConstraintType
const& columnConstraint) : mapping(mapping), columnConstraint(columnConstraint) {}
99 ~ColumnMappingGuard() {
100 for (uint64_t col : columnConstraint) {
101 mapping[col] = NotInSubmatrix;
104 std::vector<uint64_t>& mapping;
105 ConstraintType
const& columnConstraint;
113 template<
bool GroupMode,
typename Constra
intType,
typename RowFunc,
typename NewGroupFunc>
114 void forEachSelectedRow(ConstraintType
const& rowConstraint, RowFunc&& f, NewGroupFunc&& g)
const {
116 if (matrix.hasTrivialRowGrouping()) {
118 for (uint64_t row : rowConstraint) {
122 auto const& groups = matrix.getRowGroupIndices();
123 if constexpr (GroupMode) {
124 for (uint64_t group : rowConstraint) {
126 for (uint64_t row = groups[group], end = groups[group + 1]; row < end; ++row) {
134 index_type currentGroup = std::numeric_limits<index_type>::max();
136 for (uint64_t row : rowConstraint) {
137 if (row >= groupEnd) {
139 auto const searchStart = currentGroup == std::numeric_limits<index_type>::max() ? groups.begin() : groups.begin() + currentGroup + 1;
140 auto const it = std::upper_bound(searchStart, groups.end(), row);
141 currentGroup = std::distance(groups.begin(), it) - 1;
142 groupEnd = groups[currentGroup + 1];
151 template<
bool GroupMode,
typename RowConstra
intType,
typename ColumnConstra
intType>
152 SparseMatrix<ValueType> build(RowConstraintType
const& rowConstraint, ColumnConstraintType
const& columnConstraint,
bool const insertDiagonalElement,
154 STORM_LOG_THROW(!(rowConstraint.begin() == rowConstraint.end()) && !(columnConstraint.begin() == columnConstraint.end()),
155 storm::exceptions::InvalidArgumentException,
"Cannot build empty submatrix.");
156 STORM_LOG_ASSERT(isStrictlyAscending(rowConstraint),
"Row (group) constraint must be iterated in strictly ascending order.");
157 STORM_LOG_ASSERT(isStrictlyAscending(columnConstraint),
"Column constraint must be iterated in strictly ascending order.");
158 STORM_LOG_ASSERT(!makeZeroColumns || makeZeroColumns->size() == matrix.getColumnCount(),
"Dimension mismatch.");
159 bool const hasGroups = !matrix.hasTrivialRowGrouping();
165 for (uint64_t col : columnConstraint) {
166 if (!makeZeroColumns || !makeZeroColumns->get(col)) {
167 originalToSubColumnIndex[col] = subColumnCount;
171 ColumnMappingGuard<ColumnConstraintType> guard(originalToSubColumnIndex, columnConstraint);
175 forEachSelectedRow<GroupMode>(
179 sizes.entryBound += (matrix.end(row) - matrix.begin(row)) + (insertDiagonalElement ? 1 : 0);
181 [&](uint64_t) { ++sizes.groups; });
184 std::vector<index_type> rowIndications;
185 rowIndications.reserve(sizes.rows + 1);
186 std::vector<entry_type> entries;
187 entries.reserve(sizes.entryBound);
188 boost::optional<std::vector<index_type>> rowGroupIndices;
190 rowGroupIndices.emplace();
191 rowGroupIndices->reserve(sizes.groups + 1);
193 forEachSelectedRow<GroupMode>(
196 rowIndications.push_back(entries.size());
197 copyRow(row, diagonalIndex, subColumnCount, insertDiagonalElement, entries);
201 rowGroupIndices->push_back(rowIndications.size());
204 rowIndications.push_back(entries.size());
206 rowGroupIndices->push_back(rowIndications.size() - 1);
209 if (entries.size() < sizes.entryBound - sizes.entryBound / 4) {
210 entries.shrink_to_fit();
212 return SparseMatrix<ValueType>(subColumnCount, std::move(rowIndications), std::move(entries), std::move(rowGroupIndices));
218 void copyRow(uint64_t row,
index_type diagonalIndex,
index_type subColumnCount,
bool insertDiagonalElement, std::vector<entry_type>& entries)
const {
219 bool diagonalMissing = insertDiagonalElement && diagonalIndex < subColumnCount;
220 for (
auto it = matrix.begin(row), ite = matrix.end(row); it != ite; ++it) {
221 uint64_t
const subColumn = originalToSubColumnIndex[it->getColumn()];
222 if (subColumn == NotInSubmatrix) {
225 if (diagonalMissing && subColumn >= diagonalIndex) {
226 if (subColumn > diagonalIndex) {
229 diagonalMissing =
false;
231 entries.emplace_back(subColumn, it->getValue());
233 if (diagonalMissing) {
238 SparseMatrix<ValueType>
const& matrix;
240 mutable std::vector<uint64_t> originalToSubColumnIndex;