A utility for the creation and evaluation of self-stabilizing algorithms
Python Makefile
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.

README.org

SSA-Tool: Working with Self-Stabilizing Algorithms

https://travis-ci.org/vermiculus/ssa-tool.svg

This is a set of tools for the representation, creation, and evaluation of self-stabilizing algorithms.

Introduction

A self-stabilizing network is seen as a graph of state machines. Each privilege is realized as a transition from the current state to another state. The state of the graph is passed as input to this state machine. When the input graph matches some predicate, this privilege is set – there is some transition out of this state. This is why the choice of predicate to act upon is arbitrary: you can only move to one other state!

When every node of the graph is in an accepting state with no set predicates, then the graph has stabilized.

Privilege

  • We consider graphs of finite state machines.
  • Privileges are boolean functions of the FSM’s state and the states of its neighbors.
  • When these functions are true, the privilege is ‘present’.

System State

  • Each legitimate state must have at least one privilege present, even if the action is ‘do nothing’
  • In each legitimate state, every possible action will maintain legitimacy.
  • Each privilege must be present in at least one legitimate state.
  • For any given pair of legitimate states, there exists a transformation between them.

Self-Stabilization

Regardless of the initial state and regardless of the privilege selected each time for the next move, at least one privilege will always be present and the system is guaranteed to find itself in a legitimate state after a finite number of moves.

References

Examples

# define your predicates/moves
# predicates have access to node (v) and neighborhood (N) attributes
cat <<DONE > unmarked-and-neighbors-unmarked.py
marked = v['marked']
neighbor_marked = any(map(lambda n: n['marked'], N))
RESULT = not (marked or neighbor_marked)
DONE

cat <<DONE > marked-and-neighbor-marked.py
marked = v['marked']
neighbor_marked = any(map(lambda n: n['marked'], N))
RESULT = marked and neighbor_marked
DONE

# moves can set node state
cat <<DONE > mark.py
v['marked'] = True
DONE

cat <<DONE > unmark.py
v['marked'] = False
DONE


# move predefined code to the bundle
python3 ssa.py indset.ssax new predicate can-mark -p marked bool < unmarked-and-neighbors-unmarked.py
python3 ssa.py indset.ssax new move      mark     -p marked bool < mark.py

python3 ssa.py indset.ssax new predicate must-unmark -p marked bool < marked-and-neighbor-marked.py
python3 ssa.py indset.ssax new move      unmark      -p marked bool < unmark.py

# create a new algorithm
python3 ssa.py indset.ssax new algorithm 'Independent Set'

# define rules for that algorithm
python3 ssa.py indset.ssax add-rule-to 'Independent Set' can-mark mark
python3 ssa.py indset.ssax add-rule-to 'Independent Set' must-unmark unmark

# run the algorithm
python3 ssa.py indset.ssax run 'Independent Set' gn,5 1000 100

The above run command generates 1000 graphs and iterates the algorithm 100 times on each. The properties of nodes in the graph are determined by the predicates and moves composing the rules in the algorithm. For example:

-p age range,1,120...

In this example, range is called the generator descriptor and 1,120 are its arguments. This particular specification will ensure each node has an age attribute with a value between 1 and 120. The actual graph itself is determined by the gn,5 string you see in the run command. The descriptor here (gn) determines what mathematical properties the generated graph will have (tree/path/cycle/grid/…). Note some graph-generators can provide properties of their own.

Property generators defined on predicates/moves can be overridden at run-time with the --property-override option to run.

The definitive list of graph- and property-generators (and their arguments) are available in ssa.trial.

Installing

This package can be installed locally using pip install .. Be sure to install the requirements with pip install -r requirements.txt.

Alternatively, use the targets from the Makefile: make dependencies install.