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