#include "src/storage/dd/Add.h" #include #include "src/storage/dd/DdMetaVariable.h" #include "src/storage/dd/DdManager.h" #include "src/storage/dd/Odd.h" #include "src/storage/SparseMatrix.h" #include "src/utility/constants.h" #include "src/utility/macros.h" #include "src/exceptions/InvalidArgumentException.h" namespace storm { namespace dd { template Add::Add(DdManager const& ddManager, InternalAdd const& internalAdd, std::set const& containedMetaVariables) : Dd(ddManager, containedMetaVariables), internalAdd(internalAdd) { // Intentionally left empty. } template bool Add::operator==(Add const& other) const { return internalAdd == other.internalAdd; } template bool Add::operator!=(Add const& other) const { return internalAdd != other.internalAdd; } template Add Add::ite(Add const& thenAdd, Add const& elseAdd) const { std::set metaVariables = Dd::joinMetaVariables(thenAdd, elseAdd); metaVariables.insert(this->getContainedMetaVariables().begin(), this->getContainedMetaVariables().end()); return Add(this->getDdManager(), internalAdd.ite(thenAdd.internalAdd, elseAdd.internalAdd), metaVariables); } template Add Add::operator+(Add const& other) const { return Add(this->getDdManager(), internalAdd + other.internalAdd, Dd::joinMetaVariables(*this, other)); } template Add& Add::operator+=(Add const& other) { this->addMetaVariables(other.getContainedMetaVariables()); internalAdd += other.internalAdd; return *this; } template Add Add::operator*(Add const& other) const { return Add(this->getDdManager(), internalAdd * other.internalAdd, Dd::joinMetaVariables(*this, other)); } template Add& Add::operator*=(Add const& other) { this->addMetaVariables(other.getContainedMetaVariables()); internalAdd *= other.internalAdd; return *this; } template Add Add::operator-(Add const& other) const { return Add(this->getDdManager(), internalAdd - other.internalAdd, Dd::joinMetaVariables(*this, other)); } template Add Add::operator-() const { return this->getDdManager().template getAddZero() - *this; } template Add& Add::operator-=(Add const& other) { this->addMetaVariables(other.getContainedMetaVariables()); internalAdd -= other.internalAdd; return *this; } template Add Add::operator/(Add const& other) const { return Add(this->getDdManager(), internalAdd / other.internalAdd, Dd::joinMetaVariables(*this, other)); } template Add& Add::operator/=(Add const& other) { this->addMetaVariables(other.getContainedMetaVariables()); internalAdd /= other.internalAdd; return *this; } template Bdd Add::equals(Add const& other) const { return Bdd(this->getDdManager(), internalAdd.equals(other), Dd::joinMetaVariables(*this, other)); } template Bdd Add::notEquals(Add const& other) const { return Bdd(this->getDdManager(), internalAdd.notEquals(other), Dd::joinMetaVariables(*this, other)); } template Bdd Add::less(Add const& other) const { return Bdd(this->getDdManager(), internalAdd.less(other), Dd::joinMetaVariables(*this, other)); } template Bdd Add::lessOrEqual(Add const& other) const { return Bdd(this->getDdManager(), internalAdd.lessOrEqual(other), Dd::joinMetaVariables(*this, other)); } template Bdd Add::greater(Add const& other) const { return Bdd(this->getDdManager(), internalAdd.greater(other), Dd::joinMetaVariables(*this, other)); } template Bdd Add::greaterOrEqual(Add const& other) const { return Bdd(this->getDdManager(), internalAdd.greaterOrEqual(other), Dd::joinMetaVariables(*this, other)); } template Add Add::pow(Add const& other) const { return Add(this->getDdManager(), internalAdd.pow(other), Dd::joinMetaVariables(*this, other)); } template Add Add::mod(Add const& other) const { return Add(this->getDdManager(), internalAdd.mod(other), Dd::joinMetaVariables(*this, other)); } template Add Add::logxy(Add const& other) const { return Add(this->getDdManager(), internalAdd.logxy(other), Dd::joinMetaVariables(*this, other)); } template Add Add::floor() const { return Add(this->getDdManager(), internalAdd.floor(), this->getContainedMetaVariables()); } template Add Add::ceil() const { return Add(this->getDdManager(), internalAdd.ceil(), this->getContainedMetaVariables()); } template Add Add::minimum(Add const& other) const { return Add(this->getDdManager(), internalAdd.minimum(other), Dd::joinMetaVariables(*this, other)); } template Add Add::maximum(Add const& other) const { return Add(this->getDdManager(), internalAdd.maximum(other), Dd::joinMetaVariables(*this, other)); } template Add Add::sumAbstract(std::set const& metaVariables) const { Bdd cube = Bdd::getCube(this->getDdManager(), metaVariables); return Add(this->getDdManager(), internalAdd.sumAbstract(cube), Dd::subtractMetaVariables(*this, cube)); } template Add Add::minAbstract(std::set const& metaVariables) const { Bdd cube = Bdd::getCube(this->getDdManager(), metaVariables); return Add(this->getDdManager(), internalAdd.minAbstract(cube), Dd::subtractMetaVariables(*this, cube)); } template Add Add::maxAbstract(std::set const& metaVariables) const { Bdd cube = Bdd::getCube(this->getDdManager(), metaVariables); return Add(this->getDdManager(), internalAdd.maxAbstract(cube), Dd::subtractMetaVariables(*this, cube)); } template bool Add::equalModuloPrecision(Add const& other, double precision, bool relative) const { return internalAdd.equalModuloPrecision(other, precision, relative); } template Add Add::swapVariables(std::vector> const& metaVariablePairs) const { std::set newContainedMetaVariables; std::vector> from; std::vector> to; for (auto const& metaVariablePair : metaVariablePairs) { DdMetaVariable const& variable1 = this->getDdManager().getMetaVariable(metaVariablePair.first); DdMetaVariable const& variable2 = this->getDdManager().getMetaVariable(metaVariablePair.second); // Keep track of the contained meta variables in the DD. if (this->containsMetaVariable(metaVariablePair.first)) { newContainedMetaVariables.insert(metaVariablePair.second); } if (this->containsMetaVariable(metaVariablePair.second)) { newContainedMetaVariables.insert(metaVariablePair.first); } for (auto const& ddVariable : variable1.getDdVariables()) { from.push_back(ddVariable); } for (auto const& ddVariable : variable2.getDdVariables()) { to.push_back(ddVariable); } } STORM_LOG_THROW(from.size() == to.size(), storm::exceptions::InvalidArgumentException, "Unable to swap mismatching meta variables."); return Add(this->getDdManager(), internalAdd.swapVariables(from, to), newContainedMetaVariables); } template Add Add::multiplyMatrix(Add const& otherMatrix, std::set const& summationMetaVariables) const { // Create the CUDD summation variables. std::vector> summationDdVariables; for (auto const& metaVariable : summationMetaVariables) { for (auto const& ddVariable : this->getDdManager().getMetaVariable(metaVariable).getDdVariables()) { summationDdVariables.push_back(ddVariable); } } std::set unionOfMetaVariables = Dd::joinMetaVariables(*this, otherMatrix); std::set containedMetaVariables; std::set_difference(unionOfMetaVariables.begin(), unionOfMetaVariables.end(), summationMetaVariables.begin(), summationMetaVariables.end(), std::inserter(containedMetaVariables, containedMetaVariables.begin())); return Add(this->getDdManager(), internalAdd.multiplyMatrix(otherMatrix, summationDdVariables), containedMetaVariables); } template Bdd Add::greater(ValueType const& value) const { return Bdd(this->getDdManager(), internalAdd.greater(value), this->getContainedMetaVariables()); } template Bdd Add::greaterOrEqual(ValueType const& value) const { return Bdd(this->getDdManager(), internalAdd.greaterOrEqual(value), this->getContainedMetaVariables()); } template Bdd Add::less(ValueType const& value) const { return Bdd(this->getDdManager(), internalAdd.less(value), this->getContainedMetaVariables()); } template Bdd Add::lessOrEqual(ValueType const& value) const { return Bdd(this->getDdManager(), internalAdd.lessOrEqual(value), this->getContainedMetaVariables()); } template Bdd Add::notZero() const { return Bdd(this->getDdManager(), internalAdd.notZero(), this->getContainedMetaVariables()); } template Add Add::constrain(Add const& constraint) const { return Add(this->getDdManager(), internalAdd.constrain(constraint), Dd::joinMetaVariables(*this, constraint)); } template Add Add::restrict(Add const& constraint) const { return Add(this->getDdManager(), internalAdd.restrict(constraint), Dd::joinMetaVariables(*this, constraint)); } template Bdd Add::getSupport() const { return Bdd(this->getDdManager(), internalAdd.getSupport(), this->getContainedMetaVariables()); } template uint_fast64_t Add::getNonZeroCount() const { std::size_t numberOfDdVariables = 0; for (auto const& metaVariable : this->getContainedMetaVariables()) { numberOfDdVariables += this->getDdManager().getMetaVariable(metaVariable).getNumberOfDdVariables(); } return internalAdd.getNonZeroCount(numberOfDdVariables); } template uint_fast64_t Add::getLeafCount() const { return internalAdd.getLeafCount(); } template uint_fast64_t Add::getNodeCount() const { return internalAdd.getNodeCount(); } template ValueType Add::getMin() const { return internalAdd.getMin(); } template ValueType Add::getMax() const { return internalAdd.getMax(); } template void Add::setValue(storm::expressions::Variable const& metaVariable, int_fast64_t variableValue, ValueType const& targetValue) { std::map metaVariableToValueMap; metaVariableToValueMap.emplace(metaVariable, variableValue); this->setValue(metaVariableToValueMap, targetValue); } template void Add::setValue(storm::expressions::Variable const& metaVariable1, int_fast64_t variableValue1, storm::expressions::Variable const& metaVariable2, int_fast64_t variableValue2, ValueType const& targetValue) { std::map metaVariableToValueMap; metaVariableToValueMap.emplace(metaVariable1, variableValue1); metaVariableToValueMap.emplace(metaVariable2, variableValue2); this->setValue(metaVariableToValueMap, targetValue); } template void Add::setValue(std::map const& metaVariableToValueMap, ValueType const& targetValue) { Bdd valueEncoding = this->getDdManager().getBddOne(); for (auto const& nameValuePair : metaVariableToValueMap) { valueEncoding &= this->getDdManager().getEncoding(nameValuePair.first, nameValuePair.second); // Also record that the DD now contains the meta variable. this->addMetaVariable(nameValuePair.first); } internalAdd = valueEncoding.template toAdd().ite(this->getDdManager().getConstant(targetValue), *this); } template ValueType Add::getValue(std::map const& metaVariableToValueMap) const { std::set remainingMetaVariables(this->getContainedMetaVariables()); Bdd valueEncoding = this->getDdManager().getBddOne(); for (auto const& nameValuePair : metaVariableToValueMap) { valueEncoding &= this->getDdManager().getEncoding(nameValuePair.first, nameValuePair.second); if (this->containsMetaVariable(nameValuePair.first)) { remainingMetaVariables.erase(nameValuePair.first); } } STORM_LOG_THROW(remainingMetaVariables.empty(), storm::exceptions::InvalidArgumentException, "Cannot evaluate function for which not all inputs were given."); Add value = *this * valueEncoding.template toAdd(); value = value.sumAbstract(this->getContainedMetaVariables()); return value.getMax(); } template bool Add::isOne() const { return internalAdd.isOne(); } template bool Add::isZero() const { return internalAdd.isZero(); } template bool Add::isConstant() const { return internalAdd.isConstant(); } template uint_fast64_t Add::getIndex() const { return internalAdd.getIndex(); } template std::vector Add::toVector() const { return this->toVector(this->createOdd()); } template std::vector Add::toVector(Odd const& rowOdd) const { std::vector result(rowOdd.getTotalOffset()); std::vector ddVariableIndices = this->getSortedVariableIndices(); internalAdd.composeWithExplicitVector(rowOdd, ddVariableIndices, result, std::plus()); return result; } template storm::storage::SparseMatrix Add::toMatrix() const { std::set rowVariables; std::set columnVariables; for (auto const& variable : this->getContainedMetaVariables()) { if (variable.getName().size() > 0 && variable.getName().back() == '\'') { columnVariables.insert(variable); } else { rowVariables.insert(variable); } } return toMatrix(rowVariables, columnVariables, this->sumAbstract(rowVariables).createOdd(), this->sumAbstract(columnVariables).createOdd()); } template storm::storage::SparseMatrix Add::toMatrix(storm::dd::Odd const& rowOdd, storm::dd::Odd const& columnOdd) const { std::set rowMetaVariables; std::set columnMetaVariables; for (auto const& variable : this->getContainedMetaVariables()) { if (variable.getName().size() > 0 && variable.getName().back() == '\'') { columnMetaVariables.insert(variable); } else { rowMetaVariables.insert(variable); } } return toMatrix(rowMetaVariables, columnMetaVariables, rowOdd, columnOdd); } template storm::storage::SparseMatrix Add::toMatrix(std::set const& rowMetaVariables, std::set const& columnMetaVariables, storm::dd::Odd const& rowOdd, storm::dd::Odd const& columnOdd) const { std::vector ddRowVariableIndices; std::vector ddColumnVariableIndices; for (auto const& variable : rowMetaVariables) { DdMetaVariable const& metaVariable = this->getDdManager().getMetaVariable(variable); for (auto const& ddVariable : metaVariable.getDdVariables()) { ddRowVariableIndices.push_back(ddVariable.getIndex()); } } std::sort(ddRowVariableIndices.begin(), ddRowVariableIndices.end()); for (auto const& variable : columnMetaVariables) { DdMetaVariable const& metaVariable = this->getDdManager().getMetaVariable(variable); for (auto const& ddVariable : metaVariable.getDdVariables()) { ddColumnVariableIndices.push_back(ddVariable.getIndex()); } } std::sort(ddColumnVariableIndices.begin(), ddColumnVariableIndices.end()); // Prepare the vectors that represent the matrix. std::vector rowIndications(rowOdd.getTotalOffset() + 1); std::vector> columnsAndValues(this->getNonZeroCount()); // Create a trivial row grouping. std::vector trivialRowGroupIndices(rowIndications.size()); uint_fast64_t i = 0; for (auto& entry : trivialRowGroupIndices) { entry = i; ++i; } // Use the toMatrix function to compute the number of elements in each row. Using the flag, we prevent // it from actually generating the entries in the entry vector. internalAdd.toMatrixComponents(trivialRowGroupIndices, rowIndications, columnsAndValues, rowOdd, columnOdd, ddRowVariableIndices, ddColumnVariableIndices, false); // TODO: counting might be faster by just summing over the primed variables and then using the ODD to convert // the resulting (DD) vector to an explicit vector. // Now that we computed the number of entries in each row, compute the corresponding offsets in the entry vector. uint_fast64_t tmp = 0; uint_fast64_t tmp2 = 0; for (uint_fast64_t i = 1; i < rowIndications.size(); ++i) { tmp2 = rowIndications[i]; rowIndications[i] = rowIndications[i - 1] + tmp; std::swap(tmp, tmp2); } rowIndications[0] = 0; // Now actually fill the entry vector. internalAdd.toMatrixComponents(trivialRowGroupIndices, rowIndications, columnsAndValues, rowOdd, columnOdd, ddRowVariableIndices, ddColumnVariableIndices, true); // Since the last call to toMatrixRec modified the rowIndications, we need to restore the correct values. for (uint_fast64_t i = rowIndications.size() - 1; i > 0; --i) { rowIndications[i] = rowIndications[i - 1]; } rowIndications[0] = 0; // Construct matrix and return result. return storm::storage::SparseMatrix(columnOdd.getTotalOffset(), std::move(rowIndications), std::move(columnsAndValues), std::move(trivialRowGroupIndices), false); } template storm::storage::SparseMatrix Add::toMatrix(std::set const& groupMetaVariables, storm::dd::Odd const& rowOdd, storm::dd::Odd const& columnOdd) const { std::set rowMetaVariables; std::set columnMetaVariables; for (auto const& variable : this->getContainedMetaVariables()) { // If the meta variable is a group meta variable, we do not insert it into the set of row/column meta variables. if (groupMetaVariables.find(variable) != groupMetaVariables.end()) { continue; } if (variable.getName().size() > 0 && variable.getName().back() == '\'') { columnMetaVariables.insert(variable); } else { rowMetaVariables.insert(variable); } } // Create the canonical row group sizes and build the matrix. return toMatrix(rowMetaVariables, columnMetaVariables, groupMetaVariables, rowOdd, columnOdd); } template storm::storage::SparseMatrix Add::toMatrix(std::set const& rowMetaVariables, std::set const& columnMetaVariables, std::set const& groupMetaVariables, storm::dd::Odd const& rowOdd, storm::dd::Odd const& columnOdd) const { std::vector ddRowVariableIndices; std::vector ddColumnVariableIndices; std::vector ddGroupVariableIndices; std::set rowAndColumnMetaVariables; for (auto const& variable : rowMetaVariables) { DdMetaVariable const& metaVariable = this->getDdManager().getMetaVariable(variable); for (auto const& ddVariable : metaVariable.getDdVariables()) { ddRowVariableIndices.push_back(ddVariable.getIndex()); } rowAndColumnMetaVariables.insert(variable); } std::sort(ddRowVariableIndices.begin(), ddRowVariableIndices.end()); for (auto const& variable : columnMetaVariables) { DdMetaVariable const& metaVariable = this->getDdManager().getMetaVariable(variable); for (auto const& ddVariable : metaVariable.getDdVariables()) { ddColumnVariableIndices.push_back(ddVariable.getIndex()); } rowAndColumnMetaVariables.insert(variable); } std::sort(ddColumnVariableIndices.begin(), ddColumnVariableIndices.end()); for (auto const& variable : groupMetaVariables) { DdMetaVariable const& metaVariable = this->getDdManager().getMetaVariable(variable); for (auto const& ddVariable : metaVariable.getDdVariables()) { ddGroupVariableIndices.push_back(ddVariable.getIndex()); } } std::sort(ddGroupVariableIndices.begin(), ddGroupVariableIndices.end()); Bdd columnVariableCube = Bdd::getCube(this->getDdManager(), columnMetaVariables); // Start by computing the offsets (in terms of rows) for each row group. Add stateToNumberOfChoices = this->notZero().existsAbstract(columnMetaVariables).template toAdd().sumAbstract(groupMetaVariables); std::vector rowGroupIndices = stateToNumberOfChoices.toVector(rowOdd); rowGroupIndices.resize(rowGroupIndices.size() + 1); uint_fast64_t tmp = 0; uint_fast64_t tmp2 = 0; for (uint_fast64_t i = 1; i < rowGroupIndices.size(); ++i) { tmp2 = rowGroupIndices[i]; rowGroupIndices[i] = rowGroupIndices[i - 1] + tmp; std::swap(tmp, tmp2); } rowGroupIndices[0] = 0; // Next, we split the matrix into one for each group. Note that this only works if the group variables are // at the very top. std::vector> groups = internalAdd.splitIntoGroups(ddGroupVariableIndices); // Create the actual storage for the non-zero entries. std::vector> columnsAndValues(this->getNonZeroCount()); // Now compute the indices at which the individual rows start. std::vector rowIndications(rowGroupIndices.back() + 1); std::vector> statesWithGroupEnabled(groups.size()); InternalAdd stateToRowGroupCount = this->getDdManager().template getAddZero(); for (uint_fast64_t i = 0; i < groups.size(); ++i) { auto const& dd = groups[i]; dd.toMatrixComponents(rowGroupIndices, rowIndications, columnsAndValues, rowOdd, columnOdd, ddRowVariableIndices, ddColumnVariableIndices, false); statesWithGroupEnabled[i] = dd.notZero().existsAbstract(columnVariableCube).template toAdd(); stateToRowGroupCount += statesWithGroupEnabled[i]; statesWithGroupEnabled[i].composeWithExplicitVector(rowOdd, ddRowVariableIndices, rowGroupIndices, std::plus()); } // Since we modified the rowGroupIndices, we need to restore the correct values. stateToRowGroupCount.composeWithExplicitVector(rowOdd, ddRowVariableIndices, rowGroupIndices, std::minus()); // Now that we computed the number of entries in each row, compute the corresponding offsets in the entry vector. tmp = 0; tmp2 = 0; for (uint_fast64_t i = 1; i < rowIndications.size(); ++i) { tmp2 = rowIndications[i]; rowIndications[i] = rowIndications[i - 1] + tmp; std::swap(tmp, tmp2); } rowIndications[0] = 0; // Now actually fill the entry vector. for (uint_fast64_t i = 0; i < groups.size(); ++i) { auto const& dd = groups[i]; dd.toMatrixComponents(rowGroupIndices, rowIndications, columnsAndValues, rowOdd, columnOdd, ddRowVariableIndices, ddColumnVariableIndices, true); statesWithGroupEnabled[i].composeWithExplicitVector(rowOdd, ddRowVariableIndices, rowGroupIndices, std::plus()); } // Since we modified the rowGroupIndices, we need to restore the correct values. stateToRowGroupCount.composeWithExplicitVector(rowOdd, ddRowVariableIndices, rowGroupIndices, std::minus()); // Since the last call to toMatrixRec modified the rowIndications, we need to restore the correct values. for (uint_fast64_t i = rowIndications.size() - 1; i > 0; --i) { rowIndications[i] = rowIndications[i - 1]; } rowIndications[0] = 0; return storm::storage::SparseMatrix(columnOdd.getTotalOffset(), std::move(rowIndications), std::move(columnsAndValues), std::move(rowGroupIndices), true); } template std::pair, std::vector> Add::toMatrixVector(storm::dd::Add const& vector, std::vector&& rowGroupSizes, std::set const& groupMetaVariables, storm::dd::Odd const& rowOdd, storm::dd::Odd const& columnOdd) const { std::set rowMetaVariables; std::set columnMetaVariables; for (auto const& variable : this->getContainedMetaVariables()) { // If the meta variable is a group meta variable, we do not insert it into the set of row/column meta variables. if (groupMetaVariables.find(variable) != groupMetaVariables.end()) { continue; } if (variable.getName().size() > 0 && variable.getName().back() == '\'') { columnMetaVariables.insert(variable); } else { rowMetaVariables.insert(variable); } } // Create the canonical row group sizes and build the matrix. return toMatrixVector(vector, std::move(rowGroupSizes), rowMetaVariables, columnMetaVariables, groupMetaVariables, rowOdd, columnOdd); } template std::pair, std::vector> Add::toMatrixVector(storm::dd::Add const& vector, std::vector&& rowGroupIndices, std::set const& rowMetaVariables, std::set const& columnMetaVariables, std::set const& groupMetaVariables, storm::dd::Odd const& rowOdd, storm::dd::Odd const& columnOdd) const { std::vector ddRowVariableIndices; std::vector ddColumnVariableIndices; std::vector ddGroupVariableIndices; std::set rowAndColumnMetaVariables; for (auto const& variable : rowMetaVariables) { DdMetaVariable const& metaVariable = this->getDdManager().getMetaVariable(variable); for (auto const& ddVariable : metaVariable.getDdVariables()) { ddRowVariableIndices.push_back(ddVariable.getIndex()); } rowAndColumnMetaVariables.insert(variable); } std::sort(ddRowVariableIndices.begin(), ddRowVariableIndices.end()); for (auto const& variable : columnMetaVariables) { DdMetaVariable const& metaVariable = this->getDdManager().getMetaVariable(variable); for (auto const& ddVariable : metaVariable.getDdVariables()) { ddColumnVariableIndices.push_back(ddVariable.getIndex()); } rowAndColumnMetaVariables.insert(variable); } std::sort(ddColumnVariableIndices.begin(), ddColumnVariableIndices.end()); for (auto const& variable : groupMetaVariables) { DdMetaVariable const& metaVariable = this->getDdManager().getMetaVariable(variable); for (auto const& ddVariable : metaVariable.getDdVariables()) { ddGroupVariableIndices.push_back(ddVariable.getIndex()); } } std::sort(ddGroupVariableIndices.begin(), ddGroupVariableIndices.end()); Bdd columnVariableCube = Bdd::getCube(this->getDdManager(), columnMetaVariables); // Transform the row group sizes to the actual row group indices. rowGroupIndices.resize(rowGroupIndices.size() + 1); uint_fast64_t tmp = 0; uint_fast64_t tmp2 = 0; for (uint_fast64_t i = 1; i < rowGroupIndices.size(); ++i) { tmp2 = rowGroupIndices[i]; rowGroupIndices[i] = rowGroupIndices[i - 1] + tmp; std::swap(tmp, tmp2); } rowGroupIndices[0] = 0; // Create the explicit vector we need to fill later. std::vector explicitVector(rowGroupIndices.back()); // Next, we split the matrix into one for each group. Note that this only works if the group variables are at the very top. std::vector, InternalAdd>> groups = internalAdd.splitIntoGroups(vector, ddGroupVariableIndices); // Create the actual storage for the non-zero entries. std::vector> columnsAndValues(this->getNonZeroCount()); // Now compute the indices at which the individual rows start. std::vector rowIndications(rowGroupIndices.back() + 1); std::vector> statesWithGroupEnabled(groups.size()); InternalAdd stateToRowGroupCount = this->getDdManager().template getAddZero(); for (uint_fast64_t i = 0; i < groups.size(); ++i) { std::pair, InternalAdd> const& ddPair = groups[i]; ddPair.first.toMatrixComponents(rowGroupIndices, rowIndications, columnsAndValues, rowOdd, columnOdd, ddRowVariableIndices, ddColumnVariableIndices, false); ddPair.second.composeWithExplicitVector(rowOdd, ddRowVariableIndices, rowGroupIndices, explicitVector, std::plus()); statesWithGroupEnabled[i] = (ddPair.first.notZero().existsAbstract(columnVariableCube) || ddPair.second.notZero()).template toAdd(); stateToRowGroupCount += statesWithGroupEnabled[i]; statesWithGroupEnabled[i].composeWithExplicitVector(rowOdd, ddRowVariableIndices, rowGroupIndices, std::plus()); } // Since we modified the rowGroupIndices, we need to restore the correct values. stateToRowGroupCount.composeWithExplicitVector(rowOdd, ddRowVariableIndices, rowGroupIndices, std::minus()); // Now that we computed the number of entries in each row, compute the corresponding offsets in the entry vector. tmp = 0; tmp2 = 0; for (uint_fast64_t i = 1; i < rowIndications.size(); ++i) { tmp2 = rowIndications[i]; rowIndications[i] = rowIndications[i - 1] + tmp; std::swap(tmp, tmp2); } rowIndications[0] = 0; // Now actually fill the entry vector. for (uint_fast64_t i = 0; i < groups.size(); ++i) { auto const& dd = groups[i].first; dd.toMatrixComponents(rowGroupIndices, rowIndications, columnsAndValues, rowOdd, columnOdd, ddRowVariableIndices, ddColumnVariableIndices, true); statesWithGroupEnabled[i].composeWithExplicitVector(rowOdd, ddRowVariableIndices, rowGroupIndices, std::plus()); } // Since we modified the rowGroupIndices, we need to restore the correct values. stateToRowGroupCount.composeWithExplicitVector(rowOdd, ddRowVariableIndices, rowGroupIndices, std::minus()); // Since the last call to toMatrixRec modified the rowIndications, we need to restore the correct values. for (uint_fast64_t i = rowIndications.size() - 1; i > 0; --i) { rowIndications[i] = rowIndications[i - 1]; } rowIndications[0] = 0; return std::make_pair(storm::storage::SparseMatrix(columnOdd.getTotalOffset(), std::move(rowIndications), std::move(columnsAndValues), std::move(rowGroupIndices), true), std::move(explicitVector)); } template void Add::exportToDot(std::string const& filename) const { internalAdd.exportToDot(filename, this->getDdManager().getDdVariableNames()); } template AddIterator Add::begin(bool enumerateDontCareMetaVariables) const { return internalAdd.begin(this->getDdManager(), this->getContainedMetaVariables(), enumerateDontCareMetaVariables); } template AddIterator Add::end(bool enumerateDontCareMetaVariables) const { return internalAdd.end(this->getDdManager(), enumerateDontCareMetaVariables); } template std::ostream& operator<<(std::ostream& out, Add const& add) { out << "ADD with " << add.getNonZeroCount() << " nnz, " << add.getNodeCount() << " nodes, " << add.getLeafCount() << " leaves" << std::endl; std::vector variableNames; for (auto const& variable : add.getContainedMetaVariables()) { variableNames.push_back(variable.getName()); } out << "contained variables: " << boost::algorithm::join(variableNames, ", ") << std::endl; return out; } template Add Add::fromVector(DdManager const& ddManager, std::vector const& values, Odd const& odd, std::set const& metaVariables) { return Add(ddManager, InternalAdd::fromVector(ddManager.getInternalDdManagerPointer(), values, odd, ddManager.getSortedVariableIndices(metaVariables)), metaVariables); } template Bdd Add::toBdd() const { return this->notZero(); } template Odd Add::createOdd() const { return internalAdd.createOdd(this->getSortedVariableIndices()); } template Add::operator InternalAdd() const { return internalAdd; } template class Add; template class Add; template class Add; template class Add; } }