Skip to main content

A package for simulating population protocols.

Project description

ppsim Python package

The ppsim package is used for simulating population protcols. The core of the simulator uses a batching algorithm which gives significant asymptotic gains for protocols with relatively small reachable state sets. The package is designed to be run in a Python notebook, to concisely describe complex protocols, efficiently simulate their dynamics, and provide helpful visualization of the simulation.

Installation

The package can be installed with pip via

pip install ppsim

The most important part of the package is the Simulation class, which is responsible for parsing a protocol, performing the simulation, and giving data about the simulation.

from ppsim import Simulation

Example protcol

A state can be any hashable Python object. The simplest way to describe a protocol is a dictionary mapping pairs of input states to pairs of output states. For example, here is a description of the classic 3-state approximate majority protocol. There are two initial states A and B, and the protocol converges with high probability to the majority state with the help of a third "undecided" state U.

a, b, u = 'A', 'B', 'U'
approximate_majority = {
    (a,b): (u,u),
    (a,u): (a,a),
    (b,u): (b,b)
}

Example Simulation

To instantiate a Simulation, we must specify a protocol along with an initial condition, which is a dictionary mapping states to counts. Let's simulate approximate majority with in a population of one billion agents with a slight majority of A agents.

n = 10 ** 9
init_config = {a: 0.501 * n, b: 0.499 * n}
sim = Simulation(init_config, approximate_majority)

Now let's run this simulation for 10 units of parallel time (10 * n interactions). We will record the configuration every 0.1 units of time.

sim.run(10, 0.1)

The Simulation class can display all these configurations in a pandas dataframe in the attribute history.

sim.history
A B U
time
0.000000 501000000 499000000 0
0.100010 478285585 476280966 45433449
0.200039 459449200 457428961 83121839
0.300056 443650105 441607805 114742090
0.400098 430264769 428196457 141538774
... ... ... ...
9.601324 352755117 314377928 332866955
9.701327 353418258 313744457 332837285
9.801359 354106871 313093847 332799282
9.901364 354824761 312423976 332751263
10.001375 355556526 311728627 332714847

101 rows × 3 columns

sim.history.plot()

png

Without specifying an end time, run will run the simulation until the configuration is silent (all interactions are null). In this case, that will be when the protcol reaches a silent majority consensus configuration.

sim.run()
sim.history.plot()

png

As currently described, this protocol is one-way, where these interactions only take place if the two states meet in the specified order. We can see this by checking print_reactions.

sim.print_reactions()
A, B  -->  U, U      with probability 0.5
A, U  -->  A, A      with probability 0.5
B, U  -->  B, B      with probability 0.5

Here we have unorder pairs of reactants, and the probability 0.5 is because these interactions as written depended on the order of the agents. If we wanted to consider the more sensible symmetric variant of the protocol, one approach would explicitly give all non-null interactions:

approximate_majority_symmetric = {
    (a,b): (u,u), (b,a): (u,u),
    (a,u): (a,a), (u,a): (a,a),
    (b,u): (b,b), (u,b): (b,b)
}
sim = Simulation(init_config, approximate_majority_symmetric)

But a quicker equivalent approach is to tell Simulation that all interactions should be interpreted as symmetric, so if we specify interaction (a,b) but leave (b,a) as null, then (b,a) will be interpreted as having the same output pair.

sim = Simulation(init_config, approximate_majority, transition_order='symmetric')
sim.print_reactions()
sim.run()
sim.history.plot()
A, B  -->  U, U
A, U  -->  A, A
B, U  -->  B, B

png

A key result about this protocol is it converges in expected O(log n) time, which surprisingly is very nontrivial to prove. We can use this package to very quickly gather some convincing data that the convergence really is O(log n) time, with the function time_trials.

from ppsim import time_trials
import numpy as np

ns = [int(n) for n in np.geomspace(10, 10 ** 8, 20)]
def initial_condition(n):
    return {'A': n // 2, 'B': n // 2}
df = time_trials(approximate_majority, ns, initial_condition, num_trials=100, max_wallclock_time = 30, transition_order='symmetric')
df
n time
0 10 14.100000
1 10 9.000000
2 10 7.700000
3 10 14.900000
4 10 7.200000
... ... ...
1359 42813323 48.937840
1360 42813323 50.391446
1361 42813323 56.390054
1362 100000000 50.265050
1363 100000000 53.851442

1364 rows x 2 columns

This dataframe collected time from up to 100 trials for each population size n across a many orders of magnitude, limited by the budget of 30 seconds of wallclock time that we gave it. We can now use the seaborn library to get a convincing plot of the data.

import seaborn as sns
lp = sns.lineplot(x='n', y='time', data=df)
lp.set_xscale('log')

png

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ppsim-0.0.4.tar.gz (218.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ppsim-0.0.4-cp37-cp37m-win_amd64.whl (277.1 kB view details)

Uploaded CPython 3.7mWindows x86-64

File details

Details for the file ppsim-0.0.4.tar.gz.

File metadata

  • Download URL: ppsim-0.0.4.tar.gz
  • Upload date:
  • Size: 218.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.1 importlib_metadata/3.7.3 pkginfo/1.7.0 requests/2.25.1 requests-toolbelt/0.9.1 tqdm/4.59.0 CPython/3.7.3

File hashes

Hashes for ppsim-0.0.4.tar.gz
Algorithm Hash digest
SHA256 e207e46e7703eb2c6257b66fae67f9e4999f007799794e7ea97ae3c9ceee238c
MD5 e4d5362a30bacd9b8907769132acb8ff
BLAKE2b-256 0a83e039b734642b96eff9300d9259bc0dde661ce200dbf1f9fbbab068f1b2fd

See more details on using hashes here.

File details

Details for the file ppsim-0.0.4-cp37-cp37m-win_amd64.whl.

File metadata

  • Download URL: ppsim-0.0.4-cp37-cp37m-win_amd64.whl
  • Upload date:
  • Size: 277.1 kB
  • Tags: CPython 3.7m, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.4.1 importlib_metadata/3.7.3 pkginfo/1.7.0 requests/2.25.1 requests-toolbelt/0.9.1 tqdm/4.59.0 CPython/3.7.3

File hashes

Hashes for ppsim-0.0.4-cp37-cp37m-win_amd64.whl
Algorithm Hash digest
SHA256 1d3ab0bb92087cc0a6eab4c337ff70ff767fec9126cad1b06d927e82eb11c0c2
MD5 756cdfdd60ddfb761398bbdc06e9aeb3
BLAKE2b-256 7506a83c6af5da5ee4ca9c6f3b25782d765e2a08acab81370de165b2d63216ae

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page