|
|
@ -8,7 +8,10 @@ |
|
|
|
#include <iostream> |
|
|
|
#include <vector> |
|
|
|
|
|
|
|
#include "storm/models/sparse/Model.h" |
|
|
|
#include "storm/storage/BitVector.h" |
|
|
|
#include "storm/storage/SparseMatrix.h" |
|
|
|
|
|
|
|
|
|
|
|
namespace storm { |
|
|
|
namespace analysis { |
|
|
@ -33,18 +36,24 @@ namespace storm { |
|
|
|
/*! |
|
|
|
* Adds a node with the given state below node1 and above node2. |
|
|
|
* @param state The given state. |
|
|
|
* @param node1 The pointer to the node below which a new node is added. |
|
|
|
* @param node2 The pointer to the node above which a new node is added. |
|
|
|
* @param node1 The pointer to the node below which a new node (with state) is added |
|
|
|
* @param node2 The pointer to the node above which a new node (with state) is added |
|
|
|
*/ |
|
|
|
void addBetween(uint_fast64_t state, Node *node1, Node *node2); |
|
|
|
|
|
|
|
/*! |
|
|
|
* Adds state to the states of the given node. |
|
|
|
* @param state The state which is added. |
|
|
|
* @param node The pointer to the node to which state is added. |
|
|
|
* @param node The pointer to the node to which state is added, should not be nullptr. |
|
|
|
*/ |
|
|
|
void addToNode(uint_fast64_t state, Node *node); |
|
|
|
|
|
|
|
/*! |
|
|
|
* Adds state between the top and bottom node of the lattice |
|
|
|
* @param state The given state |
|
|
|
*/ |
|
|
|
void add(uint_fast64_t state); |
|
|
|
|
|
|
|
/*! |
|
|
|
* Compares the level of the nodes of the states. |
|
|
|
* Behaviour unknown when one or more of the states doesnot occur at any Node in the Lattice. |
|
|
@ -74,11 +83,103 @@ namespace storm { |
|
|
|
*/ |
|
|
|
void toString(std::ostream &out); |
|
|
|
|
|
|
|
// std::vector<uint_fast64_t> addedStates; |
|
|
|
/*! |
|
|
|
* Creates a Lattice based on the transition matrix, topStates of the Lattice and bottomStates of the Lattice |
|
|
|
* @tparam ValueType Type of the probabilities |
|
|
|
* @param matrix The transition matrix. |
|
|
|
* @param topStates Set of topStates of the Lattice. |
|
|
|
* @param bottomStates Set of bottomStates of the Lattice. |
|
|
|
* @return pointer to the created Lattice. |
|
|
|
*/ |
|
|
|
template <typename ValueType> |
|
|
|
static Lattice* toLattice(storm::storage::SparseMatrix<ValueType> matrix, |
|
|
|
storm::storage::BitVector topStates, |
|
|
|
storm::storage::BitVector bottomStates) { |
|
|
|
uint_fast64_t numberOfStates = matrix.getColumnCount(); |
|
|
|
|
|
|
|
// Transform the transition matrix into a vector containing the states with the state to which the transition goes. |
|
|
|
std::vector <State*> stateVector = std::vector<State *>({}); |
|
|
|
for (uint_fast64_t i = 0; i < numberOfStates; ++i) { |
|
|
|
State* state = new State(); |
|
|
|
state->stateNumber = i; |
|
|
|
|
|
|
|
auto row = matrix.getRow(i); |
|
|
|
//TODO assert that there are at most two successors |
|
|
|
if ((*(row.begin())).getValue() != ValueType(1)) { |
|
|
|
state->successor1 = (*(row.begin())).getColumn(); |
|
|
|
state->successor2 = (*(++row.begin())).getColumn(); |
|
|
|
} else { |
|
|
|
state-> successor1 = (*(row.begin())).getColumn(); |
|
|
|
state-> successor2 = (*(row.begin())).getColumn(); |
|
|
|
} |
|
|
|
|
|
|
|
stateVector.push_back(state); |
|
|
|
} |
|
|
|
// Start creating the Lattice |
|
|
|
storm::analysis::Lattice *lattice = new storm::analysis::Lattice(topStates, bottomStates, numberOfStates); |
|
|
|
storm::storage::BitVector oldStates(numberOfStates); |
|
|
|
// Create a copy of the states already present in the lattice. |
|
|
|
storm::storage::BitVector seenStates = topStates|= bottomStates; |
|
|
|
|
|
|
|
while (oldStates != seenStates) { |
|
|
|
// As long as new states are added to the lattice, continue. |
|
|
|
oldStates = storm::storage::BitVector(seenStates); |
|
|
|
|
|
|
|
for (auto itr = stateVector.begin(); itr != stateVector.end(); ++itr) { |
|
|
|
// Iterate over all states |
|
|
|
State *currentState = *itr; |
|
|
|
|
|
|
|
if (!seenStates[currentState->stateNumber] |
|
|
|
&& seenStates[currentState->successor1] |
|
|
|
&& seenStates[currentState->successor2]) { |
|
|
|
|
|
|
|
|
|
|
|
// Otherwise, check how the two states compare, and add if the comparison is possible. |
|
|
|
uint_fast64_t successor1 = currentState->successor1; |
|
|
|
uint_fast64_t successor2 = currentState->successor2; |
|
|
|
int compareResult = lattice->compare(successor1, successor2); |
|
|
|
if (compareResult == 1) { |
|
|
|
// successor 1 is closer to top than successor 2 |
|
|
|
lattice->addBetween(currentState->stateNumber, lattice->getNode(successor1), |
|
|
|
lattice->getNode(successor2)); |
|
|
|
// Add stateNumber to the set with seen states. |
|
|
|
seenStates.set(currentState->stateNumber); |
|
|
|
} else if (compareResult == 2) { |
|
|
|
// successor 2 is closer to top than successor 1 |
|
|
|
lattice->addBetween(currentState->stateNumber, lattice->getNode(successor2), |
|
|
|
lattice->getNode(successor1)); |
|
|
|
// Add stateNumber to the set with seen states. |
|
|
|
seenStates.set(currentState->stateNumber); |
|
|
|
} else if (compareResult == 0) { |
|
|
|
// the successors are at the same level |
|
|
|
lattice->addToNode(currentState->stateNumber, lattice->getNode(successor1)); |
|
|
|
// Add stateNumber to the set with seen states. |
|
|
|
seenStates.set(currentState->stateNumber); |
|
|
|
} else { |
|
|
|
// TODO: is this what we want? |
|
|
|
lattice->add(currentState->stateNumber); |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return lattice; |
|
|
|
} |
|
|
|
|
|
|
|
private: |
|
|
|
struct State { |
|
|
|
uint_fast64_t stateNumber; |
|
|
|
uint_fast64_t successor1; |
|
|
|
uint_fast64_t successor2; |
|
|
|
}; |
|
|
|
|
|
|
|
std::vector<Node *> nodes; |
|
|
|
|
|
|
|
Node * top; |
|
|
|
|
|
|
|
Node * bottom; |
|
|
|
|
|
|
|
uint_fast64_t numberOfStates; |
|
|
|
|
|
|
|
bool above(Node *, Node *); |
|
|
|