- Clone the project
git clone https://github.com/wwszola/interactive_story
cd interactive_story
- Create, activate and prepare a virtual environment
python -m venv venv
./venv/Scripts/activate
pip install -r requirements.txt
python setup.py install
- Run some examples
python examples/example2.py
- In order to run tests:
pip install pytest
pytest tests/test1.py
- Deactivate the virtual environment after use
deactivate
from MarkovTool import Markov, Endless
process = Markov(3).fill_random(seed_ = 0)
print(Endless(process).take(10))
[0, 0, 2, 2, 0, 1, 1, 1, 1, 2]
We set dimension of the state space by calling constructor Markov
.
Method fill_random
generates values for probability matrix and initial probability vector. Identical description is generated every time by passing seed_
argument.
Constructor Endless
creates a new running instance. We generate first 10 states and print them to the terminal.
for _ in range(3):
print(Endless(process).take(10))
[2, 2, 2, 0, 1, 0, 1, 0, 2, 0]
[2, 0, 1, 0, 2, 0, 2, 0, 1, 0]
[0, 1, 2, 0, 2, 2, 0, 2, 0, 2]
The same description generates different processes. That happens because my_seed
property of Markov
defaults to None
, generating unique RNGs.
Set this property to make sure the process behaves in repeatable manner.
process.my_seed = 0
for _ in range(3):
print(Endless(process).take(10))
[2, 2, 0, 0, 0, 2, 2, 2, 2, 2]
[0, 2, 0, 0, 0, 2, 2, 2, 2, 2]
[1, 2, 0, 0, 0, 2, 2, 2, 2, 2]
To ensure the first state is always the same set initial_state
to an int
value.
process.initial_state = 1
for _ in range(3):
print(Endless(d).take(10))
[1, 2, 0, 0, 0, 2, 2, 2, 2, 2]
[1, 2, 0, 0, 0, 2, 2, 2, 2, 2]
[1, 2, 0, 0, 0, 2, 2, 2, 2, 2]
See also Markov.random
, Endless.skip
process = Markov(2).fill_random()
process.initial_state = 0
p_mat = process.matrix
# removing transition from state 1 to state 0 entirely
p_mat[1, 0] = 0.0
variation = process.variant(matrix = p_mat)
print(Endless(process).take(10))
print(Endless(variation).take(10))
[0, 0, 1, 1, 0, 1, 1, 0, 0, 1]
[0, 0, 0, 0, 0, 1, 1, 1, 1, 1]
Call method variant
to create a copy of the description. Pass properties you wish to change as keyword arguments.
You may run instances with different properties while keeping others to create complex behaviour. First, generate 5 steps from Endless
instance.
process = Markov(7, my_seed = 17).fill_random()
instance = Endless(process)
print(instance.take(5))
[4, 6, 1, 5, 3]
Next, run second unique process, which has _state
set to 4, by calling branch
. Both of them eventually converge to the same output. Instances produces the same states at the same steps, but only given the same previous state.
print(instance.branch(state=4).take(10))
print(instance.take(10))
[4, 1, 4, 5, 5, 0, 2, 4, 0, 6]
[1, 3, 2, 4, 5, 0, 2, 4, 0, 6]
Collector
allows to gather all instances running in a manner that takes into a consideration parallel branches, but no duplicates will be present.
Present in stat module
- parallel is itertools.zip_longest? : kinda, firing order if they depend on themselves
- just use itertools to get the result you want
- fill_random argument if initial_state too
- better collector:
-
- diff
-
- pretty summary
-
- counting occurences, pairs, triples
-
- playback: maybe cashe full chunks??
- model: parallel, correct firing order for dependence
- package distribution using setuptools
- load from file: we want json maybe?
- benchmark tests, how slow all of it is?
- tests: description -> instance -> stat