Skip to content

Commit 4e27cae

Browse files
committed
add docs for stater tracking
1 parent f687116 commit 4e27cae

4 files changed

Lines changed: 57 additions & 51 deletions

File tree

AUTHORS.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ Ciw has been developed by the following contributors:
1414
+ `Emma Aspland <https://github.com/EmmaAspland>`_
1515
+ `Henry Wilde <https://github.com/daffidwilde>`_
1616
+ `timlathy <https://github.com/timlathy>`_
17+
+ `Michalis Panayides <https://github.com/11michalis11>`_

docs/Guides/deadlock.rst

Lines changed: 1 addition & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -48,54 +48,4 @@ Running until deadlock (using a :code:`ciw.trackers.NaiveBlocking` object)::
4848
>>> Q.times_to_deadlock # doctest:+SKIP
4949
{((0, 0),): 0.94539784..., ((1, 0),): 0.92134933..., ((2, 0),): 0.68085451..., ((3, 0),): 0.56684471..., ((3, 1),): 0.0, ((4, 0),): 0.25332344...}
5050

51-
Here the keys correspond to states recorded by the state tracker.
52-
53-
54-
55-
.. _state-trackers:
56-
57-
How to Set a State Tracker
58-
==========================
59-
60-
Ciw has the option to activate a state :code:`tracker` in order to track the state of the system as the simulation progresses towards deadlock.
61-
In the example above a :code:`NaiveBlocking` was used.
62-
The default is the basic :code:`StateTracker` which does nothing.
63-
The state trackers have their uses when simulating until deadlock, as a time to deadlock is recorded for every state the simulation reaches.
64-
65-
For a list and explanation of the state trackers that Ciw currently supports see :ref:`refs-statetrackers`.
66-
67-
Consider the M/M/2/1 queue with a feedback loop.
68-
The following states are expected if a NaiveBlocking Tracker is used: ((0, 0)), ((1, 0)), ((2, 0)), ((3, 0)), ((2, 1)), ((1, 2)).
69-
Simulating until deadlock, the :code:`times_to_deadlock` dictionary will contain a subset of these states as keys::
70-
71-
>>> import ciw
72-
>>> N = ciw.create_network(
73-
... arrival_distributions=[ciw.dists.Exponential(6.0)],
74-
... service_distributions=[ciw.dists.Exponential(5.0)],
75-
... routing=[[0.5]],
76-
... number_of_servers=[2],
77-
... queue_capacities=[1]
78-
... )
79-
80-
>>> ciw.seed(1)
81-
>>> Q = ciw.Simulation(N,
82-
... deadlock_detector=ciw.deadlock.StateDigraph(),
83-
... tracker=ciw.trackers.NaiveBlocking()
84-
... )
85-
>>> Q.simulate_until_deadlock()
86-
>>> Q.times_to_deadlock # doctest:+SKIP
87-
{((0, 0),): 1.3354..., ((1, 0),): 1.3113..., ((1, 2),): 0.0, ((2, 0),): 1.0708..., ((2, 1),): 0.9353..., ((3, 0),): 0.9568...}
88-
89-
The following states are expected if a MatrixBlocking Tracker is used: ((()), (0)), ((()), (1)), ((()), (2)), ((()), (3)), (((1)), (3)), (((1, 2)), (3)).
90-
91-
>>> ciw.seed(1)
92-
>>> Q = ciw.Simulation(N,
93-
... deadlock_detector=ciw.deadlock.StateDigraph(),
94-
... tracker=ciw.trackers.MatrixBlocking()
95-
... )
96-
>>> Q.simulate_until_deadlock()
97-
>>> Q.times_to_deadlock # doctest:+SKIP
98-
{((((),),), (0,)): 1.3354..., ((((),),), (1,)): 1.3113..., ((((),),), (2,)): 1.0708..., ((((),),), (3,)): 0.9568..., ((((1,),),), (3,)): 0.9353..., ((((1, 2),),), (3,)): 0.0}
99-
100-
Notice that in this simple case, the NaiveBlocking and MatrixBlocking trackers correspond to the same states.
101-
In other examples, where customers may get blocked in different orders and to different places, then the two trackers may track different system states.
51+
Here the keys correspond to states recorded by the state tracker. Note in order for :code:`times_to_deadlock` to be meaningful, a state tracker must be used.

docs/Guides/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Contents:
1919
baulking.rst
2020
server_schedule.rst
2121
dynamic_customerclasses.rst
22+
state_trackers.rst
2223
deadlock.rst
2324
process_based.rst
2425
behaviour.rst

docs/Guides/state_trackers.rst

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
.. state-trackers:
2+
3+
===============================
4+
How to Track the System's State
5+
===============================
6+
7+
The system's state is the configuration of individuals around the system. It can be measured in a variety of ways - for example, a state can be the number of customers waiting at each node.
8+
9+
Ciw has the option to activate a state :code:`tracker` in order to track the state of the system as the simulation progresses through the simulation. This tracker has a number of uses: the system state's full history can be obtained, from which state probabilities can be found, and it has uses when investigating deadlock.
10+
11+
The default is the basic :code:`StateTracker` which does nothing.
12+
A number of other state trackers can be implemented, which record the system's state in a number of ways. These objects inherit from the basic :code:`StateTracker` class, and so custom state trackers can also be implemented by doing this.
13+
For a list and explanation of the state trackers that Ciw currently supports see :ref:`refs-statetrackers`.
14+
15+
16+
Example: consider an M/M/1 queue. The :code:`SystemPopulation` tracker defines a state as the number of individuals in the system::
17+
18+
>>> import ciw
19+
>>> N = ciw.create_network(
20+
... arrival_distributions=[ciw.dists.Exponential(0.1)],
21+
... service_distributions=[ciw.dists.Exponential(0.2)],
22+
... number_of_servers=[1]
23+
... )
24+
25+
>>> ciw.seed(1)
26+
>>> Q = ciw.Simulation(N,
27+
... tracker=ciw.trackers.SystemPopulation()
28+
... )
29+
>>> Q.simulate_until_max_time(250)
30+
31+
Now the system's history can be viewed::
32+
33+
>>> Q.statetracker.history # doctest:+SKIP
34+
[[0.0, 0],
35+
[1.44291..., 1],
36+
[10.84369..., 0],
37+
[15.87259..., 1],
38+
[17.34491..., 0],
39+
[22.71318..., 1],
40+
[25.69774..., 0],
41+
...
42+
]
43+
44+
This shows that the system was in state :code:`0` from time 0.0 to 1.44291, was in state :code:`1` from time 1.44291 to 10.84369, went back to state :code:`0` from 10.84369 to time 15.87259, and so on.
45+
46+
From this we can obtain the proportion of time the system spend in each state::
47+
48+
>>> Q.statetracker.state_probabilities() # doctest:+SKIP
49+
{0: 0.55425..., 1: 0.24676..., 2: 0.13140..., 3: 0.06757...}
50+
51+
So the system was in state :code:`0` (no individuals in the system) 55.4% of the time, in state :code:`1` (one individual in the system) 24.7% of the time, state :code:`2` (two individuals in the system) 13.1% of the time, and state :code:`3` (three individuals in the system) 6.8% of the time.
52+
53+
54+
Note that different trackers represent different states in different ways, see :ref:`refs-statetrackers` for a list of implemented trackers.

0 commit comments

Comments
 (0)