Giter VIP home page Giter VIP logo

pyrandwalk's Introduction

pyrandwalk-logo

๐Ÿšถ Python Library for Random Walks

built with Python3 CodeFactor Document


Table of contents

Overview

Pyrandwalk is an educational tool for simulating random walks, calculating the probability of given state sequences, etc. Random walk is a representation of the discrete-time, discrete-value Markov chain model used in stochastic processes.

PyPI Counter
Github Stars
Branch master dev
CI

Installation

Source code

  • Download Version 1.1 or Latest Source
  • Run pip install -r requirements.txt or pip3 install -r requirements.txt (Need root access)
  • Run python3 setup.py install or python setup.py install (Need root access)

PyPI

Usage

>>> from pyrandwalk import *
>>> import numpy as np
>>> states = [0, 1, 2, 3, 4]
>>> trans = np.array([[1,    0, 0,    0, 0],
...                   [0.25, 0, 0.75, 0, 0],
...                   [0, 0.25, 0, 0.75, 0],
...                   [0, 0, 0.25, 0, 0.75],
...                   [0, 0,    0, 1,    0]])
>>> rw = RandomWalk(states, trans)

We are simulating random walks on the above graph (weights are probabilities):

Probability of A Sequence

Imagine you want to calculate probability which you start from state 2, go to state 1 and stuck in state 0. What's the probability of these walk sequences?

>>> rw.prob_sec([2, 1, 0])
0.0125

Initial probability distribution is assumed to be uniform by default but you can change it by passing optional argument initial_dist:

>>> rw.prob_sec([2, 1, 0], initial_dist=[0, 0, 1, 0, 0])
0.0625

Run a random walk

You can start a random walk on given markov chain and see the result:

>>> states, probs = rw.run()
>>> states
[4, 3, 4, 3, 4, 3, 4, 3, 2, 3, 4]
>>> probs
[0.2, 1.0, 0.75, 1.0, 0.75, 1.0, 0.75, 1.0, 0.25, 0.75, 0.75]

By default your random walk will contain 10 steps, but you can change it by passing optional argument ntimes:

>>> states, probs = rw.run(ntimes=20)
>>> states
[3, 4, 3, 4, 3, 2, 1, 2, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 2, 3]
>>> probs
[0.2, 0.75, 1.0, 0.75, 1.0, 0.25, 0.25, 0.75, 0.75, 0.75, 1.0, 0.75, 1.0, 0.75, 1.0, 0.75, 1.0, 0.75, 1.0, 0.25, 0.75]

And if you want to see what's going on down there during the simulation you can set the show flag:

>>> states, probs = rw.run(ntimes=30, show=True)
1 --> 2  (p = 0.750)
2 --> 3  (p = 0.750)
3 --> 4  (p = 0.750)
4 --> 3  (p = 1.000)
3 --> 4  (p = 0.750)
4 --> 3  (p = 1.000)
3 --> 4  (p = 0.750)
4 --> 3  (p = 1.000)
3 --> 4  (p = 0.750)
4 --> 3  (p = 1.000)
3 --> 4  (p = 0.750)
4 --> 3  (p = 1.000)
3 --> 4  (p = 0.750)
4 --> 3  (p = 1.000)
3 --> 2  (p = 0.250)
2 --> 1  (p = 0.250)
1 --> 2  (p = 0.750)
2 --> 3  (p = 0.750)
3 --> 4  (p = 0.750)
4 --> 3  (p = 1.000)
3 --> 4  (p = 0.750)
4 --> 3  (p = 1.000)
3 --> 4  (p = 0.750)
4 --> 3  (p = 1.000)
3 --> 4  (p = 0.750)
4 --> 3  (p = 1.000)
3 --> 4  (p = 0.750)
4 --> 3  (p = 1.000)
3 --> 2  (p = 0.250)
2 --> 3  (p = 0.750)
>>> states
[1, 2, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 2, 1, 2, 3, 4, 3, 4, 3, 4, 3, 4, 3, 4, 3, 2, 3]
>>> probs
[0.2, 0.75, 0.75, 0.75, 1.0, 0.75, 1.0, 0.75, 1.0, 0.75, 1.0, 0.75, 1.0, 0.75, 1.0, 0.25, 0.25, 0.75, 0.75, 0.75, 1.0, 0.75, 1.0, 0.75, 1.0, 0.75, 1.0, 0.75, 1.0, 0.25, 0.75]

Final Probability Distribution

You can easily find out the final probability distribution of you random walk by:

>>> rw.final_dist()
array([1., 0., 0., 0., 0.])

Which implies that the walk will in state 0 for sure as time goes on.

Is it irreducible?

You can check if your Markov chain is irreducible to lower rank ones or not by:

>>> rw.is_irreducible()
False

nth transition matrix

If you want to see what's the probability of moving from state i to j with n steps, you can easily calculate the nth transition matrix by:

>>> rw.trans_power(2)
array([[1.    , 0.    , 0.    , 0.    , 0.    ],
       [0.25  , 0.1875, 0.    , 0.5625, 0.    ],
       [0.0625, 0.    , 0.375 , 0.    , 0.5625],
       [0.    , 0.0625, 0.    , 0.9375, 0.    ],
       [0.    , 0.    , 0.25  , 0.    , 0.75  ]])

Graph edges

You can have your final graph edges in a list containing tuples like (from, to, probability) for each edge by:

>>> rw.get_edges()
[(0, 0, 1.0), (1, 0, 0.25), (1, 2, 0.75), (2, 1, 0.25), (2, 3, 0.75), (3, 2, 0.25), (3, 4, 0.75), (4, 3, 1.0)]

Graph

Making a networkx graph object from your random walk process is also token care of by this library:

>>> rw_graph = rw.get_graph()

Colors of Nodes [will be removed]

Until now we could not show graphs with self-loops using networkx so as far as this feature being added to networkx, we're using blue color for ordinary states and red color for states with self-loop.

>>> rw.get_colormap()
['red', 'blue', 'blue', 'blue', 'blue']

Type of Classes

For knowing which class is recurrent or transient you can use above method, you can also have reduced transition matrix for each set.

>>> rw_class_types = rw.get_typeof_classes()
>>> rw_class_types['recurrent']
([0], array([[1.]]))
>>> rw_class_types['transient'][0]
[1, 2, 3, 4]
>>> rw_class_types['transient'][1]
array([[0.  , 0.75, 0.  , 0.  ],
       [0.25, 0.  , 0.75, 0.  ],
       [0.  , 0.25, 0.  , 0.75],
       [0.  , 0.  , 1.  , 0.  ]])

The Best Policy Problems

For making the best policy problems for your random walk you can easily:

>>> states = [0, 1, 2]
>>> trans = np.array([[1, 0, 0], [1/2, 0, 1/2], [0, 1, 0]])
>>> rw = RandomWalk(states, trans, payoff=[0, 1, 4], cost=[1, 0, 2], discount=0.5)
>>> rw.best_policy()
{'continue': [], 'stop': [0, 1, 2]}

References

1- Lawler, Gregory F. Introduction to stochastic processes. Chapman and Hall/CRC, 2018.
2- Markusfeng
Icon made by Becris from www.flaticon.com

pyrandwalk's People

Contributors

sadrasabouri avatar sepandhaghighi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

pyrandwalk's Issues

`states` array of data type `np.ndarray` causes an error when trying to find index of values

Description

The current code for simulating a random walk cannot handle data type np.array as the states vector, given that numpy arrays do not have index attribute.

Steps/Code to Reproduce

With the current code base, the issue can be reproduced using the following:

from pyrandwalk import *
import numpy as np

# Using the same examples given in README for transition matrix
trans = np.array([[1,    0, 0,    0, 0], [0.25, 0, 0.75, 0, 0],[0, 0.25, 0, 0.75, 0], [0, 0, 0.25, 0, 0.75], [0, 0,    0, 1,    0]])
# The only change here is to switch `states` from a List to np.array
states =np.array([0,1,2,3,4])
# This is the check that is run using a utility to ensure the correct data types are used for states
print(isinstance(states, (list, np.ndarray)))
# >>> True
rw = RandomWalk(states, trans)
states, probs = rw.run()
# Error: `AttributeError: 'numpy.ndarray' object has no attribute 'index'`

Operating System

Linux

Python Version

Python 3.9.12

pyrandwalk Version

1.1

I will try to do a PR later to handle this issue by using np.where when we have a numpy array.

`plot_graph` method bug

Description

This bug is occurring because of a bad approach taken for setting the plot title which seems deprecated, now.

Steps/Code to Reproduce

So when you use the method like this:

ax = rw.plot_graph()

Expected Behavior

The graph shows happily.

Actual Behavior

UNEXPECTED EXCEPTION: AttributeError("'FigureCanvasAgg' object has no attribute 'set_window_title'")
Traceback (most recent call last):
    ....
AttributeError: 'FigureCanvasAgg' object has no attribute 'set_window_title'

Operating System

Unbuntu

Python Version

3.8

pyrandwalk Version (Use : pyrandwalk.__version__)

1.1

pyrandwalk JOSE paper

Description

This repository has educational potential which can be published as a paper on Journal of Open Source Educational.

For this goal we need to take into consideration some actions which described here.
Related works will be fallowed on branch jose-paper-branch.

Handling Deadends

Description

In some cases, the random walker will reach nodes with no option but to stay in the same state. This situation referred to as the dead ends can be handled by teleportation in these nodes - as mentioned in ML with graphs.

Steps/Code to Reproduce

rw = RandomWalk([0, 1], [[1, 0], [0.5, 0.5]], jump_on_deadends=True)

Expected Behavior

The random walker will no longer be stuck in dead-end situations.

Operating System

Ubuntu

Python Version

3.8

pyrandwalk Version (Use : pyrandwalk.__version__)

1.1

Add Pay-off Cost Random Walks

Description

There is a major category in random walk which you will be payed off according to given payoff list by stopping your walk in each state and/or will pay a cost according to given cost variable. (You may take a factor called discount into consider which will be manipulate our payoff by multiplying into it. [0<discount<=1])

>>> rw = RandomWalk([0, 1, 2],
...                [[0.5, 0.5, 0], [0.25, 0.5, 0.25], [0, 0, 0]],
...                payoff=[1, 4, 0],
...                cost=0.5,
...                discount=0.9)
>>> rw.best_policy()

Add Teleportation Probability

Description

There are some cases in which the random walker would jump to none-adjacent states (Teleport) which you can see one of its use cases here in PageRank Overview by Dan Jurafsky.

Steps/Code to Reproduce

>>> rw = RandomWalk([0, 1], [[1, 0], [0.5, 0.5]], teleport_prob=0.9)

Tasks To Be Done for v1

These are the works that should be done before our first release:

  • Error handling in each function
  • Add final_dist method for calculating final distirbution of the random walk.
  • Tests for graphical part and macOS
  • Making a .ipynb document and its tests
  • Version releasing tasks
  • Add codefactor
  • Add related badeges to README.md

Add string type state support

Description

Until now pyrandwalk just accept numbers(ints) as its states, it would be nice if we add other types support too.

For example we can take into consider a BiGram simulation like bellow:

Steps/Code to Reproduce

>>> lexicon = ['I', 'eat', 'food']
>>> bigram = np.array([[0.1, 0.8, 0.1], [0.3, 0.1, 0.6], [0.6, 0.3, 0.1]])
>>> rw = RandomWalk(lexicon, bigram)
>>> states, probs = rw.run()

Expected Behavior

>>> states
['I', 'eat', 'food', 'food', 'I', 'food', 'I', 'eat', 'food', 'I', 'eat']
>>> probs
[0.3, 0.8, 0.6, 0.1, 0.6, 0.1, 0.1, 0.8, 0.6, 0.6, 0.8]

Actual Behavior

Traceback (most recent call last):
    ...
IndexError: only integers, slices (`:`), ellipsis (`...`), numpy.newaxis (`None`) and integer or boolean arrays are valid indices

Operating System

Linux 5.4.0-80-generic #90-Ubuntu SMP Fri Jul 9 22:49:44 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

Python Version

Python 3.8.10

pyrandwalk Version (Use : pyrandwalk.__version__)

1.0

Remove networkx dependencies

Description

networkx is a huge dependency and I wonder if we should replace it by a more lightweight library.

In pyrandwalk we just use networkx for two reasons:

  1. checking strongly connectivity (networkx.is_strongly_connected in is_irreducible)
  2. getting strongly connected components (networkx.strongly_connected_components in get_typeof_classes)
  3. making graphs (netwokx.DiGraph in get_graph)
  4. plotting graphs (networkx.draw_circular in plot_graph)

As a alternative we can use graph-tools.

Any other options will be highly accepted.

Add Reference Examples to Documents

Description

There are some examples for different uses of random walks on references (like the main reference) this issue is concerning adding these examples to Document/examples.ipynb

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.