|
|
@ -74,9 +74,8 @@ namespace storm { |
|
|
|
|
|
|
|
template<typename ModelType> |
|
|
|
void NondeterministicModelBisimulationDecomposition<ModelType>::buildQuotient() { |
|
|
|
std::cout << "Found " << this->partition.size() << " blocks" << std::endl; |
|
|
|
this->partition.print(); |
|
|
|
STORM_LOG_ASSERT(false, "Not yet implemented"); |
|
|
|
// TODO
|
|
|
|
} |
|
|
|
|
|
|
|
template<typename ModelType> |
|
|
@ -129,17 +128,105 @@ namespace storm { |
|
|
|
|
|
|
|
template<typename ModelType> |
|
|
|
bool NondeterministicModelBisimulationDecomposition<ModelType>::checkQuotientDistributions() const { |
|
|
|
|
|
|
|
std::vector<uint_fast64_t> nondeterministicChoiceIndices = this->model.getTransitionMatrix().getRowGroupIndices(); |
|
|
|
for (auto state = 0; state < this->model.getNumberOfStates(); ++state) { |
|
|
|
for (auto choice = nondeterministicChoiceIndices[state]; choice < nondeterministicChoiceIndices[state + 1]; ++choice) { |
|
|
|
storm::storage::Distribution<ValueType> distribution; |
|
|
|
for (auto const& element : this->model.getTransitionMatrix().getRow(choice)) { |
|
|
|
distribution.addProbability(this->partition.getBlock(element.getColumn()).getId(), element.getValue()); |
|
|
|
} |
|
|
|
|
|
|
|
if (!distribution.equals(quotientDistributions[choice])) { |
|
|
|
std::cout << "the distributions for choice " << choice << " of state " << state << " do not match." << std::endl; |
|
|
|
std::cout << "is: " << quotientDistributions[choice] << " but should be " << distribution << std::endl; |
|
|
|
exit(-1); |
|
|
|
} |
|
|
|
|
|
|
|
bool less1 = distribution.less(quotientDistributions[choice], this->comparator); |
|
|
|
bool less2 = quotientDistributions[choice].less(distribution, this->comparator); |
|
|
|
|
|
|
|
if (distribution.equals(quotientDistributions[choice]) && (less1 || less2)) { |
|
|
|
std::cout << "mismatch of equality and less for " << std::endl; |
|
|
|
std::cout << quotientDistributions[choice] << " vs " << distribution << std::endl; |
|
|
|
exit(-1); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
for (auto choice = nondeterministicChoiceIndices[state]; choice < nondeterministicChoiceIndices[state + 1] - 1; ++choice) { |
|
|
|
if (orderedQuotientDistributions[choice + 1]->less(*orderedQuotientDistributions[choice], this->comparator)) { |
|
|
|
std::cout << "choice " << (choice+1) << " is less than predecessor" << std::endl; |
|
|
|
std::cout << *orderedQuotientDistributions[choice] << " should be less than " << *orderedQuotientDistributions[choice + 1] << std::endl; |
|
|
|
exit(-1); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
template<typename ModelType> |
|
|
|
bool NondeterministicModelBisimulationDecomposition<ModelType>::printDistributions(uint_fast64_t state) const { |
|
|
|
std::vector<uint_fast64_t> nondeterministicChoiceIndices = this->model.getTransitionMatrix().getRowGroupIndices(); |
|
|
|
for (auto choice = nondeterministicChoiceIndices[state]; choice < nondeterministicChoiceIndices[state + 1]; ++choice) { |
|
|
|
std::cout << quotientDistributions[choice] << std::endl; |
|
|
|
} |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
template<typename ModelType> |
|
|
|
bool NondeterministicModelBisimulationDecomposition<ModelType>::checkBlockStable(bisimulation::Block<BlockDataType> const& newBlock) const { |
|
|
|
std::cout << "checking stability of new block " << newBlock.getId() << " of size " << newBlock.getNumberOfStates() << std::endl; |
|
|
|
for (auto stateIt1 = this->partition.begin(newBlock), stateIte1 = this->partition.end(newBlock); stateIt1 != stateIte1; ++stateIt1) { |
|
|
|
for (auto stateIt2 = this->partition.begin(newBlock), stateIte2 = this->partition.end(newBlock); stateIt2 != stateIte2; ++stateIt2) { |
|
|
|
bool less1 = quotientDistributionsLess(*stateIt1, *stateIt2); |
|
|
|
bool less2 = quotientDistributionsLess(*stateIt2, *stateIt1); |
|
|
|
if (less1 || less2) { |
|
|
|
std::cout << "the partition is not stable for the states " << *stateIt1 << " and " << *stateIt2 << std::endl; |
|
|
|
std::cout << "less1 " << less1 << " and less2 " << less2 << std::endl; |
|
|
|
|
|
|
|
std::cout << "distributions of state " << *stateIt1 << std::endl; |
|
|
|
this->printDistributions(*stateIt1); |
|
|
|
std::cout << "distributions of state " << *stateIt2 << std::endl; |
|
|
|
this->printDistributions(*stateIt2); |
|
|
|
exit(-1); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
template<typename ModelType> |
|
|
|
bool NondeterministicModelBisimulationDecomposition<ModelType>::checkDistributionsDifferent(bisimulation::Block<BlockDataType> const& block, storm::storage::sparse::state_type end) const { |
|
|
|
for (auto stateIt1 = this->partition.begin(block), stateIte1 = this->partition.end(block); stateIt1 != stateIte1; ++stateIt1) { |
|
|
|
for (auto stateIt2 = this->partition.begin() + block.getEndIndex(), stateIte2 = this->partition.begin() + end; stateIt2 != stateIte2; ++stateIt2) { |
|
|
|
if (!quotientDistributionsLess(*stateIt1, *stateIt2)) { |
|
|
|
std::cout << "distributions are not less, even though they should be!" << std::endl; |
|
|
|
exit(-3); |
|
|
|
} else { |
|
|
|
std::cout << "less:" << std::endl; |
|
|
|
this->printDistributions(*stateIt1); |
|
|
|
std::cout << "and" << std::endl; |
|
|
|
this->printDistributions(*stateIt2); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
template<typename ModelType> |
|
|
|
bool NondeterministicModelBisimulationDecomposition<ModelType>::splitBlockAccordingToCurrentQuotientDistributions(Block<BlockDataType>& block, std::deque<Block<BlockDataType>*>& splitterQueue) { |
|
|
|
std::list<Block<BlockDataType>*> newBlocks; |
|
|
|
bool split = this->partition.splitBlock(block, |
|
|
|
[this] (storm::storage::sparse::state_type state1, storm::storage::sparse::state_type state2) { |
|
|
|
return quotientDistributionsLess(state1, state2); |
|
|
|
bool result = quotientDistributionsLess(state1, state2); |
|
|
|
// std::cout << state1 << " is " << (!result ? "not" : "") << " smaller than " << state2 << std::endl;
|
|
|
|
return result; |
|
|
|
}, |
|
|
|
[this, &block, &splitterQueue] (Block<BlockDataType>& newBlock) { |
|
|
|
updateQuotientDistributionsOfPredecessors(newBlock, block, splitterQueue); |
|
|
|
[this, &block, &splitterQueue, &newBlocks] (Block<BlockDataType>& newBlock) { |
|
|
|
newBlocks.push_back(&newBlock); |
|
|
|
|
|
|
|
// this->checkBlockStable(newBlock);
|
|
|
|
// this->checkDistributionsDifferent(block, block.getEndIndex());
|
|
|
|
// this->checkQuotientDistributions();
|
|
|
|
}); |
|
|
|
|
|
|
|
// The quotient distributions of the predecessors of block do not need to be updated, since the probability
|
|
|
@ -148,25 +235,26 @@ namespace storm { |
|
|
|
// std::cout << "partition after split: " << std::endl;
|
|
|
|
// this->partition.print();
|
|
|
|
|
|
|
|
this->checkQuotientDistributions(); |
|
|
|
// defer updating the quotient distributions until *after* all splits, because
|
|
|
|
// it otherwise influences the subsequent splits!
|
|
|
|
for (auto el : newBlocks) { |
|
|
|
this->updateQuotientDistributionsOfPredecessors(*el, block, splitterQueue); |
|
|
|
} |
|
|
|
|
|
|
|
// this->checkQuotientDistributions();
|
|
|
|
|
|
|
|
return split; |
|
|
|
} |
|
|
|
|
|
|
|
template<typename ModelType> |
|
|
|
bool NondeterministicModelBisimulationDecomposition<ModelType>::quotientDistributionsLess(storm::storage::sparse::state_type state1, storm::storage::sparse::state_type state2) { |
|
|
|
bool NondeterministicModelBisimulationDecomposition<ModelType>::quotientDistributionsLess(storm::storage::sparse::state_type state1, storm::storage::sparse::state_type state2) const { |
|
|
|
STORM_LOG_TRACE("Comparing the quotient distributions of state " << state1 << " and " << state2 << "."); |
|
|
|
std::vector<uint_fast64_t> nondeterministicChoiceIndices = this->model.getTransitionMatrix().getRowGroupIndices(); |
|
|
|
|
|
|
|
// std::cout << "state " << state1 << std::endl;
|
|
|
|
// for (int c = nondeterministicChoiceIndices[state1]; c < nondeterministicChoiceIndices[state1 + 1]; ++c) {
|
|
|
|
// std::cout << quotientDistributions[c] << std::endl;
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// std::cout << "state " << state2 << std::endl;
|
|
|
|
// for (int c = nondeterministicChoiceIndices[state2]; c < nondeterministicChoiceIndices[state2 + 1]; ++c) {
|
|
|
|
// std::cout << quotientDistributions[c] << std::endl;
|
|
|
|
// }
|
|
|
|
|
|
|
|
// std::cout << "distributions of state " << state1 << std::endl;
|
|
|
|
// this->printDistributions(state1);
|
|
|
|
// std::cout << "distributions of state " << state2 << std::endl;
|
|
|
|
// this->printDistributions(state2);
|
|
|
|
|
|
|
|
auto firstIt = orderedQuotientDistributions.begin() + nondeterministicChoiceIndices[state1]; |
|
|
|
auto firstIte = orderedQuotientDistributions.begin() + nondeterministicChoiceIndices[state1 + 1]; |
|
|
|