hannah
4 years ago
committed by
Matthias Volk
No known key found for this signature in database
GPG Key ID: 83A57678F739FCD3
3 changed files with 200 additions and 0 deletions
-
1doc/source/advanced_topics.rst
-
132doc/source/doc/building_dtmcs.rst
-
67examples/building_dtmcs/01-building-dtmcs.py
@ -0,0 +1,132 @@ |
|||
********************************** |
|||
Discrete-time Markov chains (DTMCs) |
|||
********************************** |
|||
|
|||
|
|||
Background |
|||
===================== |
|||
As described in :doc:`../getting_started`, |
|||
Storm can be used to translate a model description e.g. in form of a prism file into a Markov chain. |
|||
|
|||
Here, we use Stormpy to create the single components, to build a DTMC without parsing a model description. |
|||
We consider the previous example of the die. |
|||
|
|||
.. seealso:: `01-building-dtmcs.py <todo/02-gspns.py/examples/building_dtmcs/01-building-dtmcs.py>` |
|||
|
|||
In the following we create transition matrix, the state labeling and the reward models of a DTMC. |
|||
First, we import stormpy:: |
|||
|
|||
>>> import stormpy |
|||
|
|||
Transition Matrix |
|||
===================== |
|||
We begin by creating the matrix representing the transitions in the model in terms of probabilities. |
|||
For constructing the transition matrix, we use the SparseMatrixBuilder:: |
|||
|
|||
>>> builder = stormpy.SparseMatrixBuilder(rows = 0, columns = 0, entries = 0, force_dimensions = False, has_custom_row_grouping = False) |
|||
|
|||
Here, we start with an empty matrix to later insert more entries. |
|||
If the number of rows, columns and entries is known, the matrix can be constructed using these values. |
|||
|
|||
For DTMCs each state has at most one outgoing probability distribution. |
|||
Thus, we create matrix with trivial row grouping where each group contains one row representing the state action. |
|||
|
|||
We specify the transitions of the model, by adding values to the matrix where the column represents the target state. |
|||
All transitions are equipped with a probability defined by the value:: |
|||
|
|||
>>> builder.add_next_value(row = 0, column = 1, value = 0.5) |
|||
>>> builder.add_next_value(0, 2, 0.5) |
|||
>>> builder.add_next_value(1, 3, 0.5) |
|||
>>> builder.add_next_value(1, 4, 0.5) |
|||
>>> builder.add_next_value(2, 5, 0.5) |
|||
>>> builder.add_next_value(2, 6, 0.5) |
|||
>>> builder.add_next_value(3, 7, 0.5) |
|||
>>> builder.add_next_value(3, 1, 0.5) |
|||
>>> builder.add_next_value(4, 8, 0.5) |
|||
>>> builder.add_next_value(4, 9, 0.5) |
|||
>>> builder.add_next_value(5, 10, 0.5) |
|||
>>> builder.add_next_value(5, 11, 0.5) |
|||
>>> builder.add_next_value(6, 2, 0.5) |
|||
>>> builder.add_next_value(6, 12, 0.5) |
|||
|
|||
Lastly, we add a self-loop with probability one to the final states:: |
|||
|
|||
>>> for s in range(7,13): |
|||
>>> builder.add_next_value(s, s, 1) |
|||
|
|||
|
|||
Finally, we can build the matrix with updated row and columns count that both coincide with the number of states:: |
|||
|
|||
>>> transition_matrix = builder.build(13, 13) |
|||
|
|||
It should be noted that entries can only be inserted in ascending order, i.e. row by row and column by column. |
|||
Stormpy provides the possibility to build a sparse matrix using the numpy library <https://numpy.org/> |
|||
Instead of using the SparseMatrixBuilder, a sparse matrix can be build from a numpy array via the method stormpy.build_sparse_matrix. |
|||
|
|||
Labeling |
|||
==================== |
|||
|
|||
States can be labelled with sets of propositions, for example state 0 can be labelled with 'init'. |
|||
In order to specify the state labeling we create an empty labeling for the given number of states and add the labels to the labeling:: |
|||
|
|||
>>> state_labeling = stormpy.storage.StateLabeling(13) |
|||
|
|||
>>> labels = {'init', 'one', 'two', 'three', 'four', 'five', 'six', 'done', 'deadlock'} |
|||
>>> for label in labels: |
|||
>>> state_labeling.add_label(label) |
|||
|
|||
Next, we set teh associations between the labels and the respective states.:: |
|||
|
|||
>>> state_labeling.add_label_to_state('init', 0) |
|||
>>> state_labeling.add_label_to_state('one', 7) |
|||
>>> state_labeling.add_label_to_state('two', 8) |
|||
>>> state_labeling.add_label_to_state('three', 9) |
|||
>>> state_labeling.add_label_to_state('four', 10) |
|||
>>> state_labeling.add_label_to_state('five', 11) |
|||
>>> state_labeling.add_label_to_state('six', 12) |
|||
|
|||
To set the same label for multiple states, we can use a BitVector representation for the set of states:: |
|||
|
|||
>>> state_labeling.set_states('done', stormpy.BitVector(13, [7, 8, 9, 10, 11, 12])) |
|||
|
|||
In addition, it is possible to define a choice labeling, which is described in :doc:`building_ctmcs`. |
|||
|
|||
Reward Models |
|||
==================== |
|||
Stormpy supports multiple reward models such as state rewards, state-action rewards and as transition rewards. |
|||
In this example, the actions of states which satisfy s<7 acquire a reward of 1.0. |
|||
|
|||
The state-action rewards are represented by a vector, which is associated to a reward model named 'coin_flips':: |
|||
|
|||
>>> reward_models = {} |
|||
>>> action_reward = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] |
|||
>>> reward_models['coin_flips'] = stormpy.SparseRewardModel(optional_state_action_reward_vector = action_reward) |
|||
|
|||
Building the Model |
|||
==================== |
|||
|
|||
Next, we collect all components:: |
|||
|
|||
>>> components = stormpy.SparseModelComponents(transition_matrix=transition_matrix, state_labeling=state_labeling, reward_models=reward_models) |
|||
|
|||
And finally, we can build the DTMC:: |
|||
|
|||
>>> dtmc = stormpy.storage.SparseDtmc(components) |
|||
>>> print(dtmc) |
|||
-------------------------------------------------------------- |
|||
Model type: DTMC (sparse) |
|||
States: 13 |
|||
Transitions: 20 |
|||
Reward Models: coin_flips |
|||
State Labels: 9 labels |
|||
* three -> 1 item(s) |
|||
* six -> 1 item(s) |
|||
* done -> 6 item(s) |
|||
* four -> 1 item(s) |
|||
* five -> 1 item(s) |
|||
* deadlock -> 0 item(s) |
|||
* init -> 1 item(s) |
|||
* two -> 1 item(s) |
|||
* one -> 1 item(s) |
|||
Choice Labels: none |
|||
-------------------------------------------------------------- |
@ -0,0 +1,67 @@ |
|||
import stormpy |
|||
import numpy as np |
|||
|
|||
|
|||
def example_building_dtmcs_01(): |
|||
|
|||
|
|||
# Use the SparseMatrixBuilder for constructing the transition matrix |
|||
builder = stormpy.SparseMatrixBuilder(rows = 0, columns = 0, entries = 0, force_dimensions = False, has_custom_row_grouping = False) |
|||
|
|||
# New Transition from state 0 to target state 1 with probability 0.5 |
|||
builder.add_next_value(row = 0, column = 1, value = 0.5) |
|||
builder.add_next_value(0, 2, 0.5) |
|||
builder.add_next_value(1, 3, 0.5) |
|||
builder.add_next_value(1, 4, 0.5) |
|||
builder.add_next_value(2, 5, 0.5) |
|||
builder.add_next_value(2, 6, 0.5) |
|||
builder.add_next_value(3, 7, 0.5) |
|||
builder.add_next_value(3, 1, 0.5) |
|||
builder.add_next_value(4, 8, 0.5) |
|||
builder.add_next_value(4, 9, 0.5) |
|||
builder.add_next_value(5, 10, 0.5) |
|||
builder.add_next_value(5, 11, 0.5) |
|||
builder.add_next_value(6, 2, 0.5) |
|||
builder.add_next_value(6, 12, 0.5) |
|||
|
|||
# Add transitions for the final states |
|||
for s in range(7,13): |
|||
builder.add_next_value(s, s, 1) |
|||
|
|||
# Build matrix |
|||
transition_matrix = builder.build(13, 13) |
|||
|
|||
# State labeling |
|||
state_labeling = stormpy.storage.StateLabeling(13) |
|||
|
|||
# Add labels |
|||
labels = {'init','one', 'two', 'three', 'four', 'five', 'six', 'done', 'deadlock'} |
|||
for label in labels: |
|||
state_labeling.add_label(label) |
|||
|
|||
# Add label to state |
|||
state_labeling.add_label_to_state('init', 0) |
|||
state_labeling.add_label_to_state('one', 7) |
|||
state_labeling.add_label_to_state('two', 8) |
|||
state_labeling.add_label_to_state('three', 9) |
|||
state_labeling.add_label_to_state('four', 10) |
|||
state_labeling.add_label_to_state('five', 11) |
|||
state_labeling.add_label_to_state('six', 12) |
|||
|
|||
# Add label 'done' to multiple states |
|||
state_labeling.set_states('done', stormpy.BitVector(13, [7, 8, 9, 10, 11, 12])) |
|||
|
|||
# Reward models: |
|||
reward_models = {} |
|||
# Create a vector representing the state-action rewards |
|||
action_reward = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] |
|||
reward_models['coin_flips'] = stormpy.SparseRewardModel(optional_state_action_reward_vector = action_reward) |
|||
|
|||
components = stormpy.SparseModelComponents(transition_matrix=transition_matrix, state_labeling=state_labeling, reward_models=reward_models) |
|||
|
|||
dtmc = stormpy.storage.SparseDtmc(components) |
|||
|
|||
print(dtmc) |
|||
|
|||
if __name__ == '__main__': |
|||
example_building_dtmcs_01() |
Write
Preview
Loading…
Cancel
Save
Reference in new issue