Joachim Klein
4 years ago
committed by
Stefan Pranger
4 changed files with 276 additions and 0 deletions
-
27src/storm/transformer/DAProduct.h
-
55src/storm/transformer/DAProductBuilder.h
-
89src/storm/transformer/Product.h
-
105src/storm/transformer/ProductBuilder.h
@ -0,0 +1,27 @@ |
|||
#pragma |
|||
|
|||
#include "storm/automata/AcceptanceCondition.h" |
|||
#include "storm/transformer/Product.h" |
|||
#include <memory> |
|||
|
|||
namespace storm { |
|||
namespace transformer { |
|||
|
|||
template <typename Model> |
|||
class DAProduct : public Product<Model> { |
|||
public: |
|||
typedef std::shared_ptr<DAProduct<Model>> ptr; |
|||
|
|||
DAProduct(Product<Model>&& product, storm::automata::AcceptanceCondition::ptr acceptance) |
|||
: Product<Model>(std::move(product)), acceptance(acceptance) { |
|||
// Intentionally left blank |
|||
} |
|||
|
|||
storm::automata::AcceptanceCondition::ptr getAcceptance() { |
|||
return acceptance; |
|||
} |
|||
private: |
|||
storm::automata::AcceptanceCondition::ptr acceptance; |
|||
}; |
|||
} |
|||
} |
@ -0,0 +1,55 @@ |
|||
#pragma once |
|||
|
|||
#include "storm/storage/BitVector.h" |
|||
#include "storm/automata/DeterministicAutomaton.h" |
|||
#include "storm/transformer/DAProduct.h" |
|||
#include "storm/transformer/Product.h" |
|||
#include "storm/transformer/ProductBuilder.h" |
|||
|
|||
#include <vector> |
|||
|
|||
namespace storm { |
|||
namespace transformer { |
|||
class DAProductBuilder { |
|||
public: |
|||
DAProductBuilder(const storm::automata::DeterministicAutomaton& da, const std::vector<storm::storage::BitVector>& statesForAP) |
|||
: da(da), statesForAP(statesForAP) { |
|||
} |
|||
|
|||
template <typename Model> |
|||
typename DAProduct<Model>::ptr build(const Model& originalModel, const storm::storage::BitVector& statesOfInterest) const { |
|||
typename Product<Model>::ptr product = ProductBuilder<Model>::buildProduct(originalModel, *this, statesOfInterest); |
|||
storm::automata::AcceptanceCondition::ptr prodAcceptance |
|||
= da.getAcceptance()->lift(product->getProductModel().getNumberOfStates(), |
|||
[&product](std::size_t prodState) {return product->getAutomatonState(prodState);}); |
|||
|
|||
return typename DAProduct<Model>::ptr(new DAProduct<Model>(std::move(*product), prodAcceptance)); |
|||
} |
|||
|
|||
storm::storage::sparse::state_type getInitialState(storm::storage::sparse::state_type modelState) const { |
|||
return da.getSuccessor(da.getInitialState(), getLabelForState(modelState)); |
|||
} |
|||
|
|||
storm::storage::sparse::state_type getSuccessor(storm::storage::sparse::state_type modelFrom, |
|||
storm::storage::sparse::state_type automatonFrom, |
|||
storm::storage::sparse::state_type modelTo) const { |
|||
return da.getSuccessor(automatonFrom, getLabelForState(modelTo)); |
|||
} |
|||
|
|||
|
|||
private: |
|||
const storm::automata::DeterministicAutomaton& da; |
|||
const std::vector<storm::storage::BitVector>& statesForAP; |
|||
|
|||
storm::automata::APSet::alphabet_element getLabelForState(storm::storage::sparse::state_type s) const { |
|||
storm::automata::APSet::alphabet_element label = da.getAPSet().elementAllFalse(); |
|||
for (unsigned int ap = 0; ap < da.getAPSet().size(); ap++) { |
|||
if (statesForAP.at(ap).get(s)) { |
|||
label = da.getAPSet().elementAddAP(label, ap); |
|||
} |
|||
} |
|||
return label; |
|||
} |
|||
}; |
|||
} |
|||
} |
@ -0,0 +1,89 @@ |
|||
#pragma once |
|||
|
|||
#include <memory> |
|||
|
|||
namespace storm { |
|||
namespace transformer { |
|||
template <typename Model> |
|||
class Product { |
|||
public: |
|||
typedef std::shared_ptr<Product<Model>> ptr; |
|||
|
|||
typedef storm::storage::sparse::state_type state_type; |
|||
typedef std::pair<state_type, state_type> product_state_type; |
|||
typedef std::map<product_state_type, state_type> product_state_to_product_index_map; |
|||
typedef std::vector<product_state_type> product_index_to_product_state_vector; |
|||
|
|||
Product(Model&& productModel, |
|||
std::string&& productStateOfInterestLabel, |
|||
product_state_to_product_index_map&& productStateToProductIndex, |
|||
product_index_to_product_state_vector&& productIndexToProductState) |
|||
: productModel(productModel), |
|||
productStateOfInterestLabel(productStateOfInterestLabel), |
|||
productStateToProductIndex(productStateToProductIndex), |
|||
productIndexToProductState(productIndexToProductState) {} |
|||
|
|||
Product(Product<Model>&& product) = default; |
|||
Product& operator=(Product<Model>&& product) = default; |
|||
|
|||
Model& getProductModel() {return productModel;} |
|||
|
|||
state_type getModelState(state_type productStateIndex) const { |
|||
return productIndexToProductState.at(productStateIndex).first; |
|||
} |
|||
|
|||
state_type getAutomatonState(state_type productStateIndex) const { |
|||
return productIndexToProductState.at(productStateIndex).second; |
|||
} |
|||
|
|||
storm::storage::BitVector liftFromAutomaton(const storm::storage::BitVector& vector) const { |
|||
state_type n = productModel.getNumberOfStates(); |
|||
storm::storage::BitVector lifted(n, false); |
|||
for (state_type s = 0; s < n; s++) { |
|||
if (vector.get(getAutomatonState(s))) { |
|||
lifted.set(s); |
|||
} |
|||
} |
|||
return lifted; |
|||
} |
|||
|
|||
storm::storage::BitVector liftFromModel(const storm::storage::BitVector& vector) const { |
|||
state_type n = productModel.getNumberOfStates(); |
|||
storm::storage::BitVector lifted(n, false); |
|||
for (state_type s = 0; s < n; s++) { |
|||
if (vector.get(getModelState(s))) { |
|||
lifted.set(s); |
|||
} |
|||
} |
|||
return lifted; |
|||
} |
|||
|
|||
template <typename ValueType> |
|||
std::vector<ValueType> projectToOriginalModel(const Model& originalModel, const std::vector<ValueType>& prodValues) { |
|||
std::vector<ValueType> origValues(originalModel.getNumberOfStates()); |
|||
for (state_type productState : productModel.getStateLabeling().getStates(productStateOfInterestLabel)) { |
|||
state_type originalState = getModelState(productState); |
|||
origValues.at(originalState) = prodValues.at(productState); |
|||
} |
|||
return origValues; |
|||
} |
|||
|
|||
const storm::storage::BitVector& getStatesOfInterest() const { |
|||
return productModel.getStates(productStateOfInterestLabel); |
|||
} |
|||
|
|||
void printMapping(std::ostream& out) const { |
|||
out << "Mapping index -> product state\n"; |
|||
for (std::size_t i = 0; i < productIndexToProductState.size(); i++) { |
|||
out << " " << i << ": " << productIndexToProductState.at(i).first << "," << productIndexToProductState.at(i).second << "\n"; |
|||
} |
|||
} |
|||
|
|||
private: |
|||
Model productModel; |
|||
std::string productStateOfInterestLabel; |
|||
product_state_to_product_index_map productStateToProductIndex; |
|||
product_index_to_product_state_vector productIndexToProductState; |
|||
}; |
|||
} |
|||
} |
@ -0,0 +1,105 @@ |
|||
#pragma once |
|||
|
|||
#include "storm/models/sparse/StateLabeling.h" |
|||
#include "storm/storage/SparseMatrix.h" |
|||
#include "storm/storage/BitVector.h" |
|||
|
|||
#include <vector> |
|||
#include <deque> |
|||
#include <map> |
|||
|
|||
namespace storm { |
|||
namespace transformer { |
|||
|
|||
template <typename Model> |
|||
class ProductBuilder { |
|||
public: |
|||
typedef storm::storage::SparseMatrix<typename Model::ValueType> matrix_type; |
|||
|
|||
template <typename ProductOperator> |
|||
static typename Product<Model>::ptr buildProduct(const Model& originalModel, ProductOperator& prodOp, const storm::storage::BitVector& statesOfInterest) { |
|||
const matrix_type& originalMatrix = originalModel.getTransitionMatrix(); |
|||
bool deterministic = originalMatrix.hasTrivialRowGrouping(); |
|||
|
|||
typedef storm::storage::sparse::state_type state_type; |
|||
typedef std::pair<state_type, state_type> product_state_type; |
|||
|
|||
state_type nextState = 0; |
|||
std::map<product_state_type, state_type> productStateToProductIndex; |
|||
std::vector<product_state_type> productIndexToProductState; |
|||
std::vector<state_type> prodInitial; |
|||
|
|||
// use deque for todo so that the states are handled in the order |
|||
// of their index in the product model, which is required due to the |
|||
// use of the SparseMatrixBuilder that can only handle linear addNextValue |
|||
// calls |
|||
std::deque<state_type> todo; |
|||
|
|||
for (state_type s_0 : statesOfInterest) { |
|||
state_type q_0 = prodOp.getInitialState(s_0); |
|||
|
|||
// std::cout << "Initial: " << s_0 << ", " << q_0 << " = " << nextState << "\n"; |
|||
|
|||
product_state_type s_q(s_0, q_0); |
|||
state_type index = nextState++; |
|||
productStateToProductIndex[s_q] = index; |
|||
productIndexToProductState.push_back(s_q); |
|||
prodInitial.push_back(index); |
|||
todo.push_back(index); |
|||
} |
|||
|
|||
storm::storage::SparseMatrixBuilder<typename Model::ValueType> builder(0, 0, 0, false, deterministic ? false : true, 0); |
|||
while (!todo.empty()) { |
|||
state_type prodIndexFrom = todo.front(); |
|||
todo.pop_front(); |
|||
|
|||
product_state_type from = productIndexToProductState.at(prodIndexFrom); |
|||
// std::cout << "Handle " << from.first << "," << from.second << " (prodIndexFrom = " << prodIndexFrom << "):\n"; |
|||
if (deterministic) { |
|||
typename matrix_type::const_rows row = originalMatrix.getRow(from.first); |
|||
for (auto const& entry : row) { |
|||
state_type t = entry.getColumn(); |
|||
state_type p = prodOp.getSuccessor(from.first, from.second, t); |
|||
// std::cout << " p = " << p << "\n"; |
|||
product_state_type t_p(t, p); |
|||
state_type prodIndexTo; |
|||
auto it = productStateToProductIndex.find(t_p); |
|||
if (it == productStateToProductIndex.end()) { |
|||
prodIndexTo = nextState++; |
|||
todo.push_back(prodIndexTo); |
|||
productIndexToProductState.push_back(t_p); |
|||
productStateToProductIndex[t_p] = prodIndexTo; |
|||
// std::cout << " Adding " << t_p.first << "," << t_p.second << " as " << prodIndexTo << "\n"; |
|||
} else { |
|||
prodIndexTo = it->second; |
|||
} |
|||
// std::cout << " " << t_p.first << "," << t_p.second << ": to = " << prodIndexTo << "\n"; |
|||
|
|||
// std::cout << " addNextValue(" << prodIndexFrom << "," << prodIndexTo << "," << entry.getValue() << ")\n"; |
|||
builder.addNextValue(prodIndexFrom, prodIndexTo, entry.getValue()); |
|||
} |
|||
} else { |
|||
throw std::runtime_error("nondeterministic product not yet supported"); |
|||
} |
|||
} |
|||
|
|||
state_type numberOfProductStates = nextState; |
|||
|
|||
Model product(builder.build(), storm::models::sparse::StateLabeling(numberOfProductStates)); |
|||
storm::storage::BitVector productStatesOfInterest(product.getNumberOfStates()); |
|||
for (auto& s : prodInitial) { |
|||
productStatesOfInterest.set(s); |
|||
} |
|||
std::string prodSoiLabel = product.getStateLabeling().addUniqueLabel("soi", productStatesOfInterest); |
|||
|
|||
// const storm::models::sparse::StateLabeling& orignalLabels = dtmc->getStateLabeling(); |
|||
// for (originalLabels.) |
|||
|
|||
return typename Product<Model>::ptr(new Product<Model>(std::move(product), |
|||
std::move(prodSoiLabel), |
|||
std::move(productStateToProductIndex), |
|||
std::move(productIndexToProductState))); |
|||
} |
|||
}; |
|||
} |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue