diff --git a/src/storm-pars-cli/storm-pars.cpp b/src/storm-pars-cli/storm-pars.cpp index 06f5a18c9..c44e8a8f8 100644 --- a/src/storm-pars-cli/storm-pars.cpp +++ b/src/storm-pars-cli/storm-pars.cpp @@ -1,6 +1,7 @@ #include "storm-pars/analysis/LatticeExtender.h" +#include "storm-pars/analysis/AssumptionMaker.h" #include "storm-cli-utilities/cli.h" #include "storm-cli-utilities/model-handling.h" @@ -611,27 +612,16 @@ namespace storm { // Transform to Lattice storm::utility::Stopwatch latticeWatch(true); - storm::analysis::LatticeExtender> extender = storm::analysis::LatticeExtender>(sparseModel); - std::tuple criticalPair = extender.toLattice(formulas); + storm::analysis::LatticeExtender *extender = new storm::analysis::LatticeExtender(sparseModel); + std::tuple criticalPair = extender->toLattice(formulas); - // Declare variables for all states - std::shared_ptr expressionManager(new storm::expressions::ExpressionManager()); - for (uint_fast64_t i = 0; i < sparseModel->getNumberOfStates(); ++i) { - expressionManager->declareFreshIntegerVariable(); - } + // TODO met assumptionmaker dingen doen - // Make assumptions - std::set assumptions; - while (std::get<1>(criticalPair) != sparseModel->getNumberOfStates()) { - storm::expressions::Variable var1 = expressionManager->getVariable("_x" + std::to_string(std::get<1>(criticalPair))); - storm::expressions::Variable var2 = expressionManager->getVariable("_x" + std::to_string(std::get<2>(criticalPair))); - auto assumption = new storm::expressions::BinaryRelationExpression(*expressionManager, var1.getType(), - var1.getExpression().getBaseExpressionPointer(), var2.getExpression().getBaseExpressionPointer(), - storm::expressions::BinaryRelationExpression::RelationType::Greater); - assumptions.insert(assumption); - criticalPair = extender.extendLattice(std::get<0>(criticalPair), expressionManager, assumptions); - } - auto lattice = std::get<0>(criticalPair); + + auto assumptionMaker = storm::analysis::AssumptionMaker(extender, sparseModel->getNumberOfStates()); + std::map>> result = assumptionMaker.startMakingAssumptions(std::get<0>(criticalPair), std::get<1>(criticalPair), std::get<2>(criticalPair)); + + auto lattice = result.begin()->first; latticeWatch.stop(); STORM_PRINT(std::endl << "Time for lattice creation: " << latticeWatch << "." << std::endl << std::endl); diff --git a/src/storm-pars/analysis/AssumptionMaker.cpp b/src/storm-pars/analysis/AssumptionMaker.cpp new file mode 100644 index 000000000..7124748b2 --- /dev/null +++ b/src/storm-pars/analysis/AssumptionMaker.cpp @@ -0,0 +1,97 @@ +// +// Created by Jip Spel on 03.09.18. +// + +#include "AssumptionMaker.h" + +namespace storm { + namespace analysis { + template + AssumptionMaker::AssumptionMaker(storm::analysis::LatticeExtender* latticeExtender, uint_fast64_t numberOfStates) { + this->latticeExtender = latticeExtender; + this->numberOfStates = numberOfStates; + this->expressionManager = std::make_shared(storm::expressions::ExpressionManager()); + for (uint_fast64_t i = 0; i < this->numberOfStates; ++i) { + expressionManager->declareIntegerVariable(std::to_string(i)); + expressionManager->declareFreshIntegerVariable(); + } + } + + + template + std::map>> + AssumptionMaker::startMakingAssumptions(storm::analysis::Lattice* lattice, uint_fast64_t critical1, uint_fast64_t critical2) { + + std::map>> result; + + std::set> emptySet; + if (critical1 == numberOfStates || critical2 == numberOfStates) { + result.insert(std::pair>>(lattice, emptySet)); + } else { + storm::expressions::Variable var1 = expressionManager->getVariable(std::to_string(critical1)); + storm::expressions::Variable var2 = expressionManager->getVariable(std::to_string(critical2)); + std::set> assumptions1; + std::shared_ptr assumption1 + = std::make_shared(storm::expressions::BinaryRelationExpression(*expressionManager, var1.getType(), + var1.getExpression().getBaseExpressionPointer(), var2.getExpression().getBaseExpressionPointer(), + storm::expressions::BinaryRelationExpression::RelationType::Greater)); + assumptions1.insert(assumption1); + auto lattice1 = new storm::analysis::Lattice(*lattice); + auto myMap = (runRecursive(lattice1, assumptions1)); + result.insert(myMap.begin(), myMap.end()); + + std::set> assumptions2; + std::shared_ptr assumption2 + = std::make_shared(storm::expressions::BinaryRelationExpression(*expressionManager, var1.getType(), + var2.getExpression().getBaseExpressionPointer(), var1.getExpression().getBaseExpressionPointer(), + storm::expressions::BinaryRelationExpression::RelationType::Greater)); + assumptions2.insert(assumption2); + + auto lattice2 = new storm::analysis::Lattice(*lattice); + auto myMap2 = (runRecursive(lattice2, assumptions2)); + result.insert(myMap2.begin(), myMap2.end()); + } + return result; + } + + template + std::map>> AssumptionMaker::runRecursive(storm::analysis::Lattice* lattice, std::set> assumptions) { + std::map>> result; + std::tuple criticalPair = this->latticeExtender->extendLattice(lattice, assumptions); + + if (std::get<1>(criticalPair) == numberOfStates) { + result.insert(std::pair>>(lattice, assumptions)); + } else { + storm::expressions::Variable var1 = expressionManager->getVariable(std::to_string(std::get<1>(criticalPair))); + storm::expressions::Variable var2 = expressionManager->getVariable(std::to_string(std::get<2>(criticalPair))); + + std::set> assumptions1 = std::set>(assumptions); + std::shared_ptr assumption1 = std::make_shared(storm::expressions::BinaryRelationExpression(*expressionManager, var1.getType(), + var1.getExpression().getBaseExpressionPointer(), var2.getExpression().getBaseExpressionPointer(), + storm::expressions::BinaryRelationExpression::RelationType::Greater)); + assumptions1.insert(assumption1); + auto lattice1 = new storm::analysis::Lattice(*lattice); + auto myMap = (runRecursive(lattice1, assumptions1)); + result.insert(myMap.begin(), myMap.end()); + + + std::set> assumptions2 = assumptions; + std::shared_ptr assumption2 = std::make_shared(storm::expressions::BinaryRelationExpression(*expressionManager, var1.getType(), + var2.getExpression().getBaseExpressionPointer(), var1.getExpression().getBaseExpressionPointer(), + storm::expressions::BinaryRelationExpression::RelationType::Greater)) ; + assumptions2.insert(assumption2); + auto lattice2 = new storm::analysis::Lattice(*lattice); + myMap = (runRecursive(lattice2, assumptions2)); + result.insert(myMap.begin(), myMap.end()); + } + + return result; + } + + + template class AssumptionMaker; + } +} + + +// Een map met daarin een pointer naar de lattic en een set met de geldende assumptions voor die lattice \ No newline at end of file diff --git a/src/storm-pars/analysis/AssumptionMaker.h b/src/storm-pars/analysis/AssumptionMaker.h new file mode 100644 index 000000000..0472d2fbc --- /dev/null +++ b/src/storm-pars/analysis/AssumptionMaker.h @@ -0,0 +1,34 @@ +// +// Created by Jip Spel on 03.09.18. +// + +#ifndef STORM_ASSUMPTIONMAKER_H +#define STORM_ASSUMPTIONMAKER_H + +#include "Lattice.h" +#include "storm/storage/expressions/BinaryRelationExpression.h" +#include "LatticeExtender.h" + +namespace storm { + namespace analysis { + + template + class AssumptionMaker { + public: + AssumptionMaker(storm::analysis::LatticeExtender* latticeExtender, uint_fast64_t numberOfStates); + + std::map>> startMakingAssumptions(storm::analysis::Lattice* lattice, uint_fast64_t critical1, uint_fast64_t critical2); + + + private: + std::map>> runRecursive(storm::analysis::Lattice* lattice, std::set> assumptions); + + storm::analysis::LatticeExtender* latticeExtender; + + std::shared_ptr expressionManager; + + uint_fast64_t numberOfStates; + }; + } +} +#endif //STORM_ASSUMPTIONMAKER_H diff --git a/src/storm-pars/analysis/Lattice.cpp b/src/storm-pars/analysis/Lattice.cpp index 67205c4fe..189cff147 100644 --- a/src/storm-pars/analysis/Lattice.cpp +++ b/src/storm-pars/analysis/Lattice.cpp @@ -76,11 +76,13 @@ namespace storm { return SAME; } - if (above(node1, node2)) { + std::set* seen1 = new std::set({}); + if (above(node1, node2, seen1)) { return ABOVE; } - if (above(node2, node1)) { + std::set* seen2 = new std::set({}); + if (above(node2, node1, seen2)) { return BELOW; } } @@ -108,7 +110,7 @@ namespace storm { std::vector printedNodes = std::vector({}); for (auto itr = nodes.begin(); itr != nodes.end(); ++itr) { - if (std::find(printedNodes.begin(), printedNodes.end(), (*itr)) == printedNodes.end()) { + if ((*itr) != nullptr && std::find(printedNodes.begin(), printedNodes.end(), (*itr)) == printedNodes.end()) { Node *node = *itr; printedNodes.push_back(*itr); out << "Node: {"; @@ -123,24 +125,23 @@ namespace storm { out << "}" << "\n"; out << " Address: " << node << "\n"; out << " Above: {"; - for (auto itr2 = node->above.begin(); itr2 != node->above.end(); ++itr2) { - Node *above = *itr2; - out << "{"; - index = above->states.getNextSetIndex(0); - while (index < numberOfStates) { - out << index; - index = above->states.getNextSetIndex(index + 1); - if (index < numberOfStates) { - out << ", "; + + for (auto itr2 = node->above.begin(); itr2 != node->above.end(); ++itr2) { + Node *above = *itr2; + index = above->states.getNextSetIndex(0); + out << "{"; + while (index < numberOfStates) { + out << index; + index = above->states.getNextSetIndex(index + 1); + if (index < numberOfStates) { + out << ", "; + } } - } - out << "}"; - if ((++itr2) != node->above.end()) { - out << ", "; + out << "}"; } - } - out << "}" << "\n"; + out << "}" << "\n"; + out << " Below: {"; for (auto itr2 = node->below.begin(); itr2 != node->below.end(); ++itr2) { @@ -156,9 +157,6 @@ namespace storm { } out << "}"; - if ((++itr2) != node->below.end()) { - out << ", "; - } } out << "}" << "\n"; } @@ -166,50 +164,53 @@ namespace storm { } void Lattice::toDotFile(std::ostream &out) { - out << "digraph \"Lattice\" {" << std::endl; - - // print all nodes - std::vector printed; - out << "\t" << "node [shape=ellipse]" << std::endl; - for (auto itr = nodes.begin(); itr != nodes.end(); ++itr) { - if (find(printed.begin(), printed.end(), (*itr)) == printed.end()) { - out << "\t\"" << (*itr) << "\" [label = \""; - uint_fast64_t index = (*itr)->states.getNextSetIndex(0); - while (index < numberOfStates) { - out << index; - index = (*itr)->states.getNextSetIndex(index + 1); - if (index < numberOfStates) { - out << ", "; - } + out << "digraph \"Lattice\" {" << std::endl; + + // print all nodes + std::vector printed; + out << "\t" << "node [shape=ellipse]" << std::endl; + for (auto itr = nodes.begin(); itr != nodes.end(); ++itr) { + + if ((*itr) != nullptr && find(printed.begin(), printed.end(), (*itr)) == printed.end()) { + out << "\t\"" << (*itr) << "\" [label = \""; + uint_fast64_t index = (*itr)->states.getNextSetIndex(0); + while (index < numberOfStates) { + out << index; + index = (*itr)->states.getNextSetIndex(index + 1); + if (index < numberOfStates) { + out << ", "; } - - out << "\"]" << std::endl; - printed.push_back(*itr); } + + out << "\"]" << std::endl; + printed.push_back(*itr); } + } - // print arcs - printed.clear(); - for (auto itr = nodes.begin(); itr != nodes.end(); ++itr) { - if (find(printed.begin(), printed.end(), (*itr)) == printed.end()) { - auto below = (*itr)->below; - for (auto itr2 = below.begin(); itr2 != below.end(); ++itr2) { - out << "\t\"" << (*itr) << "\" -> \"" << (*itr2) << "\";" << std::endl; - } - printed.push_back(*itr); + // print arcs + printed.clear(); + for (auto itr = nodes.begin(); itr != nodes.end(); ++itr) { + if ((*itr) != nullptr && find(printed.begin(), printed.end(), (*itr)) == printed.end()) { + auto below = (*itr)->below; + for (auto itr2 = below.begin(); itr2 != below.end(); ++itr2) { + out << "\t\"" << (*itr) << "\" -> \"" << (*itr2) << "\";" << std::endl; } + printed.push_back(*itr); } - - out << "}" << std::endl; } - bool Lattice::above(Node *node1, Node *node2) { - bool result = !node1->below.empty() && std::find(node1->below.begin(), node1->below.end(), node2) != node1->below.end(); + out << "}" << std::endl; + } - for (auto itr = node1->below.begin(); !result && node1->below.end() != itr; ++itr) { - result |= above(*itr, node2); + bool Lattice::above(Node *node1, Node *node2, std::set* seenNodes) { + bool result = !node1->below.empty() && std::find(node1->below.begin(), node1->below.end(), node2) != node1->below.end(); + for (auto itr = node1->below.begin(); !result && node1->below.end() != itr; ++itr) { + if (std::find(seenNodes->begin(), seenNodes->end(), (*itr)) == seenNodes->end()) { + seenNodes->insert(*itr); + result |= above(*itr, node2, seenNodes); } - return result; } + return result; } } +} diff --git a/src/storm-pars/analysis/Lattice.h b/src/storm-pars/analysis/Lattice.h index dcfa8c552..3d36b9120 100644 --- a/src/storm-pars/analysis/Lattice.h +++ b/src/storm-pars/analysis/Lattice.h @@ -120,7 +120,14 @@ namespace storm { uint_fast64_t numberOfStates; - bool above(Node *, Node *); + /** + * Check if node1 lies above node2 + * @param node1 + * @param node2 + * @param seenNodes + * @return + */ + bool above(Node * node1, Node * node2, std::set* seenNodes); }; } } diff --git a/src/storm-pars/analysis/LatticeExtender.cpp b/src/storm-pars/analysis/LatticeExtender.cpp index fdb4471a8..f3e7f2476 100644 --- a/src/storm-pars/analysis/LatticeExtender.cpp +++ b/src/storm-pars/analysis/LatticeExtender.cpp @@ -24,13 +24,13 @@ namespace storm { namespace analysis { - template - LatticeExtender::LatticeExtender(std::shared_ptr model) : model(model) { + template + LatticeExtender::LatticeExtender(std::shared_ptr> model) : model(model) { // intentionally left empty } - template - std::tuple LatticeExtender::toLattice(std::vector> formulas) { + template + std::tuple LatticeExtender::toLattice(std::vector> formulas) { STORM_LOG_THROW((++formulas.begin()) == formulas.end(), storm::exceptions::NotSupportedException, "Only one formula allowed for monotonicity analysis"); STORM_LOG_THROW((*(formulas[0])).isProbabilityOperatorFormula() && ((*(formulas[0])).asProbabilityOperatorFormula().getSubformula().isUntilFormula() @@ -38,7 +38,7 @@ namespace storm { uint_fast64_t numberOfStates = this->model->getNumberOfStates(); - storm::modelchecker::SparsePropositionalModelChecker propositionalChecker(*model); + storm::modelchecker::SparsePropositionalModelChecker> propositionalChecker(*model); storm::storage::BitVector phiStates; storm::storage::BitVector psiStates; if ((*(formulas[0])).asProbabilityOperatorFormula().getSubformula().isUntilFormula()) { @@ -76,15 +76,14 @@ namespace storm { return this->extendLattice(lattice); } - template - std::tuple LatticeExtender::extendLattice(storm::analysis::Lattice* lattice) { - std::shared_ptr expressionManager(new storm::expressions::ExpressionManager()); - std::set assumptions; - return this->extendLattice(lattice, expressionManager, assumptions); + template + std::tuple LatticeExtender::extendLattice(storm::analysis::Lattice* lattice) { + std::set> assumptions; + return this->extendLattice(lattice, assumptions); } - template - std::tuple LatticeExtender::extendLattice(storm::analysis::Lattice* lattice, std::shared_ptr expressionManager, std::set assumptions) { + template + std::tuple LatticeExtender::extendLattice(storm::analysis::Lattice* lattice, std::set> assumptions) { auto numberOfStates = this->model->getNumberOfStates(); // First handle assumptions for (auto itr = assumptions.begin(); itr != assumptions.end(); ++itr) { @@ -93,20 +92,19 @@ namespace storm { if (expr.getFirstOperand()->isVariable() && expr.getSecondOperand()->isVariable()) { storm::expressions::Variable largest = expr.getFirstOperand()->asVariableExpression().getVariable(); storm::expressions::Variable smallest = expr.getSecondOperand()->asVariableExpression().getVariable(); - - if (lattice->compare(largest.getOffset(), smallest.getOffset()) != storm::analysis::Lattice::ABOVE) { - storm::analysis::Lattice::Node* n1 = lattice->getNode(largest.getOffset()); - storm::analysis::Lattice::Node* n2 = lattice->getNode(smallest.getOffset()); + if (lattice->compare(std::stoul(largest.getName(), nullptr, 0), std::stoul(smallest.getName(), nullptr, 0)) != storm::analysis::Lattice::ABOVE) { + storm::analysis::Lattice::Node* n1 = lattice->getNode(std::stoul(largest.getName(), nullptr, 0)); + storm::analysis::Lattice::Node* n2 = lattice->getNode(std::stoul(smallest.getName(), nullptr, 0)); if (n1 != nullptr && n2 != nullptr) { lattice->addRelationNodes(n1, n2); } else if (n1 != nullptr) { - lattice->addBetween(smallest.getOffset(), n1, lattice->getBottom()); + lattice->addBetween(std::stoul(smallest.getName(), nullptr, 0), n1, lattice->getBottom()); } else if (n2 != nullptr) { - lattice->addBetween(largest.getOffset(), lattice->getTop(), n2); + lattice->addBetween(std::stoul(largest.getName(), nullptr, 0), lattice->getTop(), n2); } else { - lattice->add(largest.getOffset()); - lattice->addBetween(smallest.getOffset(), lattice->getNode(largest.getOffset()), + lattice->add(std::stoul(largest.getName(), nullptr, 0)); + lattice->addBetween(std::stoul(smallest.getName(), nullptr, 0), lattice->getNode(std::stoul(largest.getName(), nullptr, 0)), lattice->getBottom()); } } @@ -141,6 +139,7 @@ namespace storm { // Otherwise, check how the two states compare, and add if the comparison is possible. uint_fast64_t successor1 = successors.getNextSetIndex(0); uint_fast64_t successor2 = successors.getNextSetIndex(successor1 + 1); + int compareResult = lattice->compare(successor1, successor2); if (compareResult == storm::analysis::Lattice::ABOVE) { // successor 1 is closer to top than successor 2 @@ -163,6 +162,6 @@ namespace storm { return std::make_tuple(lattice, numberOfStates, numberOfStates); } - template class LatticeExtender>; + template class LatticeExtender; } } diff --git a/src/storm-pars/analysis/LatticeExtender.h b/src/storm-pars/analysis/LatticeExtender.h index 9c854b4f5..72d91a8c1 100644 --- a/src/storm-pars/analysis/LatticeExtender.h +++ b/src/storm-pars/analysis/LatticeExtender.h @@ -17,18 +17,18 @@ namespace storm { namespace analysis { - template + template class LatticeExtender { public: - LatticeExtender(std::shared_ptr model); + LatticeExtender(std::shared_ptr> model); std::tuple toLattice(std::vector> formulas); - std::tuple extendLattice(storm::analysis::Lattice* lattice, std::shared_ptr expressionManager, std::set assumptions); + std::tuple extendLattice(storm::analysis::Lattice* lattice, std::set> assumptions); private: - std::shared_ptr model; + std::shared_ptr> model; std::map stateMap;