You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
141 lines
8.0 KiB
141 lines
8.0 KiB
#include "storm/abstraction/ValidBlockAbstractor.h"
|
|
|
|
#include "storm/abstraction/AbstractionInformation.h"
|
|
|
|
#include "storm/storage/dd/DdManager.h"
|
|
|
|
#include "storm/utility/solver.h"
|
|
#include "storm/utility/Stopwatch.h"
|
|
|
|
namespace storm {
|
|
namespace abstraction {
|
|
|
|
template <storm::dd::DdType DdType>
|
|
ValidBlockAbstractor<DdType>::ValidBlockAbstractor(AbstractionInformation<DdType>& abstractionInformation, std::shared_ptr<storm::utility::solver::SmtSolverFactory> const& smtSolverFactory) : abstractionInformation(abstractionInformation), localExpressionInformation(abstractionInformation), validBlocks(abstractionInformation.getDdManager().getBddOne()), checkForRecomputation(false) {
|
|
|
|
uint64_t numberOfBlocks = localExpressionInformation.getNumberOfBlocks();
|
|
validBlocksForPredicateBlocks.resize(numberOfBlocks, abstractionInformation.getDdManager().getBddOne());
|
|
relevantVariablesAndPredicates.resize(numberOfBlocks);
|
|
decisionVariables.resize(numberOfBlocks);
|
|
|
|
for (uint64_t i = 0; i < numberOfBlocks; ++i) {
|
|
smtSolvers.emplace_back(smtSolverFactory->create(abstractionInformation.getExpressionManager()));
|
|
for (auto const& constraint : abstractionInformation.getConstraints()) {
|
|
smtSolvers.back()->add(constraint);
|
|
}
|
|
}
|
|
}
|
|
|
|
template <storm::dd::DdType DdType>
|
|
storm::dd::Bdd<DdType> const& ValidBlockAbstractor<DdType>::getValidBlocks() {
|
|
if (checkForRecomputation) {
|
|
recomputeValidBlocks();
|
|
}
|
|
|
|
return validBlocks;
|
|
}
|
|
|
|
template <storm::dd::DdType DdType>
|
|
void ValidBlockAbstractor<DdType>::constrain(storm::expressions::Expression const& constraint) {
|
|
for (uint64_t i = 0; i < smtSolvers.size(); ++i) {
|
|
smtSolvers[i]->add(constraint);
|
|
}
|
|
}
|
|
|
|
template <storm::dd::DdType DdType>
|
|
void ValidBlockAbstractor<DdType>::refine(std::vector<uint64_t> const& predicates) {
|
|
for (auto const& predicate : predicates) {
|
|
std::map<uint64_t, uint64_t> mergeInformation = localExpressionInformation.addExpression(predicate);
|
|
|
|
// Perform the remapping caused by merges.
|
|
for (auto const& blockRemapping : mergeInformation) {
|
|
if (blockRemapping.first == blockRemapping.second) {
|
|
continue;
|
|
}
|
|
|
|
validBlocksForPredicateBlocks[blockRemapping.second] = validBlocksForPredicateBlocks[blockRemapping.first];
|
|
smtSolvers[blockRemapping.second] = std::move(smtSolvers[blockRemapping.first]);
|
|
relevantVariablesAndPredicates[blockRemapping.second] = std::move(relevantVariablesAndPredicates[blockRemapping.first]);
|
|
decisionVariables[blockRemapping.second] = std::move(decisionVariables[blockRemapping.first]);
|
|
}
|
|
validBlocksForPredicateBlocks.resize(localExpressionInformation.getNumberOfBlocks());
|
|
smtSolvers.resize(localExpressionInformation.getNumberOfBlocks());
|
|
relevantVariablesAndPredicates.resize(localExpressionInformation.getNumberOfBlocks());
|
|
decisionVariables.resize(localExpressionInformation.getNumberOfBlocks());
|
|
}
|
|
checkForRecomputation = true;
|
|
}
|
|
|
|
template <storm::dd::DdType DdType>
|
|
void ValidBlockAbstractor<DdType>::recomputeValidBlocks() {
|
|
storm::dd::Bdd<DdType> newValidBlocks = abstractionInformation.get().getDdManager().getBddOne();
|
|
|
|
for (uint64_t blockIndex = 0; blockIndex < localExpressionInformation.getNumberOfBlocks(); ++blockIndex) {
|
|
std::set<uint64_t> const& predicateBlock = localExpressionInformation.getExpressionBlock(blockIndex);
|
|
|
|
// If the size of the block changed, we need to add the appropriate variables and recompute the solution.
|
|
if (relevantVariablesAndPredicates[blockIndex].size() < predicateBlock.size()) {
|
|
recomputeValidBlocksForPredicateBlock(blockIndex);
|
|
}
|
|
|
|
newValidBlocks &= validBlocksForPredicateBlocks[blockIndex];
|
|
}
|
|
|
|
validBlocks = newValidBlocks;
|
|
}
|
|
|
|
template <storm::dd::DdType DdType>
|
|
void ValidBlockAbstractor<DdType>::recomputeValidBlocksForPredicateBlock(uint64_t blockIndex) {
|
|
std::set<uint64_t> const& predicateBlock = localExpressionInformation.getExpressionBlock(blockIndex);
|
|
std::vector<std::pair<storm::expressions::Variable, uint_fast64_t>> newVariables = this->getAbstractionInformation().declareNewVariables(relevantVariablesAndPredicates[blockIndex], predicateBlock);
|
|
for (auto const& element : newVariables) {
|
|
smtSolvers[blockIndex]->add(storm::expressions::iff(element.first, this->getAbstractionInformation().getPredicateByIndex(element.second)));
|
|
decisionVariables[blockIndex].push_back(element.first);
|
|
}
|
|
|
|
relevantVariablesAndPredicates[blockIndex].insert(relevantVariablesAndPredicates[blockIndex].end(), newVariables.begin(), newVariables.end());
|
|
std::sort(relevantVariablesAndPredicates[blockIndex].begin(), relevantVariablesAndPredicates[blockIndex].end(),
|
|
[] (std::pair<storm::expressions::Variable, uint_fast64_t> const& first, std::pair<storm::expressions::Variable, uint_fast64_t> const& second) {
|
|
return first.second < second.second;
|
|
});
|
|
|
|
// Use all-sat to enumerate all valid blocks for this predicate block.
|
|
storm::dd::Bdd<DdType> result = this->getAbstractionInformation().getDdManager().getBddZero();
|
|
uint64_t numberOfSolutions = 0;
|
|
smtSolvers[blockIndex]->allSat(decisionVariables[blockIndex], [&result,this,&numberOfSolutions,blockIndex] (storm::solver::SmtSolver::ModelReference const& model) {
|
|
result |= getSourceStateBdd(model, blockIndex);
|
|
++numberOfSolutions;
|
|
return true;
|
|
});
|
|
|
|
STORM_LOG_TRACE("Computed valid blocks for predicate block " << blockIndex << " (" << numberOfSolutions << " solutions enumerated).");
|
|
|
|
validBlocksForPredicateBlocks[blockIndex] = result;
|
|
}
|
|
|
|
template <storm::dd::DdType DdType>
|
|
AbstractionInformation<DdType> const& ValidBlockAbstractor<DdType>::getAbstractionInformation() const {
|
|
return abstractionInformation.get();
|
|
}
|
|
|
|
template <storm::dd::DdType DdType>
|
|
storm::dd::Bdd<DdType> ValidBlockAbstractor<DdType>::getSourceStateBdd(storm::solver::SmtSolver::ModelReference const& model, uint64_t blockIndex) const {
|
|
storm::dd::Bdd<DdType> result = this->getAbstractionInformation().getDdManager().getBddOne();
|
|
for (auto variableIndexPairIt = relevantVariablesAndPredicates[blockIndex].rbegin(), variableIndexPairIte = relevantVariablesAndPredicates[blockIndex].rend(); variableIndexPairIt != variableIndexPairIte; ++variableIndexPairIt) {
|
|
auto const& variableIndexPair = *variableIndexPairIt;
|
|
if (model.getBooleanValue(variableIndexPair.first)) {
|
|
result &= this->getAbstractionInformation().encodePredicateAsSource(variableIndexPair.second);
|
|
} else {
|
|
result &= !this->getAbstractionInformation().encodePredicateAsSource(variableIndexPair.second);
|
|
}
|
|
}
|
|
|
|
STORM_LOG_ASSERT(!result.isZero(), "Source must not be empty.");
|
|
return result;
|
|
}
|
|
|
|
template class ValidBlockAbstractor<storm::dd::DdType::CUDD>;
|
|
template class ValidBlockAbstractor<storm::dd::DdType::Sylvan>;
|
|
|
|
}
|
|
}
|