Matthias Volk
8 years ago
31 changed files with 726 additions and 158 deletions
-
2CMakeLists.txt
-
55lib/stormpy/__init__.py
-
4lib/stormpy/dft/__init__.py
-
73lib/stormpy/examples/files/ctmc/dft.drn
-
71lib/stormpy/examples/files/dft/and.json
-
10lib/stormpy/storage/__init__.py
-
36lib/stormpy/storage/action.py
-
35lib/stormpy/storage/state.py
-
5setup.py
-
8src/core/bisimulation.cpp
-
3src/core/core.cpp
-
1src/dft/common.h
-
34src/dft/dft.cpp
-
8src/dft/dft.h
-
15src/mod_dft.cpp
-
4src/mod_storage.cpp
-
7src/storage/bitvector.cpp
-
29src/storage/labeling.cpp
-
8src/storage/labeling.h
-
6src/storage/matrix.cpp
-
56src/storage/model.cpp
-
49src/storage/state.cpp
-
130src/storage/state.h
-
13tests/core/test_bisimulation.py
-
11tests/core/test_modelchecking.py
-
9tests/core/test_parse.py
-
19tests/dft/test_build.py
-
49tests/storage/test_labeling.py
-
16tests/storage/test_matrix.py
-
26tests/storage/test_model.py
-
92tests/storage/test_state.py
@ -0,0 +1,4 @@ |
|||
from . import dft |
|||
from .dft import * |
|||
|
|||
dft._set_up() |
@ -0,0 +1,73 @@ |
|||
// Exported by storm |
|||
// Original model type: CTMC |
|||
@type: CTMC |
|||
@parameters |
|||
|
|||
@nr_states |
|||
16 |
|||
@model |
|||
state 0 init |
|||
action 0 |
|||
1 : 0.5 |
|||
2 : 0.5 |
|||
3 : 0.5 |
|||
4 : 0.5 |
|||
state 1 |
|||
action 0 |
|||
5 : 0.5 |
|||
9 : 0.5 |
|||
11 : 0.5 |
|||
state 2 |
|||
action 0 |
|||
5 : 0.5 |
|||
14 : 0.5 |
|||
15 : 0.5 |
|||
state 3 |
|||
action 0 |
|||
9 : 0.5 |
|||
12 : 0.5 |
|||
15 : 0.5 |
|||
state 4 |
|||
action 0 |
|||
11 : 0.5 |
|||
12 : 0.5 |
|||
14 : 0.5 |
|||
state 5 |
|||
action 0 |
|||
6 : 0.5 |
|||
8 : 0.5 |
|||
state 6 |
|||
action 0 |
|||
7 : 0.5 |
|||
state 7 failed |
|||
action 0 |
|||
7 : 1 |
|||
state 8 |
|||
action 0 |
|||
7 : 0.5 |
|||
state 9 |
|||
action 0 |
|||
8 : 0.5 |
|||
10 : 0.5 |
|||
state 10 |
|||
action 0 |
|||
7 : 0.5 |
|||
state 11 |
|||
action 0 |
|||
6 : 0.5 |
|||
10 : 0.5 |
|||
state 12 |
|||
action 0 |
|||
10 : 0.5 |
|||
13 : 0.5 |
|||
state 13 |
|||
action 0 |
|||
7 : 0.5 |
|||
state 14 |
|||
action 0 |
|||
6 : 0.5 |
|||
13 : 0.5 |
|||
state 15 |
|||
action 0 |
|||
8 : 0.5 |
|||
13 : 0.5 |
@ -0,0 +1,71 @@ |
|||
{ |
|||
"toplevel": "2", |
|||
"parameters": {}, |
|||
"nodes": [ |
|||
{ |
|||
"data": { |
|||
"id": "0", |
|||
"name": "B", |
|||
"type": "be", |
|||
"rate": "0.5", |
|||
"dorm": "1", |
|||
"label": "B (0.5)" |
|||
}, |
|||
"position": { |
|||
"x": 426, |
|||
"y": 142 |
|||
}, |
|||
"group": "nodes", |
|||
"removed": false, |
|||
"selected": false, |
|||
"selectable": true, |
|||
"locked": false, |
|||
"grabbable": true, |
|||
"classes": "be" |
|||
}, |
|||
{ |
|||
"data": { |
|||
"id": "1", |
|||
"name": "C", |
|||
"type": "be", |
|||
"rate": "0.5", |
|||
"dorm": "1", |
|||
"label": "C (0.5)" |
|||
}, |
|||
"position": { |
|||
"x": 598, |
|||
"y": 139 |
|||
}, |
|||
"group": "nodes", |
|||
"removed": false, |
|||
"selected": false, |
|||
"selectable": true, |
|||
"locked": false, |
|||
"grabbable": true, |
|||
"classes": "be" |
|||
}, |
|||
{ |
|||
"data": { |
|||
"id": "2", |
|||
"name": "A", |
|||
"type": "and", |
|||
"children": [ |
|||
"0", |
|||
"1" |
|||
], |
|||
"label": "A" |
|||
}, |
|||
"position": { |
|||
"x": 503, |
|||
"y": 42 |
|||
}, |
|||
"group": "nodes", |
|||
"removed": false, |
|||
"selected": false, |
|||
"selectable": true, |
|||
"locked": false, |
|||
"grabbable": true, |
|||
"classes": "and toplevel" |
|||
} |
|||
] |
|||
} |
@ -1,36 +0,0 @@ |
|||
class Action: |
|||
""" Represents an action in the model """ |
|||
|
|||
def __init__(self, row_group_start, row_group_end, row, model): |
|||
""" Initialize |
|||
:param row_group_start: Start index of the row group in the matrix |
|||
:param row_group_end: End index of the row group in the matrix |
|||
:param row: Index of the corresponding row in the matrix |
|||
:param model: Corresponding model |
|||
""" |
|||
self.row_group_start = row_group_start |
|||
self.row_group_end = row_group_end |
|||
self.row = row - 1 |
|||
self.model = model |
|||
assert row >= -1 and row + row_group_start <= row_group_end |
|||
|
|||
def __iter__(self): |
|||
return self |
|||
|
|||
def __next__(self): |
|||
if self.row + self.row_group_start >= self.row_group_end - 1: |
|||
raise StopIteration |
|||
else: |
|||
self.row += 1 |
|||
return self |
|||
|
|||
def __str__(self): |
|||
return "{}".format(self.row) |
|||
|
|||
def transitions(self): |
|||
""" Get transitions associated with the action |
|||
:return List of tranistions |
|||
""" |
|||
row = self.row_group_start + self.row |
|||
#return self.model.transition_matrix().get_row(self.row_group_start + self.row) |
|||
return self.model.transition_matrix.row_iter(row, row) |
@ -1,35 +0,0 @@ |
|||
from . import action |
|||
|
|||
|
|||
class State: |
|||
""" Represents a state in the model """ |
|||
|
|||
def __init__(self, id, model): |
|||
""" Initialize |
|||
:param id: Id of the state |
|||
:param model: Corresponding model |
|||
""" |
|||
self.id = id - 1 |
|||
self.model = model |
|||
|
|||
def __iter__(self): |
|||
return self |
|||
|
|||
def __next__(self): |
|||
if self.id >= self.model.nr_states - 1: |
|||
raise StopIteration |
|||
else: |
|||
self.id += 1 |
|||
return self |
|||
|
|||
def __str__(self): |
|||
return "{}".format(self.id) |
|||
|
|||
def actions(self): |
|||
""" Get actions associated with the state |
|||
:return List of actions |
|||
""" |
|||
row_group_indices = self.model.transition_matrix._row_group_indices |
|||
start = row_group_indices[self.id] |
|||
end = row_group_indices[self.id+1] |
|||
return action.Action(start, end, 0, self.model) |
@ -0,0 +1 @@ |
|||
#include "src/common.h" |
@ -0,0 +1,34 @@ |
|||
#include "dft.h"
|
|||
#include "storm-dft/parser/DFTJsonParser.h"
|
|||
#include "storm-dft/builder/ExplicitDFTModelBuilderApprox.h"
|
|||
#include "storm/settings/SettingsManager.h"
|
|||
#include "storm-dft/settings/modules/DFTSettings.h"
|
|||
#include "storm-dft/storage/dft/DFTIsomorphism.h"
|
|||
|
|||
// Thin wrapper for model building using one formula as argument
|
|||
template<typename ValueType> |
|||
std::shared_ptr<storm::models::sparse::Model<ValueType>> buildModelFromJsonDft(std::string const& jsonDft, bool symred) { |
|||
// Build DFT
|
|||
storm::parser::DFTJsonParser<ValueType> parser; |
|||
storm::storage::DFT<ValueType> dft = parser.parseJson(jsonDft); |
|||
// Build model
|
|||
std::map<size_t, std::vector<std::vector<size_t>>> emptySymmetry; |
|||
storm::storage::DFTIndependentSymmetries symmetries(emptySymmetry); |
|||
if (symred) { |
|||
auto colouring = dft.colourDFT(); |
|||
symmetries = dft.findSymmetries(colouring); |
|||
} |
|||
storm::builder::ExplicitDFTModelBuilderApprox<ValueType> builder(dft, symmetries, true); |
|||
typename storm::builder::ExplicitDFTModelBuilderApprox<ValueType>::LabelOptions labeloptions({}, true); |
|||
builder.buildModel(labeloptions, 0, 0.0); |
|||
return builder.getModel(); |
|||
} |
|||
|
|||
void define_dft(py::module& m) { |
|||
m.def("_set_up", []() { |
|||
storm::settings::addModule<storm::settings::modules::DFTSettings>(); |
|||
}, "Initialize Storm-dft"); |
|||
// Build model
|
|||
m.def("build_sparse_model_from_json_dft", &buildModelFromJsonDft<double>, "Build the model", py::arg("jsonDft"), py::arg("symred") = false); |
|||
m.def("build_sparse_parametric_model_from_json_dft", &buildModelFromJsonDft<storm::RationalFunction>, "Build the parametric model", py::arg("jsonDft"), py::arg("symred") = false); |
|||
} |
@ -0,0 +1,8 @@ |
|||
#ifndef PYTHON_DFT_DFT_H_ |
|||
#define PYTHON_DFT_DFT_H_ |
|||
|
|||
#include "common.h" |
|||
|
|||
void define_dft(py::module& m); |
|||
|
|||
#endif /* PYTHON_DFT_DFT_H_ */ |
@ -0,0 +1,15 @@ |
|||
#include "common.h"
|
|||
|
|||
#include "dft/dft.h"
|
|||
|
|||
PYBIND11_PLUGIN(dft) { |
|||
py::module m("dft", "Functionality for DFT analysis"); |
|||
|
|||
#ifdef STORMPY_DISABLE_SIGNATURE_DOC
|
|||
py::options options; |
|||
options.disable_function_signatures(); |
|||
#endif
|
|||
|
|||
define_dft(m); |
|||
return m.ptr(); |
|||
} |
@ -0,0 +1,29 @@ |
|||
#include "labeling.h"
|
|||
|
|||
#include "storm/models/sparse/StateLabeling.h"
|
|||
|
|||
// Define python bindings
|
|||
void define_labeling(py::module& m) { |
|||
|
|||
// StateLabeling
|
|||
py::class_<storm::models::sparse::StateLabeling, std::shared_ptr<storm::models::sparse::StateLabeling>>(m, "StateLabeling", "Labeling for states") |
|||
.def("add_label", [](storm::models::sparse::StateLabeling& labeling, std::string label) { |
|||
labeling.addLabel(label); |
|||
}, py::arg("label"), "Add label") |
|||
.def("get_labels", &storm::models::sparse::StateLabeling::getLabels, "Get all labels") |
|||
.def("get_labels_of_state", &storm::models::sparse::StateLabeling::getLabelsOfState, "Get labels of given state", py::arg("state")) |
|||
.def("contains_label", &storm::models::sparse::StateLabeling::containsLabel, "Check if the given label is contained in the labeling", py::arg("label")) |
|||
.def("add_label_to_state", &storm::models::sparse::StateLabeling::addLabelToState, "Add label to state", py::arg("label"), py::arg("state")) |
|||
.def("has_state_label", &storm::models::sparse::StateLabeling::getStateHasLabel, "Check if the given state has the given label", py::arg("label"), py::arg("state")) |
|||
.def("get_states", &storm::models::sparse::StateLabeling::getStates, "Get all states which have the given label", py::arg("label")) |
|||
.def("set_states", [](storm::models::sparse::StateLabeling& labeling, std::string const& label, storm::storage::BitVector const& states) { |
|||
labeling.setStates(label, states); |
|||
}, "Set all states which have the given label", py::arg("label"), py::arg("states")) |
|||
.def("__str__", [](storm::models::sparse::StateLabeling const& labeling) { |
|||
std::ostringstream oss; |
|||
oss << labeling; |
|||
return oss.str(); |
|||
}) |
|||
; |
|||
|
|||
} |
@ -0,0 +1,8 @@ |
|||
#ifndef PYTHON_STORAGE_LABELING_H_ |
|||
#define PYTHON_STORAGE_LABELING_H_ |
|||
|
|||
#include "common.h" |
|||
|
|||
void define_labeling(py::module& m); |
|||
|
|||
#endif /* PYTHON_STORAGE_LABELING_H_ */ |
@ -0,0 +1,49 @@ |
|||
#include "state.h"
|
|||
|
|||
void define_state(py::module& m) { |
|||
|
|||
// SparseModelStates
|
|||
py::class_<SparseModelStates<double>>(m, "SparseModelStates", "States in sparse model") |
|||
.def("__getitem__", &SparseModelStates<double>::getState) |
|||
.def("__len__", &SparseModelStates<double>::getSize) |
|||
; |
|||
py::class_<SparseModelStates<storm::RationalFunction>>(m, "SparseParametricModelStates", "States in sparse parametric model") |
|||
.def("__getitem__", &SparseModelStates<storm::RationalFunction>::getState) |
|||
.def("__len__", &SparseModelStates<storm::RationalFunction>::getSize) |
|||
; |
|||
// SparseModelState
|
|||
py::class_<SparseModelState<double>>(m, "SparseModelState", "State in sparse model") |
|||
.def("__str__", &SparseModelState<double>::toString) |
|||
.def_property_readonly("id", &SparseModelState<double>::getIndex, "Id") |
|||
.def_property_readonly("labels", &SparseModelState<double>::getLabels, "Labels") |
|||
.def_property_readonly("actions", &SparseModelState<double>::getActions, "Get actions") |
|||
; |
|||
py::class_<SparseModelState<storm::RationalFunction>>(m, "SparseParametricModelState", "State in sparse parametric model") |
|||
.def("__str__", &SparseModelState<storm::RationalFunction>::toString) |
|||
.def_property_readonly("id", &SparseModelState<storm::RationalFunction>::getIndex, "Id") |
|||
.def_property_readonly("labels", &SparseModelState<storm::RationalFunction>::getLabels, "Labels") |
|||
.def_property_readonly("actions", &SparseModelState<storm::RationalFunction>::getActions, "Get actions") |
|||
; |
|||
|
|||
// SparseModelActions
|
|||
py::class_<SparseModelActions<double>>(m, "SparseModelActions", "Actions for state in sparse model") |
|||
.def("__getitem__", &SparseModelActions<double>::getAction) |
|||
.def("__len__", &SparseModelActions<double>::getSize) |
|||
; |
|||
py::class_<SparseModelActions<storm::RationalFunction>>(m, "SparseParametricModelActions", "Actions for state in sparse parametric model") |
|||
.def("__getitem__", &SparseModelActions<storm::RationalFunction>::getAction) |
|||
.def("__len__", &SparseModelActions<storm::RationalFunction>::getSize) |
|||
; |
|||
// SparseModelAction
|
|||
py::class_<SparseModelAction<double>>(m, "SparseModelAction", "Action for state in sparse model") |
|||
.def("__str__", &SparseModelAction<double>::toString) |
|||
.def_property_readonly("id", &SparseModelAction<double>::getIndex, "Id") |
|||
.def_property_readonly("transitions", &SparseModelAction<double>::getTransitions, "Get transitions") |
|||
; |
|||
py::class_<SparseModelAction<storm::RationalFunction>>(m, "SparseParametricModelAction", "Action for state in sparse parametric model") |
|||
.def("__str__", &SparseModelAction<storm::RationalFunction>::toString) |
|||
.def_property_readonly("id", &SparseModelAction<storm::RationalFunction>::getIndex, "Id") |
|||
.def_property_readonly("transitions", &SparseModelAction<storm::RationalFunction>::getTransitions, "Get transitions") |
|||
; |
|||
|
|||
} |
@ -0,0 +1,130 @@ |
|||
#ifndef PYTHON_STORAGE_STATE_H_ |
|||
#define PYTHON_STORAGE_STATE_H_ |
|||
|
|||
#include "common.h" |
|||
|
|||
#include "storm/storage/SparseMatrix.h" |
|||
#include "storm/models/sparse/Model.h" |
|||
|
|||
// Forward declaration |
|||
template<typename ValueType> |
|||
class SparseModelActions; |
|||
|
|||
// State definition |
|||
template<typename ValueType> |
|||
class SparseModelState { |
|||
using s_index = typename storm::storage::SparseMatrix<ValueType>::index_type; |
|||
|
|||
public: |
|||
SparseModelState(storm::models::sparse::Model<ValueType>& model, s_index stateIndex) : model(model), stateIndex(stateIndex) { |
|||
} |
|||
|
|||
s_index getIndex() const { |
|||
return stateIndex; |
|||
} |
|||
|
|||
std::set<std::string> getLabels() const { |
|||
return this->model.getStateLabeling().getLabelsOfState(this->stateIndex); |
|||
} |
|||
|
|||
SparseModelActions<ValueType> getActions() const { |
|||
return SparseModelActions<ValueType>(this->model, stateIndex); |
|||
} |
|||
|
|||
std::string toString() const { |
|||
std::stringstream stream; |
|||
stream << stateIndex; |
|||
return stream.str(); |
|||
} |
|||
|
|||
private: |
|||
s_index stateIndex; |
|||
storm::models::sparse::Model<ValueType>& model; |
|||
}; |
|||
|
|||
template<typename ValueType> |
|||
class SparseModelStates { |
|||
using s_index = typename storm::storage::SparseMatrix<ValueType>::index_type; |
|||
|
|||
public: |
|||
SparseModelStates(storm::models::sparse::Model<ValueType>& model) : model(model) { |
|||
length = model.getNumberOfStates(); |
|||
} |
|||
|
|||
s_index getSize() const { |
|||
return length; |
|||
} |
|||
|
|||
SparseModelState<ValueType> getState(s_index index) const { |
|||
if (index < length) { |
|||
return SparseModelState<ValueType>(model, index); |
|||
} else { |
|||
throw py::index_error(); |
|||
} |
|||
} |
|||
|
|||
private: |
|||
s_index length; |
|||
storm::models::sparse::Model<ValueType>& model; |
|||
}; |
|||
|
|||
// Action definition |
|||
template<typename ValueType> |
|||
class SparseModelAction { |
|||
using s_index = typename storm::storage::SparseMatrix<ValueType>::index_type; |
|||
|
|||
public: |
|||
SparseModelAction(storm::models::sparse::Model<ValueType>& model, s_index stateIndex, s_index actionIndex) : model(model), stateIndex(stateIndex), actionIndex(actionIndex) { |
|||
} |
|||
|
|||
s_index getIndex() const { |
|||
return this->actionIndex; |
|||
} |
|||
|
|||
typename storm::storage::SparseMatrix<ValueType>::rows getTransitions() { |
|||
return model.getTransitionMatrix().getRow(stateIndex, actionIndex); |
|||
} |
|||
|
|||
std::string toString() const { |
|||
std::stringstream stream; |
|||
stream << actionIndex; |
|||
return stream.str(); |
|||
} |
|||
|
|||
|
|||
private: |
|||
s_index stateIndex; |
|||
s_index actionIndex; |
|||
storm::models::sparse::Model<ValueType>& model; |
|||
}; |
|||
|
|||
template<typename ValueType> |
|||
class SparseModelActions { |
|||
using s_index = typename storm::storage::SparseMatrix<ValueType>::index_type; |
|||
|
|||
public: |
|||
SparseModelActions(storm::models::sparse::Model<ValueType>& model, s_index stateIndex) : model(model), stateIndex(stateIndex) { |
|||
length = model.getTransitionMatrix().getRowGroupSize(stateIndex); |
|||
} |
|||
|
|||
s_index getSize() const { |
|||
return length; |
|||
} |
|||
|
|||
SparseModelAction<ValueType> getAction(size_t index) const { |
|||
if (index < length) { |
|||
return SparseModelAction<ValueType>(model, stateIndex, index); |
|||
} else { |
|||
throw py::index_error(); |
|||
} |
|||
} |
|||
|
|||
private: |
|||
s_index stateIndex; |
|||
s_index length; |
|||
storm::models::sparse::Model<ValueType>& model; |
|||
}; |
|||
|
|||
void define_state(py::module& m); |
|||
|
|||
#endif /* PYTHON_STORAGE_STATE_H_ */ |
@ -0,0 +1,19 @@ |
|||
import stormpy |
|||
import stormpy.dft |
|||
import stormpy.logic |
|||
from helpers.helper import get_example_path |
|||
|
|||
import math |
|||
|
|||
class TestBuild: |
|||
def test_build_dft(self): |
|||
model = stormpy.dft.build_sparse_model_from_json_dft(get_example_path("dft", "and.json")) |
|||
formulas = stormpy.parse_properties("T=? [ F \"failed\" ]") |
|||
assert model.nr_states == 4 |
|||
assert model.nr_transitions == 5 |
|||
assert len(model.initial_states) == 1 |
|||
initial_state = model.initial_states[0] |
|||
assert initial_state == 1 |
|||
result = stormpy.model_checking(model, formulas[0]) |
|||
assert math.isclose(result.at(initial_state), 3) |
|||
|
@ -0,0 +1,49 @@ |
|||
import stormpy |
|||
import stormpy.logic |
|||
from helpers.helper import get_example_path |
|||
|
|||
class TestLabeling: |
|||
def test_set_labeling(self): |
|||
program = stormpy.parse_prism_program(get_example_path("dtmc", "die.pm")) |
|||
model = stormpy.build_model(program) |
|||
labeling = model.labeling |
|||
assert "tmp" not in labeling.get_labels() |
|||
assert not labeling.contains_label("tmp") |
|||
labeling.add_label("tmp") |
|||
assert labeling.contains_label("tmp") |
|||
labeling.add_label_to_state("tmp", 0) |
|||
assert labeling.has_state_label("tmp", 0) |
|||
states = labeling.get_states("tmp") |
|||
assert states.get(0) |
|||
states.set(3) |
|||
labeling.set_states("tmp", states) |
|||
assert labeling.has_state_label("tmp", 3) |
|||
|
|||
def test_label(self): |
|||
program = stormpy.parse_prism_program(get_example_path("dtmc", "die.pm")) |
|||
formulas = stormpy.parse_properties_for_prism_program("P=? [ F \"one\" ]", program) |
|||
model = stormpy.build_model(program, formulas) |
|||
labeling = model.labeling |
|||
labels = labeling.get_labels() |
|||
assert len(labels) == 3 |
|||
assert "init" in labels |
|||
assert "one" in labels |
|||
assert "init" in model.labels_state(0) |
|||
assert "init" in labeling.get_labels_of_state(0) |
|||
assert "one" in model.labels_state(7) |
|||
assert "one" in labeling.get_labels_of_state(7) |
|||
|
|||
def test_label_parametric(self): |
|||
program = stormpy.parse_prism_program(get_example_path("pdtmc", "brp16_2.pm")) |
|||
formulas = stormpy.parse_properties_for_prism_program("P=? [ F s=5 ]", program) |
|||
model = stormpy.build_parametric_model(program, formulas) |
|||
labels = model.labeling.get_labels() |
|||
assert len(labels) == 3 |
|||
assert "init" in labels |
|||
assert "(s = 5)" in labels |
|||
assert "init" in model.labels_state(0) |
|||
assert "(s = 5)" in model.labels_state(28) |
|||
assert "(s = 5)" in model.labels_state(611) |
|||
initial_states = model.initial_states |
|||
assert len(initial_states) == 1 |
|||
assert 0 in initial_states |
Write
Preview
Loading…
Cancel
Save
Reference in new issue