pram package

Submodules

pram.data module

Contains data-capturing code.

One purpose of simulating a model is to elucidate the dynamics captured by that model. In the case of PRAMs, an organic example of such dynamics is agent mass dynamics, i.e., the ways in which agent mass moves between groups as a result of the application of rules. PyPRAM’s probes are the facility the user can deploy to capture the interesting aspects of the model’s dynamics. For example, a probe could monitor and persist the sizes of all groups at every step of the simulation or it could only focus on the ones the user has interest in.

class pram.data.Const(name, type, val)

Bases: pram.data.Const

Probe’s constant.

A probe can be in charge of storing multiple constants that relate to the simulation context at large. Naturally, being constants their values will not change, but it may beneficial to have them as database table columns for later data processing and analysis (e.g., forming a UNION of two or more tables with congruent schemas). This class shows how such a constant can be defined.

Parameters
  • name (str) – The constants’s name. If relational database persistence is used, this name will become the name of a table column. While PyPRAM escapes special characters, problematic names should be avoided (e.g., those containing spaces or weird characters).

  • type (str) – The constants’s type. If relational database persistence is used, this needs to be a valid data types of the RDBMS of choice.

  • val (Any) – The variable’s value (must match the type, although in case of database persistence the driver or the RDBMS itself may attempt to cast).

class pram.data.GroupAttrProbe(name, queries, qry_tot=None, var_names=None, consts=None, persistence=None, msg_mode=0, pop=None, memo=None)

Bases: pram.data.GroupProbe

A probe that monitors a PRAM group’s attribute values.

See __init__() for more details.

run(iter, t, traj_id=None)

Runs the probe.

More details in the abstract method.

Parameters
  • iter (int) – The simulation iteration.

  • t (int) – The simulation time.

class pram.data.GroupProbe(name, queries, qry_tot=None, consts=None, persistence=None, msg_mode=<ProbeMsgMode.DISP: 2>, pop=None, memo=None)

Bases: pram.data.Probe, abc.ABC

A probe that monitors any aspect of a PRAM group.

Parameters
  • name (str) – Probe’s name; probes are identified by names.

  • queries (Iterable[GroupQry]) – A GroupQry object selects one of more PRAM groups based on their attributes and relations. For example, GroupQry(attr={ 'flu': 's' }, rel={ Site.AT: Site('home') }) selects all groupsof agents that are susceptible to flu that are at the particular site called home.

  • qry_tot (GroupQry, optional) – Apart from capturing the absolute numbers of agents residing in a group or being moved between groups, a probe also calculates those numbers as proportions; naturally, both of these happen every iteration of the simulation. To calculate proportions, the total agent population mass needs to be known. qry_tot provides that total mass. It can be a GroupQry object that selects groups to have their masses summed to form the total mass (e.g., all agents that have the flu irrespective of where they currently are). Alternatively, if left at the default value of None, the entire population mass will be used as the normalizing factor.

  • consts (Iterable[Const], optional) – Constants (see pram.data.Const class for details).

  • persistence (ProbePersistence, optional) – A ProbePersistence object reference.

  • msg_mode (int) – Probe’s message mode (see ProbeMsgMode enum).

  • pop (GroupPopulation, optional) – The group population in question.

  • memo (str, optional) – Probe’s description.

Note

All classes extending this class must populate the self.vars list before calling the constructor of this class.

Todo

Figure out the relation between the ‘self.persistence’ and registering probes with multiple ProbePersistence objects. At this point it looks like due to the interaction of multiple designs the probe can only be associated with one such objects.

classmethod by_attr(probe_name, attr_name, attr_values, qry_tot=None, var_names=None, consts=None, persistence=None, msg_mode=0, pop=None, memo=None)

Instantiates a probe that queries groups by values of one of its attributes.

This constructor generates QueryGrp objects automatically for the attribute name and values specified. It is a convenience method for probes that only use only a single attribute of PRAM groups and do not use relations.

Parameters
  • probe_name (str) – Probe’s name; probes are identified by names.

  • attr_name (str) – The name of the attribute.

  • attr_values (Iterable[str]) – The values of the attribute to be monitored. Sizes of PRAM groups with different values of the attribute in question will not be monitored.

  • qry_tot (GroupQry, optional) – See __init__()

  • var_names (Iterable[str], optional) – Names which should be assigned to the attribute values. Those names must correspond to attr_values in that every element of attr_values must resolve to two elements in var_names. That is because both the proportion and the absolute number of the agents are recorded by the probe. In case of database persistence, the variable names will be column names. If left None, default names will be used (i.e., p0, p1, … for proportions and m0, m1, … for mass).

  • consts (Iterable[Const], optional) – Constants (see pram.data.Const class for details).

  • persistence (ProbePersistence, optional) – A ProbePersistence object reference.

  • msg_mode (int) – Probe’s message mode (see ProbeMsgMode enum).

  • pop (GroupPopulation, optional) – The group population in question.

  • memo (str, optional) – Probe’s description.

classmethod by_rel(probe_name, rel_name, rel_values, qry_tot=None, var_names=None, consts=None, persistence=None, msg_mode=0, pop=None, memo=None)

Instantiates a probe that queries groups by values of one of its relations.

This constructor generates QueryGrp objects automatically for the relation name and values specified. It is a convenience method for probes that only use only a single relation of PRAM groups and do not use attributes.

Parameters
  • probe_name (str) – Probe’s name; probes are identified by names.

  • rel_name (str) – The name of the relation.

  • rel_values (Iterable[str]) – The values of the relation to be monitored. Sizes of PRAM groups with different values of the relation in question will not be monitored.

  • qry_tot (GroupQry, optional) – See __init__()

  • var_names (Iterable[str], optional) – Names which should be assigned to the relation values. Those names must correspond to rel_values in that every element of rel_values must resolve to two elements in var_names. That is because both the proportion and the absolute number of the agents are recorded by the probe. In case of database persistence, the variable names will be column names. If left None, default names will be used (i.e., p0, p1, … for proportions and m0, m1, … for mass).

  • consts (Iterable[Const], optional) – Constants (see pram.data.Const class for details).

  • persistence (ProbePersistence, optional) – A ProbePersistence object reference.

  • msg_mode (int) – Probe’s message mode (see ProbeMsgMode enum).

  • pop (GroupPopulation, optional) – The group population in question.

  • memo (str, optional) – Probe’s description.

clear_msg()

Clear any cumulated messages.

get_data()

Retrieves data associated with the probe.

For this to work the probe needs to be associated with a ProbePersistence object.

get_msg(do_join=True)

Retrieve all cumulated messages.

Parameters

do_join (bool) – Join the messages with the new-line character?

Returns

The message.

Return type

str

plot(series, fig_fpath=None, figsize=8, 8, legend_loc='upper right', dpi=300)

Plots data associated with a probe.

This method calls plot().

set_consts(consts=None)

Sets the probe’s constants.

Parameters

consts (Iterable[Const], optional) – The constants (see pram.data.Const class for details).

class pram.data.GroupSizeProbe(name, queries, qry_tot=None, var_names=None, consts=None, persistence=None, msg_mode=0, pop=None, memo=None)

Bases: pram.data.GroupProbe

A probe that monitors a PRAM group’s size.

See GroupProbe for more details.

run(iter, t, traj_id=None)

Runs the probe.

More details in the abstract method.

Parameters
  • iter (int) – The simulation iteration.

  • t (int) – The simulation time.

class pram.data.Probe(name, persistence=None, pop=None, traj_id=None, memo=None)

Bases: abc.ABC

Probe base class.

plot(series, ylabel, xlabel='Iteration', figpath=None, figsize=8, 8, legend_loc='upper right', dpi=150, subplot_l=0.08, subplot_r=0.98, subplot_t=0.95, subplot_b=0.25)

Plots data associated with a probe.

This method calls plot().

abstract run(iter, t, traj_id=None)

Runs the probe.

A probe is run by the run() method of the Simulation class as it steps through the simulation. Probes are run as the last order of business before the simulation advances to the next iteration which is congruent with probe capturing the state of the simulation after it has settled at every iteration.

Setting both the ‘iter’ and ‘t’ to ‘None’ will prevent persistence from being invoked and message cumulation to occur. It will still allow printint to stdout however. In fact, this mechanism is used by the Simulation class to print the intial state of the system (as seen by those probes that actually print), that is before the simulation run begins.

Parameters
  • iter (int) – The simulation iteration.

  • t (int) – The simulation time.

set_persistence(persistence)

Associates the probe with a ProbePersistence object.

Parameters

persistence (ProbePersistence) – The ProbePersistence object.

set_pop(pop)

Sets the group population the probe should interact with.

Currently, a PyPRAM simulation operates on a single instance of the GroupPopulation object. This may change in the future and this method will associate the probe with one of the group populations.

Parameters

pop (GroupPopulation) – Group population.

set_traj_id(id)
class pram.data.ProbeMsgMode(value)

Bases: enum.Flag

Probe’s message mode enum.

A probe can be designated to send messages to stdout which is useful for testing and debugging. This class determines how those messages are handled. The three options are:

  • Ignore (do not cumulate nor display any messages)

  • Display (Display messages right away)

  • Cumulate (Store messages in an internal list for future retrieval)

When testing or debugging a simulation with only one probe, the display mode seems most useful (and it is in fact the default). However, the simulation output can quickly become unreasable if multiple probes are sending messages to stdout. The cumulate mode addresses this scenario; messages are stored and can be retrieved at any point with the end of the simulation being one reasonable choice.

Probe messages are a simpler and chronologically older alternative to probe persistence.

CUMUL = 4
DISP = 2
NONE = 1
class pram.data.ProbePersistenceDB(fpath=':memory:', mode=<ProbePersistenceMode.APPEND: 1>, flush_every=16, traj_ens=None, conn=None)

Bases: pram.data.ProbePersistence

Relational database based probe persistence.

At this point, the SQLite3 database is used. More serious RDBMSs will be added later (PostgreSQL being the first of them).

Database inserts are cached and flushed when the buffer fills up. The buffer size is under the user’s control. The default size of 16 decreases the time spent persisting data to the database about 15 times. Higher values can be used to achieve even better results, but memory utilization cost needs to be considered too.

[ Probes are unaware of the kind of persistence (i.e., standalone or trajectory ensemble) they are connected to. ]

Parameters
  • fpath (str) – Path to the database file (':memory:' for in-memory database which is good for testing).

  • mode (int) – Persistence mode (see ProbePersistenceMode enum).

  • flush_every (int) – Memory-to-database flush frequency.

FLUSH_EVERY = 16
clear_probes()
conn_close()

Closes the database connection.

conn_open()

Opens the database connection.

flush()

Flushes all buffered values to the database.

get_data(probe)

Retrieves data associated with a probe from the database.

Parameters

probe (Probe) – The probe.

Returns

A dictionary based on the SQL SELECT query of the probe

persist(probe, vals, iter=None, t=None, traj_id=None)

Dispatch.

Parameters
  • probe (Probe) – The probe.

  • vals (Iterable[Any]) – An iterable with the values to be stored.

  • iter (int) – Simulation iteration (only expected for standalone persistence).

  • t (int) – Simulation time (only expected for standalone persistence).

persist_standalone(probe, vals, iter, t)

Stores values to be persisted and persists them in accordance with the flushing frequency.

Parameters
  • probe (Probe) – The probe.

  • vals (Iterable[Any]) – An iterable with the values to be stored.

  • iter (int) – Simulation iteration.

  • t (int) – Simulation time.

persist_traj_ens(probe, vals)

Persists scheduled items in accordance with the flushing frequency. The value for the ‘iter_id’ field gets added to every item being persisted.

Note

Flushing frequency is currently ignored to make the implementation simpler. Specifically, the flush() method doesn’t need to do anything.

Parameters

iter_id (int) – ID of the iteration from the trajectory ensemble database.

persist_traj_ens_exec__(iter_id)

Persists scheduled items in accordance with the flushing frequency. The value for the ‘iter_id’ field gets added to every item being persisted.

Parameters

iter_id (int) – ID of the iteration from the trajectory ensemble database.

persist_traj_ens_remote(probe, vals, iter, traj_id)

Persists scheduled items in accordance with the flushing frequency. The value for the ‘iter_id’ field gets added to every item being persisted.

Note

Flushing frequency is currently ignored to make the implementation simpler. Specifically, the flush() method doesn’t need to do anything.

Parameters

iter_id (int) – ID of the iteration from the trajectory ensemble database.

persist_traj_ens_schedule__(probe, vals)

Schedules values to be persisted. The trajectory ensemble object which wrapps the present object executes all scheduled persists at an opportune time (when ‘iter_id’ is known). The value for the ‘iter_id’ field gets added at execution time.

Parameters
  • probe (Probe) – The probe.

  • vals (Iterable[Any]) – An iterable with the values to be stored.

plot(probe, series, ylabel='Population mass', xlabel='Iteration', figpath=None, figsize=12, 4, legend_loc='upper right', dpi=150, subplot_l=0.08, subplot_r=0.98, subplot_t=0.95, subplot_b=0.25)

Plots data associated with a probe.

Parameters
  • probe (Probe) – The probe.

  • series (dict) – Series specification (see examples below).

  • ylabel (str) – Label of the Y axis.

  • xlabel (str, optional) – Label of the X axis.

  • figpath (str, optional) – Filepath to save the figure.

  • figsize ((int,int)) – Figure size in (w,h) format.

  • legend_loc (str) – Legend location (e.g., ‘upper right’).

  • dpi (int) – Resolution.

  • subplot_l (float) – Left margin adjustment.

  • subplot_r (float) – Right margin adjustment.

  • subplot_t (float) – Top margin adjustment.

  • subplot_b (float) – Bottom margin adjustment.

Returns

The figure generated.

Return type

matplotlib.figure.Figure

Examples:

p = GroupSizeProbe.by_attr('flu', 'flu', ['s', 'i', 'r'], persistence=ProbePersistenceDB())

# define a simulation

series = [
    { 'var': 'p0', 'lw': 0.75, 'linestyle': '-',  'marker': 'o', 'color': 'red',   'markersize': 0, 'lbl': 'S' },
    { 'var': 'p1', 'lw': 0.75, 'linestyle': '--', 'marker': '+', 'color': 'blue',  'markersize': 0, 'lbl': 'I' },
    { 'var': 'p2', 'lw': 0.75, 'linestyle': ':',  'marker': 'x', 'color': 'green', 'markersize': 0, 'lbl': 'R' }
]
p.plot(series, figsize=(16,3))
plot_line(probe, xvar, yvar, ylabel, xlabel, figpath=None, figsize=6, 6, dpi=150, subplot_l=0.08, subplot_r=0.98, subplot_t=0.95, subplot_b=0.25)

Generates a 2D line plot based on data associated with a probe.

Parameters
  • probe (Probe) – The probe.

  • xvar (str) – Name of X axis variable.

  • yvar (str) – Name of Y axis variable.

  • ylabel (str) – Label of the Y axis.

  • xlabel (str) – Label of the X axis.

  • figpath (str, optional) – Filepath to save the figure.

  • figsize ((int,int)) – Figure size in (w,h) format.

  • dpi (int) – Resolution.

  • subplot_l (float) – Left margin adjustment.

  • subplot_r (float) – Right margin adjustment.

  • subplot_t (float) – Top margin adjustment.

  • subplot_b (float) – Bottom margin adjustment.

Returns

The figure generated.

Return type

matplotlib.figure.Figure

reg_probe(probe, do_overwrite=False)

Dispatcher.

Parameters
  • probe (Probe) – The probe.

  • do_overwrite (bool) – Should an already registered probe with the same name be overwriten?

reg_probe_standalone(probe, do_overwrite=False)

Registers a probe (for standalone persitance).

Parameters
  • probe (Probe) – The probe.

  • do_overwrite (bool) – Should an already registered probe with the same name be overwriten?

Throws:

ValueError

reg_probe_traj_ens(probe)

Registers a probe (for trajectory ensemble persistence).

Parameters
  • probe (Probe) – The probe.

  • do_overwrite (bool) – Should an already registered probe with the same name be overwriten?

Throws:

ValueError

reg_probe_traj_ens_remote(probe)

Registers a probe (for parallelized trajectory ensemble persistence).

Parameters
  • probe (Probe) – The probe.

  • do_overwrite (bool) – Should an already registered probe with the same name be overwriten?

Throws:

ValueError

remote_after(traj_ens, conn)
remote_before(work_collector)
classmethod with_traj(traj_ens, conn)
class pram.data.ProbePersistenceFS(fpath, mode=<ProbePersistenceMode.APPEND: 1>)

Bases: pram.data.ProbePersistence

Filesystem-based probe persistence.

Parameters
  • fpath (str) – Path to the file.

  • mode (int) – Persistence mode (see ProbePersistenceMode enum).

Note

This class is a stub and will be fully implemented when it is needed.

persist()

Stores values to be persisted and persists them in accordance with the flushing frequency set.

reg_probe(probe, do_overwrite=False)

Registers a probe.

Parameters
  • probe (Probe) – The probe.

  • do_overwrite (bool) – Should an already registered probe with the same name be overwriten?

class pram.data.ProbePersistenceMem(mode=<ProbePersistenceMode.APPEND: 1>, flush_every=16)

Bases: pram.data.ProbePersistenceDB

Relational in-memory database based probe persistence.

This class is a very light and elegant specialization of the ProbePersistenceDB class.

Parameters
  • mode (int) – Persistence mode (i.e., append or overwrite; use the ProbePersistenceMode enum type).

  • flush_every (int) – Memory-to-database flush frequency.

class pram.data.ProbePersistenceMode(value)

Bases: enum.IntEnum

Probe persistence mode enum.

A probe can either append new data or overwrite the existing data.

APPEND = 1
OVERWRITE = 2
class pram.data.Var(name, type)

Bases: pram.data.Var

Probe’s variable.

A probe can be in charge of storing multiple variables that relate to the state of the simulation as it evolves. This class shows how such a variable can be defined.

Parameters
  • name (str) – The variable’s name. If relational database persistence is used, this name will become the name of a table column. While PyPRAM escapes special characters, problematic names should be avoided (e.g., those containing spaces or weird characters).

  • type (str) – The variable’s type. If relational database persistence is used, this needs to be a valid data types of the RDBMS of choice.

pram.entity module

Contains PRAM entity code.

The three types of entities which can comprise a PRAM model are groups, sites, and resources.

class pram.entity.Group(name=None, m=0.0, attr={}, rel={}, pop=None, callee=None)

Bases: pram.entity.Entity

A group of agents.

Grouping of functionally equivalent agents is at the heart of the idea behind PRAMs. To that end, a group is the primary type of entity in the framework. Groups are considered identical if they have ideantical attributes and relations (i.e., the keys and values of those dictrionaries must be identical). Consequently, agents belonging to identical groups are considered (by definition) functionally equivalent. It is important to note that only one group with a particular combination of attributes and relations can exist in PRAM.

A Group object can be either standalone or group population bound. All Group objects are created standalone, but when added to a simulation (more specifically, an instance of the GroupPopulation class) it changes its mode. This is to minimize memory utilization by storing Site instances only once in a simulation.

Here is an example of creating and setting up a group in a chain of method calls:

(Simulation().
    add().
        rule(...).                       # add a rule that encodes the dynamics of the simulation
        probe(...).                      # add a probe to display and persist the results
        done().
    new_group(1000).                     # a group of a 1000 agents
        set_attr('income', 'medium').    # with medium income
        set_rel(Site.AT, Site('home')).  # who are all currently located at a site called 'home'
        done().                          # back to the Simulation object
    run(12)
)

In the example above, the Site('home') object will be added to the simulation automatically. Groups can also be created in a regular fashion like so:

(Simulation().
    add([
       ...,  # a rule
       ...,  # a probe
       ...,  # a site
       Group(m=1000, attr={ 'income': 'medium' }, rel={ Site.AT: Site('home') })
    ]).
    run(12)
)
Parameters
  • name (str, optional) – The name of the group. This argument is inconsequential to PyPRAM’s engine operation.

  • m (float) – Population mass. While it is not entirely logical to think about agent mass in terms of fractional numbers, PRAM distributes population mass probabilistically and it doesn’t guarantee intra-group movement of “entire” agents. What it does guarantee, however, is that the total mass being moved adds up to one. In large populations, treating agents as continuous mass rather than individuals is inconsequential.

  • attr (Mapping[str, Any]) – The group’s attributes.

  • rel (Mapping[str, Site]) – The group’s relations.

  • callee (object, optional) – The object invoking the contructor. This argument is used only throughout the process of creating a group. The reference to the invoking object can is returned by Group.done(). See usage examples above.

VOID = {'__void__': True}
__eq__(other)

Compare this group to another.

When comparing groups, only attributes and relations matter; name and size are irrelevant. Note that we need to implement this method regardless, because the one inherited from the ‘object’ class works by object identity only which is largely useless for us.

_has_attr(qry)

Checks if self.attr has keys or key-value pairs specified.

This method compares the dictionary self.attr against qry which can be a mapping, an iterable, and a string. Depending on the type of qry, the method returns True only if (and False otherwise):

  • string: qry must be a key in self.attr

  • iterable: all items in qry must be keys in self.attr

  • mapping: all items in qry must exist in self.attr

Parameters

qry (Union[str, Iterable[str], Mapping[str, Any]]) – The required content that self.attr will be queried against.

Returns

True if (False otherwise):
  • qry is a string and is a key in self.attr

  • qry is an iterable and all items in qry are keys in self.attr

  • qry is a mapping and all items in qry exist in self.attr

Return type

bool

_has_rel(qry)

Checks if self.rel has keys or key-value pairs specified.

This method compares the dictionary self.rel against qry which can be a mapping, an iterable, and a string. Depending on the type of qry, the method returns True only if (and False otherwise):

  • string: qry must be a key in self.rel

  • iterable: all items in qry must be keys in self.rel

  • mapping: all items in qry must exist in self.rel

Parameters

qry (Union[str, Iterable[str], Mapping[str, Any]]) – The required content that self.rel will be queried against.

Returns

True if (False otherwise):
  • qry is a string and is a key in self.rel

  • qry is an iterable and all items in qry are keys in self.rel

  • qry is a mapping and all items in qry exist in self.rel

Return type

bool

apply_rules(pop, rules, iter, t, is_rule_setup=False, is_rule_cleanup=False, is_sim_setup=False)

Applies all the simulation rules to the group.

Applies the list of rules, each of which may split the group into (possibly already extant) subgroups. A sequential rule application scheme is (by the definition of sequentiality) bound to produce order effects which are undesirable. To mitigate that problem, a Cartesian product of all the rule outcomes (i.e., split specifications; GroupSplitSpec class) is computed and the resulting cross-product spit specs are used to do the actual splitting.

When creating the product of split specs created by the individual rules, the probabilities associated with those individual split specs are multiplied because the rules are assumed to be independent. Any dependencies are assumed to have been handles inside the rules themselves.

The two special rule modes this method can be called in are: setup and cleanup. Neither of these modes checks for applicability; that should be performed inside the setup() and cleanup() method of a rule. An additional special mode is that of the simulation group setup (i.e., is_sim_setup = True). In that mode, the ‘rules’ argument is assumed to be a function to be called for the group (and not an iterable of Rule classes as is usual in normal operation).

Parameters
  • pop (GroupPopulation) – The group population.

  • rules (Iterable[Rule]) – Rules to be applied. Only rules compatible with the group will actually be applied as determined by Rule.is_applicable().

  • iter (int) – Simulation iterations.

  • t (int) – Simulation time.

  • is_rule_setup (bool) – Is this invocation of this method during rule setup stage of the simulation?

  • is_rule_cleanup (bool) – Is this invocation of this method during rule cleanup stage of the simulation?

  • is_sim_setup (bool) – Is this invocation of this method during simulation setup stage?

Todo

Think if the dependencies between rules could (or perhaps even should) be read from some sort of a graph. Perhaps then multiplying the probabilities would not be appropriate.

attr
attr_enc
attr_used = None
callee
copy(is_deep=False)

Generates the group’s hash.

Returns a shallow or deep copy of self.

Parameters

is_deep (bool) – Perform deep copy?

Returns

A copy of self.

Return type

object (Group)

done()

Ends creating the group by notifing the callee that has begun the group creation.

See Simulation.new_group() for explanation of the mechanism.

Returns

Reference to the object that initiated the group creation (can be None).

Return type

Simulation

ga(name=None)

See get_attr().

static gen_dict(d_in, d_upd=None, k_del=None)

Generates a group’s attributes or relations dictionary.

This method is used to create new dictionaries based on existing ones and given changes to those existing ones. Specifically, a new dictionary is based on the ‘d_in’ dictionary with values updated based on the ‘d_upd’ dictionary and keys deleted based on the ‘k_del’ iterable.

Parameters
  • d_in (Mapping[str, Any]) – Original mapping.

  • d_upd (Mapping[str, Any], optional) – Key-values to be set on the original mapping.

  • k_del (Iterable[str], optional) – An iterable of keys to be removed from the original mapping.

Returns

A shallow copy of the updated original mapping.

Return type

Mapping

Notes

A shallow copy of the dictionary is returned at this point. That is to avoid creating unnecessary copies of entities that might be stored as relations. A more adaptive mechanism can be implemented later if needed.

classmethod gen_from_db(db, schema, tbl, attr_db=[], rel_db=[], attr_fix={}, rel_fix={}, attr_rm=[], rel_rm=[], rel_at=None, limit=0, fn_live_info=None)

Generate groups from a relational database.

In this method, lists are sometimes converted to allow for set operations (e.g., union or difference) and the results of those operations are converted back to lists for nice output printout (e.g., ‘[]’ is more succinct than ‘set()’, which is what an empty set is printed out as).

This is a central method for generating complete group populations from relational databases in that it automatically calls Site.gen_from_db() when necessary.

For usage example, see SimulationDBI.gen_groups() and Simulation.gen_groups_from_db(); both methods invoke the current method internally.

Parameters
  • db (DB) – Database management system specific object.

  • schema (str) – Database schema.

  • tbl (str) – Table name.

  • attr_db (Iterable[str]) – Group attributes to be retrieved from the database (if extant).

  • rel_db (Iterable[GroupDBRelSpec]) – Group relation to be retrieved from the database (if extant).

  • attr_fix (Mappint[str, Any]) – Group attributes to be fixed for every group.

  • rel_fix (Mapping[str, Site]) – Group relations to be fixed for every group.

  • attr_rm (Iterable[str]) – Group attributes to NOT be retrieved from the database (overwrites all).

  • rel_rm (Iterable[str]) – Group relation to NOT be retrieved from the database (overwrites all).

  • rel_at (Site, optional) – A site to be set as every group’s current location.

  • limit (int) – The maximum number of groups to be generated. Ordinarily, this is not changed from its default value of zero. It is however useful for testing, especially with very large databases.

  • fn_live_info (Callable, optional) – A callable expecting a single string argument for real-time printing.

Returns

A list of groups generated.

Return type

list (Group)

static gen_hash(attr={}, rel={})

Generates the group’s hash.

Generates a hash for the attributes and relations dictionaries. A hash over those two dictionaries is needed because groups are judged functionally equivalent based on the content of those two dictionaries alone.

The following non-cryptographic hashing algorithms have been tested:

  • hash()

  • hashlib.sha1()

  • xxhash.xxh32()

  • xxhash.xxh64()

As is evident from the source code, each of the algorithms required a slightly different treatment of the attribute and relation dictionaries. All these options are legitimate and they don’t differ much in terms of speed. They do howeve differ in terms of reproducability. Namely, the results of the built-in hash() function cannot be compared between-runs while the other ones can. This behavior of the hash() function is to prevent attackers from reusing hashes and it can be disabled by setting ‘PYTHONHASHSEED=0’.

An advanced user can uncomment the desired method to experiment with it.

Parameters
  • attr (Mapping[str, Any]) – Group’s attributes.

  • rel (Mapping[str, Site or int hash]) – Group’s relations (i.e., site objects or their hashes).

Returns

A hash of the attributes and relations specified.

Return type

int

get_attr(name)

Retrieves an attribute’s value.

Parameters

name (str) – Attribute’s name.

Returns

Attribute’s value.

Return type

Any

get_attrs()

Retrieves the group’s attributes.

Returns

Mapping[str, Any].

get_hash()

Get the group’s hash.

Groups are hashed on their attributes and relations, both being dictionaries.

Calling this method should be the only way to get the group’s hash. Wanna do it otherwise? Get ready for a world of hurt.

get_mass()
get_rel(name)

Retrieves a relation’s value.

Parameters

name (str) – Relation’s name.

Returns

Relation’s value.

Return type

Any

get_rels()

Retrieves the group’s relations.

Returns

Mapping[str, Site].

get_site_at()

Get the site the group is currently located at.

Returns

Site

gr(name)

See get_rel().

ha(qry)

See has_attr().

has_attr(qry)

Checks if the group has the specified attributes.

See _has() for details on what qry can be and the specifics of the check.

Returns

bool

has_rel(qry)

Checks if the group has the specified relations.

See _has() for details on what qry can be and the specifics of the check.

Returns

bool

has_sites(sites)

Checks if the groups has the sites specified.

Parameters

sites (Iterable[Site]) – Sites the existence of which should be checked for.

Returns

bool

hash
hr(qry)

See has_rel().

is_at_site(site)

Is the groups currently at the site specified?

is_at_site_name(name)

Is the groups currently at the site with the name specified (that the group has as a relation)?

is_enc
is_void()

Checks if the group is a VOID group (i.e., it should be removed from the simulation).

Returns

True for VOID group; False otherwise.

Return type

bool

Links the group to the site it currently resides at.

Returns

self

m
matches_qry(qry)

Checks if the group matches the group query specified.

Parameters

qry (GroupQry) – The query. A group automatially matches a None qry.

Returns

True if the group matches the query; False otherwise.

Return type

bool

matches_qry_full_cond0(qry)
matches_qry_full_cond1(qry)
matches_qry_part_cond0(qry)
matches_qry_part_cond1(qry)
name
pop
rel
rel_enc
rel_used = None
set_attr(name, value, do_force=False)

Sets a group’s attribute.

Parameters
  • name (str) – Attribute’s name.

  • value (Any) – Attribute’s value.

  • do_force (bool) – Force despite the group being frozen? Don’t set to True unless you like pain.

Raises

GroupFrozenError

Returns

self

set_attrs(attrs, do_force=False)

Sets multiple group’s attributes.

This method is not implemented yet.

Parameters
  • attr (Mapping[str, Any]) – Attributes.

  • do_force (bool) – Force despite the group being frozen? Don’t set to True unless you like pain.

Raises

GroupFrozenError

Returns

self

set_rel(name, value, do_force=False)

Sets a group’s relation.

Parameters
  • name (str) – Relation’s name.

  • value (Any) – Relation’s value.

  • do_force (bool) – Force despite the group being frozen? Don’t set to True unless you like pain.

Raises

GroupFrozenError

Returns

self

set_rels(rels, do_force=False)

Sets multiple group’s relation.

This method is not implemented yet.

Parameters
  • rels (Mapping[str, Entity]) – Relations.

  • do_force (bool) – Force despite the group being frozen? Don’t set to True unless you like pain.

Raises

GroupFrozenError

Returns

self

split(specs)

Splits the group into new groups according to the split specs.

The probabilities defining the population mass distribution among the new groups need to add up to 1. Complementing of the last one of those probabilities is done automatically (i.e., it does not need to be provided and is in fact outright ignored).

A note on performance. The biggest performance hit is likley going to be generating a hash which happens as part of instantiating a new Group object. While this may seem like a good reason to avoid crearing new groups, that line of reasoning is deceptive in that a group’s hash is needed regardless. Other than that, a group object is light so its impact on performance should be negligible. Furthermore, this also grants access to full functionality of the Group class to any function that uses the result of the present method.

Parameters

specs (Iterable[GroupSplitSpec]) – Group split specs.

class pram.entity.GroupDBRelSpec

Bases: object

Specification for group relation to be retrieved from a relational database.

Parameters
  • name (str) – Table name.

  • col (str) – Column name.

  • fk_schema (str) – Schema of the foreign key table.

  • fk_tbl (str) – Foreign key table.

  • sites (Mapping[str, Site], optional) –

exception pram.entity.GroupFrozenError

Bases: Exception

Raised when an attempt at modifying a frozen group is made.

Once instantiated, PRAM groups can only be subject to arbitraty modifications when they are not part of a PRAM simulation. That is to prevent the user from inadvertantly interfering with the group splitting mechanics of PRAM. That mechanics dictates that group masses, attributes, and relations (i.e., the very definition of PRAM groups) are never changed; instead, a group at iteration n is split into multiple groups and all new groups that result from all group splittings are combined to form new groups at iteration n+1.

class pram.entity.GroupQry(attr={}, rel={}, cond=[], full=False)

Bases: object

A group query.

Objects of this class are used to select groups from a group population using attribute- and relation-based search criteria.

Typical usage example for selecting groups of agents that meet certain criteria:

GroupQry(attr={ 'flu': 's' })                 # susceptible to the flu
GroupQry(rel={ Site.AT: Site('school-83') })  # currently located at site 'school-83'

GroupQry(cond=[lambda g: g.get_attr('x') > 100]))                                   # with attribute 'x' > 100
GroupQry(cond=[lambda g: g.get_attr('x') > 100, lambda g: get_attr('y') == 200]))   # with attribute 'x' > 100 and 'y' == 200
GroupQry(cond=[lambda g: g.get_attr('x') > 100 and g.get_attr('y') ==  200]))       # explicit AND condition between attributes
GroupQry(cond=[lambda g: g.get_attr('x') > 100 or  g.get_attr('y') == -200]))       # explicit OR  condition between attributes

Group query objects do not have any utility outside of a simulation context (which implies population bound groups) and consequently won’t play well with standalong groups because all Site references are turned into their hashes (which is what a GroupPopulation object operates on internally).

Parameters
  • attr (Mapping[str, Any]) – Group’s attributes.

  • rel (Mapping[str, Any]) – Group’s relations.

  • cond (Iterable(Callable)) – Conditions on group’s attributes and relations. These conditions are given as callables which take one argument, the group. Assuming the group argument is g, the callables can then access the group’s attributes and relations respectively as g.attr and g.rel. See the typical usage examples above.

  • full (bool) – Does the match need to be full? To satisfy a full match, a group’s attributes and relations need to fully match the query. Because PRAM cannot have two groups with the same attributes and relations, it follows that a full match can either return one group on no groups (if no match exists). A partial match requires that a group’s attributes _contain_ the query’s attributes (and same for relations).

attr
attr_enc
cond
full
static gen_hash(attr={}, rel={}, cond=[], full=False)
hash
is_enc
rel
rel_enc
class pram.entity.GroupSplitSpec

Bases: object

A single group-split specification.

These specifications are oridinarily provided in a list to indicate new groups that one other group is being split into at the end of a rule’s application.

Parameters
  • p (float) – The probability of the agents mass being trasnferred to the new group.

  • attr_set (Mapping[str, Any]) – Attributes to be set in the new group.

  • attr_del (Iterable(str)) – Attributes to be removed from the new group (with respect to the current group).

  • rel_set (Mapping[str, Any]) – Relations to be set in the new group.

  • rel_del (Iterable(str)) – Relations to be removed from the new group (with respect to the current group).

Todo

At this point, attributes and relations to be removed are assumed to be identified by their names only and not not their values (i.e., we use a set to hold the keys that should be removed from the dictionaries for attributes and relations). Perhaps this is not the way to go and we should instead be using both names and values.

is_prob(attribute, value)
class pram.entity.Resource(name, capacity_max=1, pop=None)

Bases: pram.entity.Entity, abc.ABC

A resource entity.

A resource is shared by multiple agents (e.g., a public bus).

This is a basic implementation of a shared resource and can safely be used only within a single simulation. A more elaborate implementation based on synchronization mechanisms will be provided later and will accommodate multiple concurrent simulations of different and interacting systems with the agent population moving seamlessly between them.

The terminology used in the API of this class is consistent with that of concurent computing. For example, a resource is said to accommodate agents and is released after an agent (or agents) are done using it. A resource’s capacity dicates how many agents can be accommodated at the same time.

Parameters
  • name (str, optional) – A resource’s name.

  • capacity_max (int) – The maximum number of agents that can be using the resouce concurrently.

__eq__(other)

Checks equality of two objects.

We will make two resources identical if their keys are equal (i.e., object identity is not necessary). This will let us recognize resources even if they are instantiated multiple times.

allocate(n, do_all=False)

Allocate the resource to n agents.

Parameters
  • n (int) – The number of agents.

  • do_all (bool) – Accomodate all-or-nothing or any that the resourcs can accomodate.

Returns

Number of not accomodated agents (i.e., those over the resource’s max capacity).

Return type

int

allocate_all(n)

Attempts to allocate all n agents.

Parameters

n (int) – The number of agents.

Returns

True if all agents can be accommodated and False otherwise.

Return type

bool

allocate_any(n)

Allocates as many out of n agents as possible.

Parameters

n (int) – The number of agents.

Returns

Number of not accommodated agents (i.e., those over the resource’s max capacity).

Return type

int

can_accommodate_all(n)

Checks if all n agents be accomodated.

Parameters

n (int) – The number of agents.

Returns

True if all n agents can be accomodated and False otherwise.

Return type

bool

can_accommodate_any(n)

Checks if at least one agent can be accomodated.

Parameters

n (int) – The number of agents.

Returns

True if at least one agent can be accomodated and False otherwise.

Return type

bool

can_accommodate_one()

Checks if at least one agent can be accomodated.

Returns

True if at least one agent can be accomodated and False otherwise.

Return type

bool

capacity
capacity_max
get_capacity()
get_capacity_left()
get_capacity_max()
get_hash()
name
release(n)

Releases n agent spots.

Because releasing is always allowed, no return value needs to be checked. Naturally, a resource cannot release more spots than it’s max capacity.

Parameters

n (int) – The number of agents.

toJson()
class pram.entity.Site(name, attr=None, rel_name='@', pop=None, capacity_max=1)

Bases: pram.entity.Resource

A physical site (e.g., a school or a store) agents can reside at.

A site has a sensible interface which makes it useful. For example, it makes sense to ask about the size and composition of population (e.g., groups) that are at that location. However, because this information (and other, similar pieces of information) may be desired at arbitrary times, it makes most sense to compute it lazily and memoize it. For that reason, a site stores a link to the population it is associated with; it queries that population to compute quantities of interested when they are needed. An added benefit of this design is fostering proper composition; that is, updating the state of a site should be done by a site, not the population.

A Site is a Resource which means a Site may choose to utilize the capacity property with all its related methods. A good example of when this would be useful is a hospital with a limited patient capacity that may be reached during an epidemic outbreak.

Parameters
  • name (str) – Name of the site.

  • attr (Mapping[], optinoal) – Attributes describing the site.

  • rel_name (str) – The name of the relation that should be used when associating a group of agents with this site.

  • pop (GroupPopulation, optional) – The GroupPopulation object.

  • capacity_max (int) – The maximum capacity of the Site when considered a Resource.

AT = '@'

Adds a link to a group. This is to speed up lookup from sites to groups.

Parameters

group (Group) – The group.

Returns

self

attr
ga(name)

See get_attr().

classmethod gen_from_db(db, schema, tbl, name_col, rel_name='@', attr=[], limit=0)

Generates sites from a relational database.

Parameters
  • db (DB) – Database management system specific object.

  • schema (str) – Schema name.

  • tbl (str) – Table name.

  • name_col (str) – Table column storing names of sites.

  • rel_name (str) – Name of the relation to be associated with each of the sites generated. For example, if hospital sites are being generated, the rel_name could be set to hospital.

  • attr (Iterable[str]) – Names of table columns storing attributes to be internalized by the site objects being generated.

  • limit (int) – The maximum number of sites to be generated. Ordinarily, this is not changed from its default value of zero. It is however useful for testing, especially with very large databases.

Returns

A dictonary of sites with the Site object’s database IDs as keys. Previously, Site

hashes were used as keys, but a recent change in the internal design did away with that.

Return type

Mapping[str, Site]

static gen_hash(name, rel_name, attr={})
get_attr(name)

Retrieves value of the designated attribute.

Parameters

name (str) – The attribute.

Returns

Any

get_groups(qry=None, non_empty_only=False)

Returns groups which currently are at this site.

The word “currently” is key here because as a PRAM simulation evolved, agents move between groups and different compositions of groups will in general reside at any given site.

Parameters
  • qry (GroupQry, optional) – Further restrictions imposed on attributes and relations of groups currently at this site. For example, the user may be interested in retrieving only groups of agents infected with the flu (which is a restriction on the group’s attribute) or only groups of agents who attend a specific school (which is a restriction on the group’s relation).

  • non_empty_only (bool) – Return only groups with non-zero agent population mass?

Returns

List of groups currently at this site.

Return type

list[Group]

Todo

Implement memoization (probably of only all the groups, i.e., without accounting for the qry).

get_mass(qry=None)

Get the mass of groups that match the query specified. Only groups currently residing at the site are searched.

Parameters

qry (GroupQry, optional) – Group condition.

Returns

Mass

Return type

float

get_mass_and_prop(qry=None)

Get the total mass and its proportion that corresponds to the groups that match the query specified. Only groups currently residing at the site are searched.

Parameters

qry (GroupQry, optional) – Group condition.

Returns

(Mass, Mass proportion)

Return type

tuple(float, float)

get_mass_prop(qry=None)

Get the proportion of the total mass accounted for the groups that match the query specified. Only groups currently residing at the site are searched.

Parameters

qry (GroupQry, optional) – Group condition.

Returns

Mass proportion

Return type

float

groups
hash
m
name
rel_name

Resets the groups located at the site and other cache and memoization data structures.

Returns

self

pram.graph module

Contains graph related code.

class pram.graph.MassGraph

Bases: object

A graph of locus and flow of mass.

This class holds the entire time-evolution of the group space and the associated mass flow.

This class uses graph-tool library. I’ve also considered using the Python-native NetworkX, but graph-tool is faster, more featurefull, and performance-transparent (i.e., all operations are annotated with the big O notation). The only problem with graph-tool is that it is more difficult to install, which is going to be signifiant for users, especially the casual ones who just want to get feel for the software. This makes a conteinerized version desirable.

add_group(iter, hash, m, m_p)
add_mass_flow(iter, hash_src, hash_dst, m, m_p)
plot_mass_flow_time_series(scale=1.0, 1.0, filepath=None, iter_range=- 1, - 1, v_prop=False, e_prop=False)

Because this method plots a time series which can be of arbitrary length, there is no figure size argument. Instead, scale factor for the width and height of the figure is expected and defaults to no scaling. The method decides on the figure size automatically based on the iteration range given and the maximum number of groups in any iteration from that range.

set_group_names(names)
set_pos(iter_range)

Sets the position of every vertex. That position is used for plotting the graph.

pram.pop module

Contains PRAM group and agent populations code.

class pram.pop.GroupPopulation(sim, hist_len=0, do_keep_mass_flow_specs=False)

Bases: object

Population of groups of agents.

PRAM models functionally equivalent agents jointly as groups. The formalism does not invoke any “hard” notion of a group population. However, the PyPRAM package does use that concept to elegantly compartmentalize groups along with operations on them.

Because groups can be associated with sites via group relations, those sites are also stored inside of this class’ instance.

VITA groups, or groups that are the source of new population mass are stored separately from the actual group population. At the end of every iteration, masses of all VITA groups are transferred back to the population. It is also at that time that all VOID groups are removed. VOID groups contain mass that should be removed from the simulation.

Parameters
  • sim (Simulation) – The simulation.

  • do_keep_mass_flow_specs (bool, optional) – Store the last iteration mass flow specs? This is False by default for memory usage sake. If set to True, self.last_iter.mass_flow_specs will hold the specs until they are overwriten at the next iteration of the simulation.

add_group(group)

Adds a group to the population.

If the groups doesn’t exist in the population, it will be added. Otherwise, the group’s size will be added to the already existing group’s size. This behavior ensures the group population only contains exactly one instance of a group. As a reminder, groups are identical if their attributes and relations are equal.

This method also adds all Site objects from the group’s relations so there is no need for the user to do this manually.

All groups added to the population become frozen to prevent the user from changing their attribute and relations via their API; modifying groups via group splitting mechamism is the only proper way.

Parameters

group (Group) – The group being added.

Returns

self

add_groups(groups)

Adds multiple groups to the population.

See add_group() method for details.

Parameters

groups (Iterable[Group]) – Groups to be added.

Returns

self

add_resource(resource)

Adds a resource to the population.

Only adds if the resource doesn’t exist yet.

Parameters

resource (Resource) – The resource to be added.

Returns

self

add_resources(resources)

Adds multiple resources to the population.

See add_resource() method for details.

Parameters

resource (Resource) – The resource to be added.

Returns

self

add_site(site)

Adds a site to the population if it doesn’t exist.

Parameters

site (Site) – The site to be added.

Returns

self

add_sites(sites)

Adds multiple sites to the population.

See add_site() method for details.

Parameters

sites (Site) – The sites to be added.

Returns

self

add_vita_group(group)

Adds a VITA group.

If a VITA group with the same hash already exists, the masses are combined (i.e., no VITA group duplication occurs, much like is the case with regular groups).

Parameters

group (Group) – The group being added.

Returns

self

apply_rules(rules, iter, t, is_rule_setup=False, is_rule_cleanup=False, is_sim_setup=False)

Applies all rules in the simulation to all groups in the population.

This method iterates through groups and for each applies all rules (that step is handled by the Group class itself in the apply_rules() method). The result of those rules applications is a list of new groups the original group should be split into. When all the groups have been processed in this way, and consequently all resulting groups have been defined, those resulting groups are used for mass transfer (which updates existing groups and creates new ones). Note that “resulting” is different from “new” because a group might have been split into resulting groups of which one or more already exists in the group population. In other words, not all resulting groups (local scope) need to be new (global scope).

Parameters
  • rules (Iterable[Rule]) – The rules.

  • iter (int) – Simulation interation.

  • t (int) – Simulation time.

  • is_rule_setup (bool) – Is this invocation of this method during rule setup stage of the simulation?

  • is_rule_cleanup (bool) – Is this invocation of this method during rule cleanup stage of the simulation?

  • is_sim_setup (bool) – Is this invocation of this method during simulation setup stage?

Returns

self

Todo

Optimize by using hashes if groups already exist and Group objects if they don’t.

archive()
compact()

Compacts the population by removing empty groups.

Whether this is what the user needs is up to them. However, for large simulations with a high new group turnover compacting the group population will make the simulation run faster. Autocompacting can be turned on on the simulation level via the autocompact pragma (e.g., via set_pragma_autocompact() method).

Returns

self

do_post_iter()

Performs all post-iteration routines (i.e., current iter cleanup and next iter prep).

Routines performed:

  1. Remove VOID groups.

  2. Move mass from VITA groups to their corresponding groups.

Returns

self

freeze()

Freeze the population.

The Simulation object freezes the population on first run. Freezing a population is used only used to determine the total population size.

Returns

self

gen_agent_pop()

Generates a population of agents based on the current groups population.

Todo

Implement.

Returns

AgentPopulation

get_group(attr, rel={})

Returns the group with the all attributes and relations as specified; or None if such a group does not exist.

Parameters
  • attr (Mapping[str, Any]) – Group’s attributes.

  • rel (Mapping[str, Site], optional) – Group’s relations.

Returns

Group if a group is found; None otherwise

get_group_cnt(only_non_empty=False)

Get number of groups.

Parameters

only_non_empty (bool, optional) – Count only non-empty group?

Returns

int

get_groups(qry=None)

Get groups that match the group query specified, or all groups if no query is specified.

This method should only be used for population-wide queries. The Site.get_groups() pram.entity.Site.get_groups() should be used instead for querying groups located at a Site.

Parameters

qry (GroupQry, optional) – The group query.

Returns

List of groups (can be empty)

Return type

[Group]

get_groups_mass(qry=None, hist_delta=0)

Get the mass of groups that match the query specified.

This method should only be used for population-wide queries. The Site.get_groups_mass() pram.entity.Site.get_groups_mass() should be used instead for querying groups located at a Site.

Parameters
  • qry (GroupQry, optional) – Group condition.

  • hist_delta (int, optional) – Number of steps back in the history to base the delta off of. For instance, a value of 2 will yield the change of mass compared to two iterations back. The group’s history must be long enough (controlled by hist_len attribute).

Returns

Mass

Return type

float

Raises

ValueError

get_groups_mass_and_prop(qry=None)

Get the total mass and its proportion that corresponds to the groups that match the query specified.

This method should only be used for population-wide queries. The Site.get_groups_mass_prop() pram.entity.Site.get_groups_mass_prop() should be used instead for querying groups located at a Site.

Parameters

qry (GroupQry, optional) – Group condition.

Returns

(Mass, Mass proportion)

Return type

tuple(float, float)

get_groups_mass_prop(qry=None)

Get the proportion of the total mass accounted for the groups that match the query specified.

This method should only be used for population-wide queries. The Site.get_groups_prop() pram.entity.Site.get_groups_prop() should be used instead for querying groups located at a Site.

Parameters

qry (GroupQry, optional) – Group condition.

Returns

Mass proportion

Return type

float

get_mass()
get_next_group_name()

Get the next group name.

To be used by sequential group adding if naming groups is desired.

Returns

str

get_site_cnt()

Get number of sites.

Returns

int

transfer_mass(src_group_hashes, mass_flow_specs, iter, t, is_sim_setup)

Transfers population mass.

Transfers the mass as described by the list of “destination” groups. “Source” groups (i.e., those that participate in mass transfer) have their masses reset before the most-transfer mass is tallied up.

Because this method is called only once per simulation iteration, it is a good place to put simulation- wide computations that should happen after the iteration-specific computations have concluded.

Returns

self

class pram.pop.GroupPopulationHistory(pop)

Bases: object

History of the GroupPopulation object’s states.

For efficiency, this class operates on a group’s hash (i.e., a integer) and a group’s mass (i.e., a float) and does not store any actual Group objects. GroupPopulation object’s groups dict is necessary for recovery of full group definition.

Parameters

pop (GroupPopulation) – Group population to be archived.

get_group_m(group_hash, ret_if_not_found=0.0)
class pram.pop.MassFlowSpec

Bases: object

A specification of agent population mass flow.

A list of objects of this class for one simulation iteration encodes the full picture of agent population mass flow in the model. This class encodes mass flow from one source group to one or more destination groups.

Parameters
  • m_pop (float) – Total population mass at the time of mass flow.

  • src (Group) – The source group (i.e., the mass donor).

  • dst (Iterable[Group]) – Destination groups (i.e., mass acceptors).

pram.rule module

Contains rule code.

class pram.rule.Action(name='rule', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.Rule, abc.ABC

A physical action.

Wikipedia: Action (physics)

class pram.rule.BernoulliProcess(p=0.5, attr='state', vals=0, 1, name='bernoulli-process', t=attr.attrs, i=attr.attrs, memo=None)

Bases: pram.rule.BernoulliScheme

A Bernoulli process is a sequence of independent trials in which each trial results in a success or failure with respective probabilities $p$ and $q=1−p$.

A Bernoulli scheme with only two possible states is known as a Bernoulli process.

Binomial Markov Chain.

Parameters
  • name (str) – Name.

  • t (Time, int, tuple[int,int], set[int]) – Compatible time selector.

  • i (Iter, int, tuple[int,int], set[int]) – Compatible iteration selector.

  • group_qry (GroupQry, optional) – Compatible group selector.

  • memo (str, optional) – Description.

class pram.rule.BernoulliScheme(attr='state', vals=0, 1, name='bernoulli-process', t=attr.attrs, i=attr.attrs, memo=None)

Bases: pram.rule.DiscreteInvMarkovChain

Bernoulli scheme or Bernoulli shift is a generalization of the Bernoulli process to more than two possible outcomes.

A Bernoulli scheme is a special case of a Markov chain where the transition probability matrix has identical rows, which means that the next state is even independent of the current state (in addition to being independent of the past states).

Parameters
  • name (str) – Name.

  • t (Time, int, tuple[int,int], set[int]) – Compatible time selector.

  • i (Iter, int, tuple[int,int], set[int]) – Compatible iteration selector.

  • group_qry (GroupQry, optional) – Compatible group selector.

  • memo (str, optional) – Description.

class pram.rule.BirthDeathProcess(ig, name='birth-death-process', t=attr.attrs)

Bases: pram.rule.MarkovProcess

Birth death process.

A special case of continuous-time Markov process where the state transitions are of only two types: “births”, which increase the state variable by one and “deaths”, which decrease the state by one.

A homogeneous Poisson process is a pure birth process.

The following infinitesimal generator of the process (lambda are birth rates and mu are death rates):

| -l_0           l_0             0             0    0  ... |
|  m_1  -(l_1 + m_1)           l_1             0    0  ... |
|    0           m_2  -(l_2 + m_2)           l_2    0  ... |
|    0             0           m_3  -(l_3 + m_3)  l_3  ... |
|    .             .             .             .    .  ... |
|    .             .             .             .    .  ... |

should be provided as:

[l_0, [l_1, m_1], [l_2, m_2], [l_3, m_3], ..., m_n]

Sojourn times have exponential p.d.f. \(\lambda e^{-\lambda t}\).

class pram.rule.CellularAutomaton(name='rule', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.StochasticProcess

Cellular automaton.

Cellular automata are a discrete-time dynamical system of interacting entities, whose state is discrete.

class pram.rule.ChaoticMap(name='rule', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.Rule, abc.ABC

The simplest dynamical system that has relevant features of chaotic Hamiltonian systems.

Wikipedia: List of chaotic maps

class pram.rule.CompoundInterstSeq(attr, r, n, name='compund-interst-seq', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.Sequence, pram.rule.DifferenceEquation

Applies the comound interest formula to the designated attribute.

The sequence state is store in the rule object and not the group attribute space. Consequently, one instance of the rule should associated with only one group.

Parameters
  • attr (str) – Attribute name to store the value in.

  • r (float) – Nominal annual interest rate.

  • n (int) – Compund frequency in months.

  • name (str) – Name.

  • t (Time, int, tuple[int,int], set[int]) – Time selector.

  • i (Iter, int, tuple[int,int], set[int]) – Iteration selector.

  • group_qry (GroupQry, optional) – Compatible group selector.

  • memo (str, optional) – Description.

apply(pop, group, iter, t)

See pram.rule.Rule.apply.

class pram.rule.ContinuousSpaceDiscreteTimeStochasticProcess(name='rule', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.StochasticProcess, abc.ABC

class pram.rule.ContinuousSpacetimeStochasticProcess(name='rule', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.StochasticProcess, abc.ABC

class pram.rule.Control(name='rule', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.Rule, abc.ABC

class pram.rule.CotinuousMarkovChain(name='rule', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.MarkovChain, pram.rule.DiscreteSpaceContinuousTimeStochasticProcess

Continuous-time Markov chain with finite state space.

class pram.rule.CoxProcess(name='rule', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.PoissonProcess

Cox process.

A point process which is a generalization of a Poisson process where the time-dependent intensity is itself a stochastic process.

Also known as a doubly stochastic Poisson process.

class pram.rule.DifferenceEquation(name='rule', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.Equation, abc.ABC

class pram.rule.DiffusionProcess(name='rule', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.MarkovProcess

A continuous-time Markov process with almost surely continuous sample paths.

A solution to a stochastic differential equation (in short form),

d X_t = mu(X_t, t)dt + sigma X_t(X_t, t)dB_t,

where $B$ is a standard Brownian motion.

class pram.rule.Directive

Bases: abc.ABC

class pram.rule.DiscreteInvMarkovChain(attr, tm, name='markov-chain', t=attr.attrs, i=attr.attrs, memo=None, cb_before_apply=None)

Bases: pram.rule.MarkovChain, pram.rule.DiscreteSpacetimeStochasticProcess, pram.rule.StationaryProcess

Discrete-time time-homogenous Markov chain with finite state space.

The following sample transition model for the variables named X:

           x_1^t   x_2^t
x_1^{t+1}    0.1     0.3
x_2^{t+1}    0.9     0.7

should be specified as the following list of stochastic vectors:

{ 'x1': [0.1, 0.9], 'x2': [0.3, 0.7] }

Definition:

A stochastic process $X = {X_n:n geq 0}$ on a countable set $S$ is a Markov Chain if, for any $i,j in S$ and $n geq 0$,

P(X_{n+1} = j | X_0, ldots, X_n) = P(X_{n+1} = j | X_n) P(X_{n+1} = j | X_n = i) = p_{ij}

The $p_{ij} is the probability that the Markov chain jumps from state $i$ to state $j$. These transition probabilities satisfy $sum_{j in S} p_{ij} = 1, i in S$, and the matrix $P=(pij)$ is the transition matrix of the chain.

Rule notation A:

code:
    DiscreteInvMarkovChain('flu', { 's': [0.95, 0.05, 0.00], 'i': [0.00, 0.80, 0.10], 'r': [0.10, 0.00, 0.90] })

init:
    tm = {
        s: [0.95, 0.05, 0.00],
        i: [0.00, 0.80, 0.20],
        r: [0.10, 0.00, 0.90]
    }  # right stochastic matrix

is-applicable:
    has-attr: flu

apply:
    curr_state = group.attr.flu
    new_state_sv = tm[]  # stochastic vector
    move-mass:
        new_state_sv[0] -> A:flu = 's'
        new_state_sv[1] -> A:flu = 'i'
        new_state_sv[2] -> A:flu = 'r'

Rule notation B:

tm_i = tm[group.attr.flu]
tm_i[0] -> A:flu = 's'
tm_i[1] -> A:flu = 'i'
tm_i[2] -> A:flu = 'r'
Parameters
  • attr (str) – Name of state attribute.

  • tm (Mapping[str,Iterable[float]]) – Transition matrix. Keys correspond to state names and values to lists of transition probabilities.

  • name (str) – Name.

  • t (Time, int, tuple[int,int], set[int]) – Compatible time selector.

  • i (Iter, int, tuple[int,int], set[int]) – Compatible iteration selector.

  • group_qry (GroupQry, optional) – Compatible group selector.

  • memo (str, optional) – Description.

  • cb_before_apply (Callable, optional) – Function called before the group is split. The signature is fn(group, attr_val, tm).

apply(pop, group, iter, t)

See pram.rule.Rule.apply.

get_states()

Get list of states.

is_applicable(group, iter, t)

See pram.rule.Rule.is_applicable.

class pram.rule.DiscreteSpaceContinuousTimeStochasticProcess(name='rule', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.StochasticProcess, abc.ABC

class pram.rule.DiscreteSpacetimeStochasticProcess(name='rule', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.StochasticProcess, abc.ABC

class pram.rule.DiscreteVarMarkovChain(attr, tm, name='markov-chain', t=attr.attrs, i=attr.attrs, memo=None)

Bases: pram.rule.MarkovChain, pram.rule.DiscreteSpacetimeStochasticProcess

Discrete-time non-time-homogenous Markov chain with finite state space.

Rule notation A:

code:
    fn_flu_s_sv:
        p_inf = n@_{attr.flu = 'i'} / n@
        return [1 - p_inf, p_inf, 0.00]

    TimeVarMarkovChain('flu', { 's': fn_flu_s_sv, 'i': [0.00, 0.80, 0.20], 'r': [0.10, 0.00, 0.90] })

ext:
    p_inf

init:
    tm = {
        s: [1 - p_inf, p_inf, 0.00],
        i: [0.00, 0.80, 0.20],
        r: [0.10, 0.00, 0.90]
    }  # right stochastic matrix

is-applicable:
    has-attr: flu

apply:
    tm_i = tm[group.attr.flu]
    move-mass:
        tm_i[0] -> A: flu = s
        tm_i[1] -> A: flu = i
        tm_i[2] -> A: flu = r

Rule notation B:

tm_i = tm[group.attr.flu]
tm_i[0] -> A:flu = 's'
tm_i[1] -> A:flu = 'i'
tm_i[2] -> A:flu = 'r'
Parameters
  • attr (str) – Name of state attribute.

  • tm (Mapping[str,Iterable[float]]) – Transition matrix. Keys correspond to state names and values to lists of transition probabilities.

  • name (str) – Name.

  • t (Time, int, tuple[int,int], set[int]) – Compatible time selector.

  • i (Iter, int, tuple[int,int], set[int]) – Compatible iteration selector.

  • memo (str, optional) – Description.

apply(pop, group, iter, t)

See pram.rule.Rule.apply.

get_states()

Get list of states.

is_applicable(group, iter, t)

See pram.rule.Rule.is_applicable.

class pram.rule.DistributionProcess(name='distrib-proc', t=attr.attrs, i=attr.attrs, p_max=None, group_qry=None, memo=None)

Bases: pram.rule.Process, abc.ABC

Generic distribution process.

Parameters
  • name (str) – Name.

  • t (Time, int, tuple[int,int], set[int]) – Time selector.

  • i (Iter, int, tuple[int,int], set[int]) – Iteration selector.

  • p_max (float) – The maximum proportion of mass that should be converted (i.e., at the mode of the distribution). The distribution that describes mass conversion is internally scaled to match that argument. If ‘None’, no scaling is performed.

  • group_qry (GroupQry, optional) – Compatible group selector.

  • memo (str, optional) – Description.

get_p(iter)
plot(figsize=10, 2, fmt='g-', lw=1, label=None, dpi=150, do_legend=True, do_show=True)
set_dist(dist, mode)

Sets the distribution.

Parameters
  • dist (scipy.stats.rv_generic) – Distribution.

  • mode (float) – The mode of the distribution.

class pram.rule.Disturbance(name='rule', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.Rule, abc.ABC

class pram.rule.Equation(name='rule', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.Rule, abc.ABC

class pram.rule.Event(name='rule', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.Rule, abc.ABC

class pram.rule.FibonacciSeq(attr='fib', name='fibonacci-seq', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.Sequence, pram.rule.DifferenceEquation

The Fibonacci numbers sequence.

This rule updates the designated group attribute with sequential Fibonacci numbers, one number per iteration.

Parameters
  • attr (str) – The attribute name to store the sequence in. The state of the sequence is stored in the group’s attribute space using two extra attributes: attr_1 and attr_2.

  • name (str) – Name.

  • t (Time, int, tuple[int,int], set[int]) – Compatible time selector.

  • i (Iter, int, tuple[int,int], set[int]) – Compatible iteration selector.

  • group_qry (GroupQry, optional) – Compatible group selector.

  • memo (str, optional) – Description.

apply(pop, group, iter, t)

See pram.rule.Rule.apply.

is_applicable(group, iter, t)

Verifies if the rule is applicable to the specified group at the specified iteration and time.

This method is called automatically and a rule will only be applied if this method returns True.

Parameters
  • group (Group) – Group.

  • iter (Iter) – Iteration.

  • time (Time) – Time.

Returns

True if applicable, False otherwise.

Return type

bool

class pram.rule.Forcing(name='rule', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.Rule, abc.ABC

class pram.rule.ForkDirective

Bases: pram.rule.Directive

class pram.rule.GammaDistributionProcess(name='gamma-distrib-proc', t=attr.attrs, i=attr.attrs, p_max=None, a=1.0, loc=0.0, scale=1.0, label=None, group_qry=None, memo=None)

Bases: pram.rule.DistributionProcess, abc.ABC

Gamma distribution process.

Parameters
  • name (str) – Name.

  • t (Time, int, tuple[int,int], set[int]) – Time selector.

  • i (Iter, int, tuple[int,int], set[int]) – Iteration selector.

  • p_max (float, optional) – The maximum proportion of mass that should be converted (i.e., at the mode of the distribution). The distribution that describes mass conversion is internally scaled to match that argument. If ‘None’, no scaling is performed.

  • a (float) – A paramater.

  • loc (float) – Location parameter.

  • scale (float) – Scale parameter.

  • label (str, optional) – Plot label.

  • memo (str, optional) – Description.

class pram.rule.GoToAndBackTimeAtRule(to='school', back='home', time_pdf_to=None, time_pdf_back=None, t_at_attr='t@', do_force_back=True, name='to-and-back', t=[8, 16], i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.Rule

GoTo and back.

Compels agents to go to the designated site and back; agents stay at the destination for a specificed amount of time.

Both ‘to’ and ‘back’ sites need to be specified. Moreover, the proportion of agents moving to the destination can be speficied as a probability distribution function (PDF) as can the time agents should spend at the destination. As a consequence of the latter, this rule tracks the time agents spend at the destination via a group attribute ‘t_at_attr’. Furthermore, agents can be forced to the original location at the end of the rule’s time interval. For example, students can be made go back home at the time schools close, irrespective of how long they have been at school.

This rule is only applicable to groups with both to and from sites and only those that are currently located at the latter.

Parameters
  • to (str) – Name of destination site.

  • back (str) – Name of source site.

  • time_pdf_to (Mapping[int,float]) – PDF for going to the destination site.

  • time_pdf_back (Mapping[int,float]) – PDF for going back to the source site.

  • do_force_back (bool) – Force the entire population back to the source site?

  • name (str) – Name.

  • t (Time, int, tuple[int,int], set[int]) – Compatible time selector.

  • i (Iter, int, tuple[int,int], set[int]) – Compatible iteration selector.

  • group_qry (GroupQry, optional) – Compatible group selector.

  • memo (str, optional) – Description.

NAME = 'Goto and back'
TIME_PDF_BACK_DEF = {1: 0.05, 3: 0.2, 4: 0.25, 5: 0.2, 6: 0.1, 7: 0.1, 8: 0.1}
TIME_PDF_TO_DEF = {8: 0.5, 12: 0.5}
apply(pop, group, iter, t)

See pram.rule.Rule.apply.

apply_back(group, iter, t)
apply_to(group, iter, t)
is_applicable(group, iter, t)

See pram.rule.Rule.is_applicable.

class pram.rule.GoToRule(p, rel_from, rel_to, name='goto', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.Rule

GoTo.

Changes the location of a group from the designated site to the designated site. Both of the sites are specificed by relation name (e.g., ‘store’). The rule will only apply to a group that (a) is currently located at the “from” relation and has the “to” relation. If the “from” argument is None, all groups will qualify as long as they have the “to” relation. The values of the relations need to be of type Site.

Only one ‘from’ and ‘to’ location is handled by this rule (i.e., lists of locations are not supported).

The group’s current location is defined by the ‘Site.AT’ relation name and that’s the relation that this rule updates.

Example use is to compel a portion of agents that are at home go to work or vice versa.

Parameters
  • name (str) – Name.

  • t (Time, int, tuple[int,int], set[int]) – Compatible time selector.

  • i (Iter, int, tuple[int,int], set[int]) – Compatible iteration selector.

  • group_qry (GroupQry, optional) – Compatible group selector.

  • memo (str, optional) – Description.

NAME = 'Goto'
apply(pop, group, iter, t)

See pram.rule.Rule.apply.

is_applicable(group, iter, t)

See pram.rule.Rule.is_applicable.

class pram.rule.GroupMassDecByNumRule(m, name='grp-mass-dec-by-num', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.Rule

Decreases the mass of a group by number.

Parameters
  • m (float) – The mass to remove.

  • name (str) – Name.

  • t (Time, int, tuple[int,int], set[int]) – Compatible time selector.

  • i (Iter, int, tuple[int,int], set[int]) – Compatible iteration selector.

  • group_qry (GroupQry, optional) – Compatible group selector.

  • memo (str, optional) – Description.

apply(pop, group, iter, t)

See pram.rule.Rule.apply.

class pram.rule.GroupMassDecByPropRule(p, name='grp-mass-dec-by-prop', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.Rule

Decreases the mass of a group by a proportion/probability.

Parameters
  • p (float) – The proportion of mass to remove.

  • name (str) – Name.

  • t (Time, int, tuple[int,int], set[int]) – Compatible time selector.

  • i (Iter, int, tuple[int,int], set[int]) – Compatible iteration selector.

  • group_qry (GroupQry, optional) – Compatible group selector.

  • memo (str, optional) – Description.

apply(pop, group, iter, t)

See pram.rule.Rule.apply.

class pram.rule.GroupMassIncByNumRule(m, name='grp-mass-inc-by-num', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.Rule

Increases the mass of a group by number.

Parameters
  • m (float) – The mass to remove.

  • name (str) – Name.

  • t (Time, int, tuple[int,int], set[int]) – Compatible time selector.

  • i (Iter, int, tuple[int,int], set[int]) – Compatible iteration selector.

  • group_qry (GroupQry, optional) – Compatible group selector.

  • memo (str, optional) – Description.

apply(pop, group, iter, t)

See pram.rule.Rule.apply.

class pram.rule.GroupMassIncByPropRule(p, name='grp-mass-inc-by-prop', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.Rule

Increases the mass of a group by a proportion/probability.

Parameters
  • p (float) – The proportion of mass to remove.

  • name (str) – Name.

  • t (Time, int, tuple[int,int], set[int]) – Compatible time selector.

  • i (Iter, int, tuple[int,int], set[int]) – Compatible iteration selector.

  • group_qry (GroupQry, optional) – Compatible group selector.

  • memo (str, optional) – Description.

apply(pop, group, iter, t)

See pram.rule.Rule.apply.

class pram.rule.Input(name='rule', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.Rule, abc.ABC

class pram.rule.InteractingParticleSystem(name='rule', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.StochasticProcess

Continuous-time Markov jump processes describing the collective behavior of stochastically interacting components. IPS are the continuous-time analogue of stochastic cellular automata.

class pram.rule.Intervention(name='rule', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.Rule, abc.ABC

class pram.rule.JumpProcess(name='rule', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.PoissonProcess

Jump process.

A jump process is a type of stochastic process that has discrete movements, called jumps, with random arrival times, rather than continuous movement, typically modelled as a simple or compound Poisson process.

class pram.rule.LevyProcess(name='rule', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.MarkovProcess

The continuous-time analog of a random walk.

class pram.rule.LogisticMap(name='rule', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.Sequence, pram.rule.ChaoticMap

class pram.rule.LorenzSystem(fn_deriv, y0, name='ode-system', t=attr.attrs, i=attr.attrs, dt=1.0, ni_name='zvode', group_qry=None, memo=None)

Bases: pram.rule.ChaoticMap, pram.rule.ODESystem

class pram.rule.LotkaVolterraSystem(fn_deriv, y0, name='ode-system', t=attr.attrs, i=attr.attrs, dt=1.0, ni_name='zvode', group_qry=None, memo=None)

Bases: pram.rule.ChaoticMap, pram.rule.ODESystem

class pram.rule.MarkovChain(name='rule', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.MarkovProcess, pram.rule.ProbabilisticAutomaton, abc.ABC

Markov process with a discrete state space.

class pram.rule.MarkovProcess(name='rule', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.StochasticProcess, abc.ABC

A stochastic process that satisfies the Markov property.

class pram.rule.Model(name='rule', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.Rule, abc.ABC

class pram.rule.Noop(name='noop')

Bases: pram.rule.Rule

NO-OP, i.e., a rule that does not do anything.

Useful for testing simulations that require no rules (because at least one rule need to be present in a simulation in order for groups to be added).

Parameters

name (str) – Name.

apply(pop, group, iter, t)

See pram.rule.Rule.apply.

class pram.rule.NormalDistributionProcess(name='norm-distrib-proc', t=attr.attrs, i=attr.attrs, p_max=None, loc=0.0, scale=1.0, label=None, group_qry=None, memo=None)

Bases: pram.rule.DistributionProcess, abc.ABC

Normal distribution process.

Parameters
  • name (str) – Name.

  • t (Time, int, tuple[int,int], set[int]) – Time selector.

  • i (Iter, int, tuple[int,int], set[int]) – Iteration selector.

  • p_max (float) – The maximum proportion of mass that should be converted (i.e., at the mode of the distribution). The distribution that describes mass conversion is internally scaled to match that argument. If ‘None’, no scaling is performed.

  • loc (float) – Location parameter.

  • scale (float) – Scale parameter.

  • label (str, optional) – Plot label.

  • group_qry (GroupQry, optional) – Compatible group selector.

  • memo (str, optional) – Description.

class pram.rule.ODEDerivatives

Bases: abc.ABC

Ordinary differential equations system’s derivatives.

This object is one of the parameters to the ODESystemMass constructor.

abstract get_fn(state)

Get the variable values of the system given state.

Parameters

state (Iterable[float]) – List of variable values.

set_params(**kwargs)

Set a subset of superset of the parameters.

class pram.rule.ODESystem(fn_deriv, y0, name='ode-system', t=attr.attrs, i=attr.attrs, dt=1.0, ni_name='zvode', group_qry=None, memo=None)

Bases: pram.rule.Rule

Ordinary differential equations system.

Wraps a numeric integrator to solve a system of ordinary differential equations (ODEs) that do not interact with anything else in the simulation. The non-interactivity stems from the derivatives being kept internally to the integrator only. This is useful when computations need to happen on a step-by-step basis, consistent with the rest of the simulation, but the results should not affect the group attribute space. One consequnce of this operationalization is that the rule need to fire only once per iteration, which this rule does.

Parameters
  • fn_deriv (Callable) – Derivative-computing function.

  • y0 (Iterable[float]) – Initial condition.

  • name (str) – Name.

  • t (Time, int, tuple[int,int], set[int]) – Compatible time selector.

  • i (Iter, int, tuple[int,int], set[int]) – Compatible iteration selector.

  • dt (float) – Time step size.

  • ni_name (str) – Name of numeric integrator.

  • group_qry (GroupQry, optional) – Compatible group selector.

  • memo (str, optional) – Description.

apply(pop, group, iter, t)

See pram.rule.Rule.apply.

get_hist()

Get the history of times and derivatives computed at those times.

set_params(fn_deriv)

Set rule’s parameters.

class pram.rule.ODESystemAttr(fn_deriv, y0, name='ode-system', t=attr.attrs, i=attr.attrs, dt=1.0, ni_name='zvode', memo=None)

Bases: pram.rule.Rule

Ordinary differential equations system on group attributes.

Wraps a numeric integrator to solve a system of ordinary differential equations (ODEs) and store its state in the group attribute space.

Parameters
  • fn_deriv (Callable) – Derivative-computing function.

  • y0 (Iterable[float]) – Initial condition.

  • name (str) – Name.

  • t (Time, int, tuple[int,int], set[int]) – Compatible time selector.

  • i (Iter, int, tuple[int,int], set[int]) – Compatible iteration selector.

  • group_qry (GroupQry, optional) – Compatible group selector.

  • memo (str, optional) – Description.

apply(pop, group, iter, t)

See pram.rule.Rule.apply.

get_hist()

Get the history of times and derivatives computed at those times.

is_applicable(group, iter, t)

See pram.rule.Rule.is_applicable.

set_params(fn_deriv)

Set rule’s parameters.

class pram.rule.ODESystemMass(derivatives, group_queries, name='ode-system-mass', t=attr.attrs, i=attr.attrs, dt=1.0, ni_name='zvode', memo=None)

Bases: pram.rule.Rule

Ordinary differential equations system on group mass.

Wraps a numeric integrator to solve a system of ordinary differential equations (ODEs) that drive mass shifts.

The initial state is deterimed by the group landscape.

The rule splits the congruent group (i.e., the one meeting the search criteria) into the number of parts that corresponds to the number of ODEs. Even though it might seem like different groups should be split differently, this solution is correct and stems from the fact that the new group sizes are calculated for the iteration step (i.e., for all groups) and not for individual group.

Parameters
  • derivatives (ODEDerivatives) – Derivatives object.

  • group_queries (Iterable[GroupQry]) – Group selectors. The number and order must correspond to the derivatives.

  • name (str) – Name.

  • t (Time, int, tuple[int,int], set[int]) – Compatible time selector.

  • i (Iter, int, tuple[int,int], set[int]) – Compatible iteration selector.

  • dt (float) – Time step size.

  • ni_name (str) – Name of numeric integrator.

  • memo (str, optional) – Description.

apply(pop, group, iter, t)

See pram.rule.Rule.apply.

get_hist()

Get the history of times and derivatives computed at those times.

is_applicable(group, iter, t)

See pram.rule.Rule.is_applicable.

set_params(**kwargs)

Set rule’s parameters.

class pram.rule.ODeltaESystem(name='rule', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.Rule

class pram.rule.OneDecayProcess(name='rule', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.Rule

Radioactive one-decay process.

N(t) = N_0 e^{-lambda t}

class pram.rule.OrnsteinUhlenbeckProcess(name='rule', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.LevyProcess, pram.rule.DiffusionProcess

A stationary Gauss–Markov mean-reverting process.

class pram.rule.Perturbation(name='rule', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.Rule, abc.ABC

class pram.rule.PoissonIncidenceProcess(attr, age_0, rate_0, delta, delta_t, rate_delta_mode=<RateDeltaMode.NC: 1>, fn_calc_lambda=None, is_smooth=True, name='change-incidence', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.PoissonProcess

Homogenous and inhomogenous Poisson point process for disease incidence.

The non-homogeneity of the Poisson process is handled by allowing the user to specify how the rate (i.e., the $lambda$ parameter) of the process changes over time. The change to that rate is given as the combination of a delta on it and the number of iterations for that delta to take place. The rate parameter is allowed to change gradually (i.e., at every step of the simulation) or in strict increments (e.g., only every 10 iterations) and is controlled by the inc_smooth argument. The rate is determined by the rate_delta_mode argument.

A Cox process, also known as a doubly stochastic Poisson process is a point process which is a generalization of a Poisson process where the time-dependent intensity is itself a stochastic process. The Cox process can be implemented by passing as an argument a function which will be called at every iteration to determine the current Poisson rate. rate_delta_mode = RateDeltaMode.FN must be used in that case.

An example model given as “AD incidence doubles every five years after 65 yo” can be instantiated by using the delta of two and the number of iterations of five.

Epidemiology of Alzheimer’s disease and other forms of dementia in China, 1990-2010: a systematic review and analysis. PDF

Wikipedia: Incidence (epidemiology)

Rule notation A:

code:
    PoissonIncidenceProcess('ad', 65, 0.01, 2, 5, rate_delta_mode=PoissonIncidenceProcess.RateDeltaMode.EXP))

init:
    age_0=65, l_0=0.01, c=2, t_c=5

is-applicable:
    has-attr: age, ad

apply:
    if (group.attr.age >= age_0):
        l = double_rate(l)        # l0 * c^{(group.attr.age - age_0) / t_c}
        p_0 = PoissonPMF(l,0)  # ...
        move-mass:
                p_0 -> A:age = group.attr.age + 1
            1 - p_0 -> A:age = group.attr.age + 1, A:ad = True

Rule notation B:

(group.attr.age >= age_0)
    l = double_rate(l)        # l0 * c^{(group.attr.age - age_0) / t_c}
    p_0 = PoissonPMF(l,0)
    p_0     -> A:age = group.attr.age + 1
    1 - p_0 -> A:age = group.attr.age + 1, A:ad = True
Parameters
  • attr (str) – Attribute name for the disease.

  • age_0 (int) – Lower bound cut-off age for getting AD.

  • rate_0 (float) – Base rate of the Poisson process (i.e., at the cut-off age).

  • delta (float) – Increase the rate by this factor.

  • delta_t (float) – Increase the rate every this many time units

  • rate_delta_mode (str) –

    • NC - No change (i.e., the Poisson process is stationary)

    • ADD - Additive

    • MUL - Multiplicative

    • EXP - Exponential

    • FN - User-provided lambda function called at every iteration

  • fn_calc_lambda (Callable, optional) – Custom lambda function.

  • is_smooth (bool) – Smooth increment if true, defined increments otherwise.

  • name (str) – Name.

  • t (Time, int, tuple[int,int], set[int]) – Compatible time selector.

  • i (Iter, int, tuple[int,int], set[int]) – Compatible iteration selector.

  • group_qry (GroupQry, optional) – Compatible group selector.

  • memo (str, optional) – Description.

class RateDeltaMode(value)

Bases: enum.IntEnum

An enumeration.

ADD = 2
EXP = 4
FN = 5
MUL = 3
NC = 1
apply(pop, group, iter, t)

See pram.rule.Rule.apply.

calc_lambda_add(age)

Additive rate change.

calc_lambda_exp(age)

Exponential rate change.

calc_lambda_hmm(age)

Poisson hidden Markov models (PHMM) are special cases of hidden Markov models where a Poisson process has a rate which varies in association with changes between the different states of a Markov model.

calc_lambda_mul(age)

Multiplicative rate change.

calc_lambda_nc(age)

No rate change (i.e., a stationary Poisson point process).

get_split_specs(group, age_inc=1)
Parameters
  • group (Group) – Group.

  • age_inc (int) – Number by which to increment the age attribute.

is_applicable(group, iter, t)

See pram.rule.Rule.is_applicable.

setup(pop, group)

See pram.rule.Rule.setup.

class pram.rule.PoissonProcess(name='rule', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.LevyProcess

Poisson point process.

Markov processes in continuous time.

class pram.rule.ProbabilisticAutomaton(name='rule', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.Rule, abc.ABC

class pram.rule.ProbabilisticEquation(name='rule', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.Equation

An algebraic equation p(t), where $p(t) in [0,1]$ (i.e., it yields a probability).

class pram.rule.Process(name='rule', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.Rule, abc.ABC

class pram.rule.RandomWalk(attr, tm, name='markov-chain', t=attr.attrs, i=attr.attrs, memo=None, cb_before_apply=None)

Bases: pram.rule.DiscreteInvMarkovChain

A Markov processes in discreet time.

The results of discretizing both time and space of a diffusion equation.

class pram.rule.ResetRule(t=5, i=None, attr_del=None, attr_set=None, rel_del=None, rel_set=None, memo=None)

Bases: pram.rule.Rule

NAME = 'Reset'
apply(pop, group, iter, t)

See pram.rule.Rule.apply.

class pram.rule.ResetSchoolDayRule(t=5, i=None, attr_del=['t-at-school'], attr_set=None, rel_del=None, rel_set=None, memo=None)

Bases: pram.rule.ResetRule

NAME = 'Reset school day'
is_applicable(group, iter, t)

See pram.rule.Rule.is_applicable.

class pram.rule.ResetWorkDayRule(t=5, i=None, attr_del=None, attr_set=None, rel_del=None, rel_set=None, memo=None)

Bases: pram.rule.ResetRule

NAME = 'Reset work day'
is_applicable(group, iter, t)

See pram.rule.Rule.is_applicable.

class pram.rule.Rule(name='rule', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: abc.ABC

A group rule.

A rule that can be applied to a group and may split it into multiple groups.

A rule will be applied if the simulation timer’s time (external to this class) falls within the range defined by the time specification ‘t’. Every time a rule is applied, it is applied to all groups it is compatible with. For instance, a rule that renders a portion of a group infection-free (i.e., marks it as recovered) can be applied to a group of humans currently infected with some infectious disease. The same rule, however, would not be applied to a group of city buses. Each rule knows how to recognize a compatible group.

Parameters
  • name (str) – Name.

  • t (Time, int, tuple[int,int], set[int]) – Compatible time selector.

  • i (Iter, int, tuple[int,int], set[int]) – Compatible iteration selector.

  • group_qry (GroupQry, optional) – Compatible group selector.

  • memo (str, optional) – Description.

ATTRS = {}
NAME = 'Rule'
_set_i(i=None)

Decode and set iteration selector.

Parameters

i (Iter, int, tuple[int,int], set[int], optional) – Iteration selector.

_set_t(t=None)

Decode and set time selector.

Parameters

t (Time, int, tuple[int,int], set[int], optional) – Time selector.

abstract apply(pop, group, iter, t)

Apply the rule.

This method is called automatically for every group at every simulation iteration provided the rule is compatible with the iteration, time, and the group.

Parameters
  • pop (GroupPopulation) – Population.

  • group (Group) – Group.

  • iter (int) – Iteration.

  • time (float) – Time.

Returns

Specs groups the current group should be split into.

Return type

Iterable[GroupSplitSpect] or None

cleanup(pop, group)

Rule cleanup.

Run once at the end of a simulation run. Symmetrical to setup(). Uses group-splitting mechanism.

Parameters
Returns

Specs groups the current group should be split into.

Return type

Iterable[GroupSplitSpect] or None

compile_spec = None
get_inner_rules()

Get a rule’s inner rules.

A rule’s inner rules allow a rule dependency hierarchy to be specified.

Returns

Iterable[Rule] or None

static get_rand_name(name, prefix='__', rand_len=12)

Generate a random rule name.

Parameters
  • prefix (str) – Name prefix.

  • rand_len (int) – Number of random characters to be generated.

Returns

str

is_applicable(group, iter, t)

Verifies if the rule is applicable to the specified group at the specified iteration and time.

This method is called automatically and a rule will only be applied if this method returns True.

Parameters
  • group (Group) – Group.

  • iter (Iter) – Iteration.

  • time (Time) – Time.

Returns

True if applicable, False otherwise.

Return type

bool

is_applicable_group(group)

Verifies if the rule is applicable to the the specified group.

If the group_qry is None, the group is applicable automatically.

Parameters

group (Group) – Group.

Returns

True if applicable, False otherwise.

Return type

bool

is_applicable_iter(iter)

Verifies if the rule is applicable at the specified iteration.

Parameters

i (Iter, int, tuple[int,int], set) – Iteration selector.

Returns

True if applicable, False otherwise.

Return type

bool

is_applicable_time(t)

Verifies if the rule is applicable at the specified time.

Parameters

t (Time, int, tuple[int,int], set) – Time selector.

Returns

True if applicable, False otherwise.

Return type

bool

pop = None
set_params()

Set rule’s parameters.

set_t_unit(ms)

Set timer units.

Parameters

ms (int) – Number of milliseconds per timer unit. Values from pram.util.Time.MS can be used for convenience.

setup(pop, group)

Rule setup.

If a set of attributes and relations should be part of a group’s definition, that set should be specified here. For example, the following sets the attribute did-attend-school-today of all the groups:

return [GroupSplitSpec(p=1.0, attr_set={ 'did-attend-school-today': False })]

Each group will be split into a (possibly non-extant) new group via the group-splitting mechanism and the entirety of the group’s mass will be moved into that new group.

This method is also where a rule should do any other population initialization required. For example, a rule that introduces a new Site object to the simulation, should make the population object aware of that site like so:

pop.add_site(Site('new-site'))
Parameters
Returns

Specs groups the current group should be split into.

Return type

Iterable[GroupSplitSpect] or None

static tp2rv(tp, a=0, b=23)

Converts a time probability distribution function (PDF) to a scipy’s discrete random variable.

Parameters
  • tp (Mapping) – Time-probability mapping, e.g., { 1: 0.05, 3: 0.2, 4: 0.25, 5: 0.2, 6: 0.1, 7: 0.2 }.

  • a (int) – Lower bound.

  • b (int) – Upper bound.

Returns

scipy.stats.rv_discrete

class pram.rule.RuleAnalyzerTestRule(t=[8, 20], i=None, memo=None)

Bases: pram.rule.Rule

NAME = 'Rule analyzer test'
an(s)
apply(group, iter, t)

See pram.rule.Rule.apply.

is_applicable(group, iter, t)

See pram.rule.Rule.is_applicable.

rn(s)
class pram.rule.SEIRFluModel(t=attr.attrs, susceptibility=1.0, p_start_E=0.05, do_clean=True, memo=None)

Bases: pram.rule.SEIRModel

The SEIR model for the influenza.

ATTR = 'flu-state'
NAME = 'SEIR flu model'
class pram.rule.SEIRModel(name='seir', t=attr.attrs, susceptibility=1.0, p_start_E=0.05, do_clean=True, memo=None)

Bases: pram.rule.Rule, abc.ABC

The SEIR compartmental epidemiological model.

ATTR = 'seir-state'
ATTRS = {'seir-state': [1, 2, 3, 4]}
NAME = 'SEIR model'
class State(value)

Bases: enum.IntEnum

An enumeration.

E = 2
I = 3
R = 4
S = 1
apply(pop, group, iter, t)

See pram.rule.Rule.apply.

apply_E(pop, group, iter, t, state)
apply_I(pop, group, iter, t, state)
apply_R(pop, group, iter, t, state)
apply_S(pop, group, iter, t, state)
apply_err(pop, group, iter, t, state)
cleanup(pop, group)

See pram.rule.Rule.cleanup.

is_applicable(group, iter, t)

See pram.rule.Rule.is_applicable.

setup(pop, group)

See pram.rule.Rule.setup.

class pram.rule.SIRModelGillespie(name='rule', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.Rule

Gillespie algorithm.

class pram.rule.SegregationModel(attr, attr_dom_card, p_migrate=0.05, name='segregation-model', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.Rule

Segregation model.

Rule notation A:

    code:
        SegregationModel('team', 2)

    init:
        p_migrate = 0.05

    is-applicable:
        has-attr: team
        has-rel: @

    apply:
        p_team = n@_{attr.team = group.attr.team} / n@  # ...
        if (p_team < 0.5):
            rd p_migrate -> R:@ = get_random_site()
            nc 1 - p_migrate

Rule notation B::

    p_team = n@_{attr.team = group.attr.team} / n@
    if (p_team < 0.5) p_migrate -> R:@ = get_random_site()

Args:
    attr (str): Name.
    attr_dom_card (str): Cardinality of the attribute values set.
    p_migrate (str): Probability of the population to migrate if repelled.
    name (str): Name.
    t (:class:`~pram.rule.Time`, int, tuple[int,int], set[int]): Compatible time selector.
    i (:class:`~pram.rule.Iter`, int, tuple[int,int], set[int]): Compatible iteration selector.
    group_qry (GroupQry, optional): Compatible group selector.
    memo (str, optional): Description.
apply(pop, group, iter, t)

See pram.rule.Rule.apply.

get_random_site(pop, site)

Get a random site different than the specified one.

is_applicable(group, iter, t)

See pram.rule.Rule.is_applicable.

class pram.rule.Sequence(name='rule', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.Rule, abc.ABC

class pram.rule.SimRule(name='rule', t=attr.attrs, i=attr.attrs, memo=None)

Bases: pram.rule.Rule, abc.ABC

Simulation rule.

A simulation rule is run at the end of every simulation iteration (i.e., after the mass transfer for that iteration has concluded). These sort of rules are useful for implementing policy-level intervention. For example, should schools in a county, state, or the entire country be closed in response to an epidemic? This sort of mitigation measure might be in effect after, say, 6% of the population has become infected.

Upon adding an instance of this class to the Simulation object, the latter will add all ‘self.vars’ as simulation variables. Consequently, this ABC’s constructor should ordinarily be called as the first step in the child’s constructor so that the dict is not overwritten.

Parameters
  • name (str) – Name.

  • t (Time, int, tuple[int,int], set[int]) – Time selector.

  • i (Iter, int, tuple[int,int], set[int]) – Iteration selector.

  • memo (str) – Description.

abstract apply(sim, iter, t)

Apply the rule.

This method is called automatically for every group at every simulation iteration provided the rule is compatible with the iteration, time, and the group.

Parameters
  • sim (Simulation) – Simulation.

  • iter (int) – Iteration.

  • time (float) – Time.

Returns

Specs groups the current group should be split into.

Return type

Iterable[GroupSplitSpect] or None

is_applicable(group, iter, t)

See pram.rule.Rule.is_applicable.

class pram.rule.SimpleFluLocationRule(t=attr.attrs, memo=None)

Bases: pram.rule.Rule

Describes how student population changes location conditional upon being exposed to the flu.

Rule notation A:

code:
    SimpleFluLocationRule()

is-applicable:
    has-attr: flu
    has-rel: home, school

apply:
    if group.attr.flu = 'i':
        if group.attr.income = 'l':
            rd 0.1 -> R:@ = group.rel.home  # rd - redistribute mass
            nc 0.9                          # nc - no change
        if group.attr.income = 'm':
            rd 0.6 -> R:@ = group.rel.home
            nc 0.4
    if group.attr.flu = 'r':
        rd 0.8 -> R:@ = group.rel.school
        nc 0.2

Rule notation B:

if (flu = i)
    if (income = l)
        rd 0.1 -> R:@ = home
        nc 0.9
    if (income = m)
        rd 0.6 > R:@ = home
        nc 0.4
if (flu = r)
    rd 0.8 > R:@ = school
    nc 0.2
ATTRS = {'flu': ['s', 'i', 'r'], 'income': ['l', 'm']}
NAME = 'Simple flu location model'
apply(pop, group, iter, t)

See pram.rule.Rule.apply.

class pram.rule.SimpleFluProgressMoodRule(t=attr.attrs, memo=None)

Bases: pram.rule.Rule

Describes how a population transitions between the states of susceptible, infected, and recovered. Includes the inconsequential ‘mood’ attribute which may improve exposition of how the PRAM framework works.

Rule notation A:

code:
    SimpleFluProgressMoodRule()

is-applicable:
    has-attr: flu

apply:
    if group.attr.flu = 's':
        p_inf = n@_{attr.flu = 'i'} / n@
        move-mass:
            p_inf -> A:flu = 'i', A:mood = 'annoyed'
    if group.attr.flu = 'i':
        move-mass:
            0.2 -> A:flu = 'r', A:mood = 'happy'
            0.5 ->              A:mood = 'bored'
            0.3 ->              A:mood = 'annoyed'
    if group.attr.flu = 'r':
        move-mass:
            0.1 -> A:flu = 's'

Rule notation B:

if (flu = s)
    p_inf = n@_{attr.flu = i} / n@
    p_inf -> A:flu = 'i', A:mood = 'annoyed'
if (flu = i)
    0.2 -> A:flu = 'r', A:mood = 'happy'
    0.5 ->              A:mood = 'bored'
    0.3 ->              A:mood = 'annoyed'
if (flu = r) 0.1 > A:flu = s
NAME = 'Simple flu progression model with mood'
apply(pop, group, iter, t)

See pram.rule.Rule.apply.

class pram.rule.SimpleFluProgressRule(t=None, i=None, memo=None)

Bases: pram.rule.Rule

Describes how a population transitions between the flu states of susceptible, infected, and recovered.

Rule notation A:

code:
    SimpleFluProgressRule()

is-applicable:
    has-attr: flu

apply:
    if group.attr.flu = 's':
        p_inf = n@_{attr.flu = 'i'} / n@
        move-mass:
            p_inf -> A:flu = 'i'
    if group.attr.flu = 'i':
        move-mass:
            0.2 -> A:flu = 'r'
    if group.attr.flu = 'r':
        move-mass:
            0.1 -> A:flu = 's'

Rule notation B:

if (flu = s)
    p_inf = n@_{attr.flu = i} / n@
    p_inf -> A: flu = 'i'
if (flu = i) 0.2 > A:flu = r
if (flu = r) 0.1 > A:flu = s
ATTRS = {'flu': ['s', 'i', 'r']}
NAME = 'Simple flu progression model'
apply(pop, group, iter, t)

See pram.rule.Rule.apply.

setup(pop, group)

See pram.rule.Rule.setup.

class pram.rule.StationaryProcess(name='rule', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.StochasticProcess, abc.ABC

A stochastic process whose unconditional joint probability distribution does not change when shifted in time.

class pram.rule.Stimulus(name='rule', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.Rule, abc.ABC

class pram.rule.StochasticCellularAutomaton(name='rule', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.CellularAutomaton

Probabilistic cellular automata (PCA), random cellular automata, or locally interacting Markov chains.

class pram.rule.StochasticProcess(name='rule', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.Rule, abc.ABC

A stochastic process is a collection of random variables indexed by time or space.

class pram.rule.System(name='rule', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.Rule, abc.ABC

class pram.rule.TimeSeriesFn(name='rule', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.Rule, abc.ABC

Function-based time series.

class pram.rule.TimeSeriesObs(x, name='time-series', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.Rule, abc.ABC

Observation-based time series.

A rule that replays a time series given by a stochastic vector or a stochastic matrix of explicit observations (e.g., historical data). The following matrix:

    t1 t2 t3
x1   1  2  3
x2   4  5  6

should be provided as:

{ 'x1': [1,2,3], 'x2': [4,5,6] }
Parameters
  • x (Mapping[str,Iterable[number]]) – Time series to replay.

  • name (str) – Name.

  • t (Time, int, tuple[int,int], set[int]) – Compatible time selector.

  • i (Iter, int, tuple[int,int], set[int]) – Compatible iteration selector.

  • group_qry (GroupQry, optional) – Compatible group selector.

  • memo (str, optional) – Description.

apply(pop, group, iter, t)

See pram.rule.Rule.apply.

class pram.rule.WienerProcess(name='rule', t=attr.attrs, i=attr.attrs, group_qry=None, memo=None)

Bases: pram.rule.LevyProcess, pram.rule.DiffusionProcess

Markov processes in continuous time.

Brownian motion process or Brownian motion.

A limit of simple random walk.

pram.signal module

Contains signal-processing relevant code.

When considered over time, agent mass dynamics and other time series that PyPRAM outputs can be seen as signals. Signal processing toolkit can therefore be used to process those signals. Because PyPRAM currently is a discrete-time system (i.e., it only supports iteration over time steps), all signals it outputs are also discrete. However, with a sufficiently small time step size those signals can be a reasonably good approximation of the continuous-time data-generating processes. One example of that are systems of ordinary differential equations (ODEs). Because ODEs need to be numerically integrated (PyPRAM does not support analytical solvers), the time step size typically needs to be very small.

class pram.signal.Signal(series=None, names=None)

Bases: object

Multivariate time series as a signal.

A signal is a list of numpy arrays refered to as series. What every single of those array denotes depends on the outside algorithm that creates the signal. For example, they might (and often will) contain the time series of mass locus of a simulation.

Parameters
  • series (Signal or numpy.ndarray, optional) – Data for one or more series.

  • names (list(str), optional) – Names of all the series specified.

Raises

ValueError

add_series(s, name=None)

Adds one or more series to the series already stored.

Parameters
  • s (list(float), numpy.ndarray) – The series being added.

  • name (str, optional) – The name of the series being added.

Returns

For method chaining.

Return type

self

plot_autocorr(size, filename=None, do_ret_plot=False, dpi=100)

Generated autocorrelation plot.

Parameters
  • size (tuple(int,int)) – Figure size in the (w,h) format.

  • filename (string, optional) – Filename.

  • do_ret_plot (bool) – Flag: Return the figure or self?

  • dpi (int) – Resolution.

Returns

Return type

Figure if ‘do_ret_plot’ is True and self otherwise (for method chaining)

quantize(bitdepth=16)

Quantizes all series in the signal.

Parameters

bitdepth (int) – Number of bits to use.

pram.sim module

Contains PRAM simulation code.

class pram.sim.Simulation(pop_hist_len=0, traj_id=None, rand_seed=None, do_keep_mass_flow_specs=False)

Bases: object

A PRAM simulation.

At this point, this simulation is a discrete-event simulation (DES). DES models the operation of a system as a (discrete) sequence of events in time. DES can be contrasted with continuous simulation in which the system state is changed continuously over time on the basis of a set of differential equations defining the rates of change of state variables.

Parameters
  • pop_hist_len (int) – Maximum lenght of the population history. Keep memory utilization in mind when using positive numbers for this argument.

  • traj_id (Any) – ID of the trajectory which wraps the simulation object. That ID should come from the trajectory ensemble database.

  • random_seed (int, optional) – Pseudo-random number generator seed.

  • do_keep_mass_flow_specs (bool) – Store the last iteration mass flow specs? See pop.GroupPopulation and pop.MassFlowSpec classes.

add(lst=None)

Simulation element adder.

If the lst argument is None, this method returns instance of the SimulationAdder class that will handle adding simulation elements. Otherwise, it will add all elements of lst to the simulation.

Parameters

lst (Iterable) – Combination of objects of the following types: Group, Probe, SimRule, Rule, Model, and Site.

Returns

SimulationAdder

add_group(group)

Adds a group.

Parameters

group (Group) – The group.

Returns

self

add_groups(groups)

Adds groups.

Parameters

groups (Iterable[Group]) – The groups.

Returns

self

add_probe(probe)

Adds a probe.

Parameters

probe (Probe) – The probe.

Returns

self

add_probes(probes)

Adds probes.

Parameters

probes (Iterable[Probe]) – The probes.

Returns

self

add_rule(rule)

Adds a rule.

If the rule has any inner rules, all of those are added as well. An example of an inner rule is a desease transmission model that is being acted upon by another rule, e.g., an intervention rule which therefore contains it. Such containing relationship is not being enforced by the framework however.

An instance of a rule can only be added once.

Parameters

rule (Rule) – The rule.

Returns

self

add_rules(rules)

Adds rules.

Parameters

rules (Iterable[Rule]) – The rules.

Returns

self

add_sim_rule(rule)

Adds a simulation rule.

Parameters

rule (SimRule) – The simulation rule.

Returns

self

add_sim_rules(rules)

Adds simulation rules.

Parameters

rules (Iterable[SimRule]) – The simulation rules.

Returns

self

add_site(site)

Adds a site.

Parameters

site (Site) – The site.

Returns

self

add_sites(sites)

Adds sites.

Parameters

sites (Iterable[Site]) – The sites.

Returns

self

analyze_rules_dynamic()

Runs dynamic rule analysis.

See DynamicRuleAnalyzer.

Returns

self

analyze_rules_dynamic_old()
analyze_rules_static()

Runs static rule analysis.

See StaticRuleAnalyzer.

Returns

self

clear_probes()

Removes all probes.

Returns

self

clear_rules()

Removes all rules.

Returns

self

clear_sim_rules()

Removes all simulation rules.

Returns

self

commit_group(group)

Finishes adding a new group.

See new_group() for explanation of the mechanism.

Parameters

group (Group) – The group in question.

Returns

self

compact()

Compacts the simulation.

Returns

self

db(db)

Simulation database interface.

Parameters

db (DB) – Database management system specific object.

Returns

SimulationDBI

gen_diagram(fpath_diag, fpath_pdf)

Generates a simulation diagram.

Todo

Reimplement and extend this method.

Parameters
  • fpath_diag (str) – Path to the diagram source file.

  • fpath_pdf (str) – Path to the diagram PDF file.

Returns

self

gen_groups_from_db(db, schema, tbl, attr_db=[], rel_db=[], attr_fix={}, rel_fix={}, attr_rm=[], rel_rm=[], rel_at=None, limit=0)

Generate groups from a database.

Usage example:

from pram.util import SQLiteDB
...

s = Simulation()
s.gen_groups_from_db(
    db       = SQLiteDB('db.sqlite3'),
    schema   = None,
    tbl      = 'people',
    attr_db  = ['age_group'],
    attr_fix = {},
    rel_db   = [
        GroupDBRelSpec(name='school', col='school_id', fk_schema=None, fk_tbl='schools', fk_col='sp_id', sites=None)
    ],
    rel_fix  = { 'home': Site('home') },
    rel_at   = 'home'
)
s.add_rules(...)
s.add_probes(...)
s.run(24)
Parameters
  • db (DB) – Database management system specific object.

  • schema (str) – Database schema.

  • tbl (str) – Table name.

  • attr_db (Iterable[str]) – Group attributes to be retrieved from the database (if extant).

  • rel_db (Iterable[GroupDBRelSpec]) – Group relation to be retrieved from the database (if extant).

  • attr_fix (Mappint[str, Any]) – Group attributes to be fixed for every group.

  • rel_fix (Mapping[str, Site]) – Group relations to be fixed for every group.

  • attr_rm (Iterable[str]) – Group attributes to NOT be retrieved from the database (overwrites all).

  • rel_rm (Iterable[str]) – Group relation to NOT be retrieved from the database (overwrites all).

  • rel_at (Site, optional) – A site to be set as every group’s current location.

  • limit (int) – The maximum number of groups to be generated. Ordinarily, this is not changed from its default value of zero. It is however useful for testing, especially with very large databases.

Returns

self

gen_groups_from_db_old(fpath_db, tbl, attr={}, rel={}, attr_db=[], rel_db=[], rel_at=None, limit=0, fpath=None, is_verbose=False)
gen_sites_from_db(db, schema, tbl, name_col, rel_name='@', attr=[], limit=0)

Generate sites from a database.

Parameters
  • db (DB) – Database management system specific object.

  • schema (str) – Schema name.

  • tbl (str) – Table name.

  • name_col (str) – Table column storing names of sites.

  • rel_name (str) – Name of the relation to be associated with each of the sites generated. For example, if hospital sites are being generated, the rel_name could be set to hospital.

  • attr (Iterable[str]) – Names of table columns storing attributes to be internalized by the site objects being generated.

  • limit (int) – The maximum number of sites to be generated. Ordinarily, this is not changed from its default value of zero. It is however useful for testing, especially with very large databases.

Returns

self

static gen_sites_from_db_old(fpath_db, fn_gen=None, fpath=None, is_verbose=False, pragma_live_info=False, pragma_live_info_ts=False)
get_comp_hist()

Retrieves computational history.

The computational history dict contains the following items: - mem_iter (Iterable[int]): Memory usage per iteration [B]. - **t_iter* (Iterable[int]): Time per iteration [ms]. - **t_sim* (int): Total simulation time [ms].

Returns

Mapping[str, Any]

get_iter()

Get current iteration.

Used for parallel execution progress reporting.

Returns

If the simulation is running, a non-negative value is returned. If the simulation is in the

initial-condition mode (i.e., before at least one call of run()), -1 is returned.

Return type

int

get_pragma(name)

Return value of the designated pragma.

Available pragmas, their data types, and their functions are:

  • analyze (bool): Should static and dynamic rule analyses be performed?

  • autocompact (bool): Should the simulation be autocompacted after every iteration?

  • autoprune_groups (bool): Should empty groups be removed after every iteration?

  • autostop (bool): Should the simulation be stoped after stopping condition has been reached?

  • autostop_n (bool): Stopping condition: Mass smaller than specified has been transfered.

  • autostop_p (bool): Stopping condition: Mass proportion smaller than specified has been transfered.

  • autostop_t (bool):

  • live_info (bool): Display live info during simulation run?

  • live_info_ts (bool): Display live info timestamps?

  • partial_mass (bool): Allow floating point group mass? Integer is the default.

  • probe_capture_init (bool): Instruct probes to capture the initial state of the simulation?

  • rule_analysis_for_db_gen (bool):

Parameters

name (str) – The pragma.

Returns

Depending on the pragma type.

Return type

Any

get_pragma_analyze()

See get_pragma().

get_pragma_autocompact()

See get_pragma().

get_pragma_autoprune_groups()

See get_pragma().

get_pragma_autostop()

See get_pragma().

get_pragma_autostop_n()

See get_pragma().

get_pragma_autostop_p()

See get_pragma().

get_pragma_autostop_t()

See get_pragma().

get_pragma_comp_summary()

See get_pragma().

get_pragma_fractional_mass()

See get_pragma().

get_pragma_live_info()

See get_pragma().

get_pragma_live_info_ts()

See get_pragma().

get_pragma_probe_capture_init()

See get_pragma().

get_pragma_rule_analysis_for_db_gen()

See get_pragma().

get_probe(name)
get_probes()
get_state()

Get the current state of the simulation.

Returns

Mapping[str, Mapping[str, Any]]

get_var(name)

Get value of the designated simulation variable.

Parameters

name (str) – The variable.

Returns

Any

static load(fpath)

Deserialize simulation from a file.

Parameters

fpath (str) – Source file path.

Returns

Simulation

static load_bz2(fpath)

Deserialize simulation from a bzip2-compressed file.

Parameters

fpath (str) – Source file path.

Returns

Simulation

static load_gz(fpath)

Deserialize simulation from a gzip-compressed file.

Parameters

fpath (str) – Source file path.

Returns

Simulation

new_group(name=None, m=0.0)

Begins adding a new group.

After calling this method, the interaction is with the newly created group which will not have been added to the simulation until commit_group() is called, at which point the interaction returns to the simulation object. The commit_group() isn’t called directly; instead, it’s the Group.done() which calls it.

Below is a usage example:

(Simulation().
    add().
        rule(...).
        probe(...).
        done().
    new_group(1000).                     # a group of a 1000 agents
        set_attr('income', 'medium').    # with medium income
        set_rel(Site.AT, Site('home')).  # who are all currently located at a site called 'home'
        done().                          # back to the Simulation object
    run(12)
)
Parameters
  • name (str, optional) – Group name.

  • m (float, int) – Group mass.

Returns

Group

plot()

Simulation results plotter.

Returns

SimulationPlotter

plot_group_size(fpath=None, title='Distribution of Group Size', nx=250)

Plots the distribution of group sizes.

Parameters
  • fpath (str, optional) – Path to the plot file.

  • title (str) – Plot title.

  • nx (int) – Number of x-axis (i.e., the iteration axis) points.

Returns

matplotlib figure object if fpath is None; self otherwise

plot_site_size(fpath=None, title='Distribution of Site Size', nx=250)

Plots the distribution of site sizes.

Parameters
  • fpath (str, optional) – Path to the plot file.

  • title (str) – Plot title.

  • nx (int) – Number of x-axis (i.e., the iteration axis) points.

Returns

matplotlib figure object if fpath is None; self otherwise

rem_probe(probe)

Removes the designated probe.

Parameters

probe (Probe) – The probe.

Returns

self

rem_rule(rule)

Removes the designated rule.

Parameters

rule (Rule) – The rule.

Returns

self

remote_after()

Restores the object after remote execution (on a cluster).

Returns

self

remote_before()

Prepare the object for remote execution (on a cluster).

Returns

self

reset_cb()

Reset all callback functions.

The following callback functions are available: - after_iter: Call after iteration. - before_iter: Call before iteration. - check_work: - save_state: - upd_progress:

Returns

self

reset_comp_hist()

Reset computational history.

See get_comp_hist().

Returns

self

reset_pop()

Resets population.

All groups and sites are removed from the simulation and the simulation object is set back in the pre-setup state.

Returns

self

reset_pragmas()

Reset all pragmas to their default values.

See get_pragma().

Returns

self

reset_probes()

Removes all probes.

Returns

self

reset_rules()

Removes all group rules.

Returns

self

reset_sim_rules()

Removes all simulation rules.

Returns

self

reset_vars()

Reset all simulation variables.

Returns

self

run(iter_or_dur=1, do_disp_t=False, do_disp_iter=False)

Run the simulation.

Parameters
  • iter_or_dur (int or str) – Number of iterations or a string representation of duration (see util.Time.dur2ms())

  • do_disp_t (bool) – Display simulation time at every iteration? Useful for debugging.

  • do_disp_iter (bool) – Display simulation iteration at every iteration? Useful for debugging.

Returns

self

run__comp_summary()

Called by run() to display computational summary.

save(fpath)

Serialize simulation to a file.

Parameters

fpath (str) – Destination file path.

Returns

self

save_bz2(fpath)

Serialize simulation to a bzip2-compressed file.

Parameters

fpath (str) – Destination file path.

Returns

self

save_gz(fpath)

Serialize simulation to a gzip-compressed file.

Parameters

fpath (str) – Destination file path.

Returns

self

save_state(mass_flow_specs=None)

Call the save simulation state callback function.

Parameters

mass_flow_specs (MassFlowSpecs, optional) – Mass flow specs.

Returns

self

set()

Simulation element setter.

Returns

SimulationSetter

set_cb_after_iter(fn)

Set the callback function.

See reset_cb().

Parameters

fn (Callable) – The function.

Returns

self

set_cb_before_iter(fn)

Set the callback function.

See reset_cb().

Parameters

fn (Callable) – The function.

Returns

self

set_cb_check_work(fn)

Set the callback function.

See reset_cb().

Parameters

fn (Callable) – The function.

Returns

self

set_cb_save_state(fn)

Set the callback function.

See reset_cb().

Parameters

fn (Callable) – The function.

Returns

self

set_cb_upd_progress(fn)

Set the callback function.

See reset_cb().

Parameters

fn (Callable) – The function.

Returns

self

set_fn_group_setup(fn)

Set the group setup function.

The group setup function is the last function that is called before the simulatin is deemed ready for execution. An example of how that function could be used is to make a certain proportion of population infected with a disease in a epidemiological modeling setting.

Parameters

fn (Callable) – The function.

Returns

self

set_pragma(name, value)

Set value of the designated pragma.

See get_pragma().

Parameters
  • name (str) – Pragma.

  • value (Any) – Value.

Returns

self

set_pragma_analyze(value)

See get_pragma().

Returns

self

set_pragma_autocompact(value)

See get_pragma().

Returns

self

set_pragma_autoprune_groups(value)

See get_pragma().

Returns

self

set_pragma_autostop(value)

See get_pragma().

Returns

self

set_pragma_autostop_n(value)

See get_pragma().

Returns

self

set_pragma_autostop_p(value)

See get_pragma().

Returns

self

set_pragma_autostop_t(value)

See get_pragma().

Returns

self

set_pragma_comp_summary(value)

See get_pragma().

Returns

self

set_pragma_fractional_mass(value)

See get_pragma().

Returns

self

set_pragma_live_info(value)

See get_pragma().

Returns

self

set_pragma_live_info_ts(value)

See get_pragma().

Returns

self

set_pragma_probe_capture_init(value)

See get_pragma().

Returns

self

set_pragma_rule_analysis_for_db_gen(value)

See get_pragma().

Returns

self

set_pragmas(analyze=None, autocompact=None, autoprune_groups=None, autostop=None, autostop_n=None, autostop_p=None, autostop_t=None, comp_summary=None, fractional_mass=None, live_info=None, live_info_ts=None, probe_capture_init=None, rule_analysis_for_db_gen=None)

Sets values of multiple pragmas.

See get_pragma().

Parameters

of all pragmas; values set only when not None (Names) –

Returns

self

set_rand_seed(rand_seed=None)

Set pseudo-random generator seed.

Both the random and numpy generators’ seeds are set.

Parameters

rand_seed (int, optional) – The seed.

Returns

self

set_var(name, val)

Set value of a simulation variable.

Parameters
  • name (str) – The variable.

  • val (any) – The value.

Returns

self

set_vars(vars)

Set values of multiple simulation variables.

Parameters

vars (Mapping[str, Any]) – A dictionary of variable name-value pairs.

Returns

self

show_rule_analysis()

Display the results of both static and dynamic rule analyses.

See StaticRuleAnalyzer and DynamicRuleAnalyzer.

Returns

self

show_rule_analysis_dynamic()

Display the results of dynamic rule analyses.

See DynamicRuleAnalyzer.

Returns

self

show_rule_analysis_static()

Display the results of static rule analyses.

See StaticRuleAnalyzer.

Returns

self

show_summary(do_header=True, n_groups=8, n_sites=8, n_rules=8, n_probes=8, end_line_cnt=0, 0)

Display simulation summary.

Parameters
  • do_header (bool) – Display header?

  • n_groups (int) – Maximum number of groups to be displayed.

  • n_sites (int) – Maximum number of groups to be displayed.

  • n_rules (int) – Maximum number of groups to be displayed.

  • n_probes (int) – Maximum number of groups to be displayed.

  • end_line_cnt (tuple[int,int]) – The number of endline characters before and after the summary.

Returns

self

exception pram.sim.SimulationConstructionError

Bases: Exception

exception pram.sim.SimulationConstructionWarning

Bases: Warning

pram.traj module

Contains trajectory and trajectory ensemble relevant code.

class pram.traj.ClusterInf(**kwargs)

Bases: object

Computational cluster information.

This info is cluster-specific.

get_args()
class pram.traj.Trajectory(sim=None, name=None, memo=None, ensemble=None, id=None)

Bases: object

A time-ordered sequence of system configurations that occur as the system state evolves.

Also called orbit. Can also be thought of as a sequence of points in the system’s phase space.

This class delegates persistence management to the TrajectoryEnsemble class that also contains it.

This class keeps a reference to a simulation object, but that reference is only needed when running the simulation is desired. When working with an executed trajectory (i.e., the trace of past simulation run), ‘self.sim’ can be None. For example, the mass graph created by the Trajectory class is not based on an instatiated Simulation object even if that object has been used to generate the substrate data; instead, the database content is the graph’s basis.

Parameters
  • sim (Simulation) – The simulation.

  • name (str) – Trajectory name.

  • memo (str) – Trajectory memo.

  • ensemble (TrajectoryEnsemble) – The ensemble that contains this object.

  • id (Any) – The trajectory ensemble database ID of the trajectory.

_check_ens()

Ensure the trajectory is a part of an ensemble.

static comp_fft(y, T, N)

Compute Fast Fourier Transform (FFT).

Parameters
  • y (numpy.ndarray) – The signal.

  • T (float) – Nyquist sampling criterion.

  • N (int) – Sampling rate.

Returns

float

compact()

Compact the trajectory.

Returns

self

gen_agent(n_iter=- 1)

See TrajectoryEnsemble.gen_agent().

gen_agent_pop(n_agents=1, n_iter=- 1)

See TrajectoryEnsemble.gen_agent_pop().

gen_mass_graph()

See TrajectoryEnsemble.mass_graph().

get_signal(do_prob=False)

See TrajectoryEnsemble.get_signal().

get_sim()

Get the simulation wrapped by this object.

Returns

Simulation

get_time_series(group_hash)

See TrajectoryEnsemble.get_time_series().

load_sim()

Loads settings from the trajectory ensemble DB.

See TrajectoryEnsemble.load_sim().

Returns

self

plot_heatmap(size, fpath)

Plots heatmap.

Todo

Finish this method.

Parameters
  • size (tuple[int,int]) – The figure size.

  • fpath (str) – Destination filepath.

Returns

self

plot_mass_flow_time_series(scale=1.0, 1.0, filepath=None, iter_range=- 1, - 1, v_prop=False, e_prop=False)

See graph.MassGraph.plot_mass_flow_time_series().

plot_mass_locus_fft(size, filepath, iter_range=- 1, - 1, sampling_rate=1, do_sort=False, do_ret_plot=False)

See TrajectoryEnsemble.plot_mass_locus_fft().

plot_mass_locus_line(size, filepath, iter_range=- 1, - 1, stroke_w=1, col_scheme='set1', do_ret_plot=False)

See TrajectoryEnsemble.plot_mass_locus_line().

plot_mass_locus_recurrence(size, filepath, iter_range=- 1, - 1, neighbourhood=pyrqa.neighbourhood.FixedRadius, embedding_dimension=1, time_delay=2, do_ret_plot=False)

See TrajectoryEnsemble.plot_mass_locus_recurrence().

plot_mass_locus_scaleogram(size, filepath, iter_range=- 1, - 1, sampling_rate=1, do_sort=False, do_ret_plot=False)

See TrajectoryEnsemble.plot_mass_locus_scaleogram().

plot_mass_locus_spectrogram(size, filepath, iter_range=- 1, - 1, sampling_rate=None, win_len=None, noverlap=None, do_sort=False, do_ret_plot=False)

See TrajectoryEnsemble.plot_mass_locus_spectrogram().

plot_mass_locus_streamgraph(size, filepath, iter_range=- 1, - 1, do_sort=False, do_ret_plot=False)

See TrajectoryEnsemble.plot_mass_locus_streamgraph().

run(iter_or_dur=1)

Run the associated simulation.

See TrajectoryEnsemble.run().

Parameters

iter_or_dur (int or str) – Number of iterations or a string representation of duration (see util.Time.dur2ms())

Returns

self

save_sim()

Saves the associated simulation in the trajectory ensemble DB.

See TrajectoryEnsemble.save_sim().

Returns

self

save_state(mass_flow_specs=None)

Save settings to the trajectory ensemble DB.

See TrajectoryEnsemble.save_state().

Returns

self

set_id(id)

Loads trajectory ID from the trajectory ensemble DB.

Returns

self

class pram.traj.TrajectoryEnsemble(fpath_db=None, do_load_sims=True, cluster_inf=None, flush_every=16)

Bases: object

A collection of trajectories.

In mathematical physics, especially as introduced into statistical mechanics and thermodynamics by J. Willard Gibbs in 1902, an ensemble (also statistical ensemble) is an idealization consisting of a large number of virtual copies (sometimes infinitely many) of a system, considered all at once, each of which represents a possible state that the real system might be in. In other words, a statistical ensemble is a probability distribution for the state of the system.

For portability, SQLite3 is currently used RDBMS for trajectory ensemble database.

Database design notes:
  • While having a ‘traj_id’ field in the ‘grp_name’ table seems like a reasonable choice, a trajectory ensemble is assumed to hold only similar trajectories. Therefore, the ‘grp’ and ‘grp_name’ tables can simply be joined on the ‘hash’ field.

Parameters
  • fpath_db (str, optional) – Database filepath.

  • do_load_sims (bool) – Load simulations?

  • cluster_inf (ClusterInf, optional) – Computational cluster information.

  • flush_every (int) – Data flushing frequency in iterations.

FLUSH_EVERY = 16
SQL_CREATE_SCHEMA = "\n CREATE TABLE traj (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n ts DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,\n name TEXT,\n memo TEXT,\n sim BLOB\n );\n\n CREATE TABLE iter (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n ts DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,\n traj_id INTEGER,\n i INTEGER NOT NULL,\n host_name TEXT,\n host_ip TEXT,\n UNIQUE (traj_id, i),\n CONSTRAINT fk__iter__traj FOREIGN KEY (traj_id) REFERENCES traj (id) ON UPDATE CASCADE ON DELETE CASCADE\n );\n\n CREATE TABLE mass_locus (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n iter_id INTEGER,\n grp_id INTEGER,\n m REAL NOT NULL,\n m_p REAL NOT NULL,\n UNIQUE (iter_id, grp_id),\n CONSTRAINT fk__mass_locus__iter FOREIGN KEY (iter_id) REFERENCES iter (id) ON UPDATE CASCADE ON DELETE CASCADE,\n CONSTRAINT fk__mass_locus__grp FOREIGN KEY (grp_id) REFERENCES grp (id) ON UPDATE CASCADE ON DELETE CASCADE\n );\n\n CREATE TABLE mass_flow (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n iter_id INTEGER,\n grp_src_id INTEGER,\n grp_dst_id INTEGER,\n m REAL NOT NULL,\n m_p REAL NOT NULL,\n CONSTRAINT fk__mass_flow__iter FOREIGN KEY (iter_id) REFERENCES iter (id) ON UPDATE CASCADE ON DELETE CASCADE,\n CONSTRAINT fk__mass_flow__grp_src FOREIGN KEY (grp_src_id) REFERENCES grp (id) ON UPDATE CASCADE ON DELETE CASCADE,\n CONSTRAINT fk__mass_flow__grp_dst FOREIGN KEY (grp_dst_id) REFERENCES grp (id) ON UPDATE CASCADE ON DELETE CASCADE\n );\n\n CREATE TABLE grp (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n --hash INTEGER NOT NULL UNIQUE, -- SQLite3 doesn't support storing 64-bit integers\n hash TEXT NOT NULL UNIQUE,\n attr BLOB,\n rel BLOB\n );\n\n CREATE TABLE grp_name (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n ord INTEGER,\n hash TEXT NOT NULL UNIQUE,\n name TEXT NOT NULL\n );\n "
WEBDRIVER = 'chrome'
_db_conn_open(fpath_db=None, do_load_sims=True)

Opens the DB connection and, if the file exists already, populates the trajectories dictionary with those from the DB.

Parameters
  • fpath_db (str, optional) – Database filepath.

  • do_load_sims (bool) – Load simulations?

add_trajectories(traj)

Add trajectories.

Parameters

traj (Iterable[Trajectory]) – The trajectories.

Returns

self

add_trajectory(t)

Add a trajectory.

For convenience, t can be either a Trajectory or Simulation class instance. In the latter case, a Trajectory object will automatically be created with the default values.

Parameters

t (Trajectory or Simulation) – The trajectory or the simulation that should wrapped by a trajectory.

Returns

self

clear_group_names()

Removes group names from the trajectory ensemble database.

Returns

self

compact()

Compact the ensemble.

Returns

self

gen_agent(traj, n_iter=- 1)

Generate a single agent’s group transition path based on population-level mass dynamics that a PRAM simulation operates on.

This is a two-step process:

  1. Pick the agent’s initial group respecting the initial mass distribution among the groups

  2. Pick the next group respecting transition probabilities to all possible next groups

Because step 1 always takes place, the resulting list of agent’s states will be of size n_iter + 1.

Parameters
  • traj (Trajectory) – The trajectory to use.

  • n_iter (int) – Number of iterations to generate (use -1 for as many as many iterations there are in the trajectory).

Returns

A dictionary with two keys, attr and rel which correspond to the

attributes and relations of the PRAM group that agent would be a part of if it were in a PRAM model.

Return type

Mapping[str, Mapping[str, Any]]

gen_agent_pop(traj, n_agents=1, n_iter=- 1)

Generate a agent population based on procedure described in gen_agent().

Parameters
  • traj (Trajectory) – The trajectory to use.

  • n_agents (int) – Size of resulting agent population.

  • n_iter (int) – Number of iterations to generate (use -1 for as many as many iterations there are in the trajectory).

Returns

Each item is a dict with two keys, attr and rel which

correspond to the attributes and relations of the PRAM group that agent would be a part of if it were in a PRAM model.

Return type

Iterable[Mapping[str, Mapping[str, Any]]]

gen_mass_graph(traj)

Generate a mass graph.

Parameters

traj (Trajectory) – The trajectory being the graph’s basis.

Returns

MassGraph

get_signal(traj, do_prob=False)

Get time series of masses (or proportions of total mass) of all groups.

Parameters
  • traj (Trajectory) – The trajectory.

  • do_prob (bool) – Do proportions of total mass?

Returns

Signal

get_time_series(traj, group_hash)

Get a time series of group mass dynamics.

Parameters
Returns

sqlite3.Row

load_sim(traj)

Load simulation for the designated trajectory from the ensemble database.

Parameters

traj (Trajectory) – The trajectory.

Returns

self

load_sims()

Load simulations for all ensemble trajectories from the ensemble database.

Parameters

traj (Trajectory) – The trajectory.

Returns

self

normalize_iter_range(range=- 1, - 1, qry_n_iter='SELECT MAX(i) FROM iter', qry_args=[])
Parameters
  • range (tuple[int,int]) – The range of values.

  • qry_n_iter (str) – SQL query for obtaining total number of iterations.

  • qry_args (Iterable[str]) – The SQL query arguments.

Returns

tuple[int,int]

plot_mass_locus_bubble(size, filepath, iter_range=- 1, - 1, do_ret_plot=False)

Generate a mass locus bubble plot.

Todo

Finish implementing.

plot_mass_locus_fft(traj, size, filepath, iter_range=- 1, - 1, sampling_rate=1, do_ret_plot=False)

Generate a plot of mass locus Fast Fourier Transform.

Parameters
  • traj (Trajectory) – The trajectory.

  • size (tuple[int,int]) – Figure size.

  • filepath (str) – Destination filepath.

  • iter_range (tuple[int,int]) – Range of iterations.

  • sampling_rate (int) – Sampling rate.

  • do_ret_plot (bool) – Return plot? If False, self is returned.

Returns

self if do_ret_plot is False; altair chart object otherwise.

plot_mass_locus_line(size, filepath, iter_range=- 1, - 1, traj=None, n_traj=0, opacity_min=0.1, stroke_w=1, col_scheme='set1', do_ret_plot=False)

Generate a mass locus line plot (individual series).

Parameters
  • size (tuple[int,int]) – Figure size.

  • filepath (str) – Destination filepath.

  • iter_range (tuple[int,int]) – Range of iterations.

  • traj (Trajectory, optional) – The trajectory. If None, n_traj trajectories will be plotted.

  • n_traj (int) – Number of trajectories to sample from the ensemble. All trajectories will be plotted if the value is non-positive or if it exceeds the total number of trajectories in the ensemble.

  • opacity_min (float) – Minimum line opacity. Actual opacity value is scaled by the number of trajectories plotted; the more there are, the more transparent the lines will be.

  • stroke_w (float) – Line width.

  • col_scheme (str) – Color scheme name.

  • do_ret_plot (bool) – Return plot? If False, self is returned.

Returns

self if do_ret_plot is False; altair chart object otherwise.

plot_mass_locus_line_aggr(size, filepath, iter_range=- 1, - 1, band_type='ci', stroke_w=1, col_scheme='set1', do_ret_plot=False)

Generate a mass locus line plot (aggregated).

Parameters
  • size (tuple[int,int]) – Figure size.

  • filepath (str) – Destination filepath.

  • iter_range (tuple[int,int]) – Range of iterations.

  • band_type (str) – Band type.

  • stroke_w (float) – Line width.

  • col_scheme (str) – Color scheme name.

  • do_ret_plot (bool) – Return plot? If False, self is returned.

Returns

self if do_ret_plot is False; altair chart object otherwise.

plot_mass_locus_line_probe(size, filepath, probe_name, series, iter_range=- 1, - 1, traj=None, n_traj=0, opacity_min=0.1, stroke_w=1, col_scheme='set1', do_ret_plot=False)

Generate a mass locus line plot (probe).

Parameters
  • size (tuple[int,int]) – Figure size.

  • filepath (str) – Destination filepath.

  • probe_name (str) – The probe’s name.

  • series (Iterable[Mapping[str,str]]) – Series to be plotted from the ones recorded by the probe. Each series is a dict with two keys, var and lbl. The first selects the variable to be plotted while the seconds controls its name on the plot.

  • iter_range (tuple[int,int]) – Range of iterations.

  • traj (Trajectory, optional) – The trajectory. If None, n_traj trajectories will be plotted.

  • n_traj (int) – Number of trajectories to sample from the ensemble. All trajectories will be plotted if the value is non-positive or if it exceeds the total number of trajectories in the ensemble.

  • opacity_min (float) – Minimum line opacity. Actual opacity value is scaled by the number of trajectories plotted; the more there are, the more transparent the lines will be.

  • stroke_w (float) – Line width.

  • col_scheme (str) – Color scheme name.

  • do_ret_plot (bool) – Return plot? If False, self is returned.

Returns

self if do_ret_plot is False; altair chart object otherwise.

plot_mass_locus_polar(size, filepath, iter_range=- 1, - 1, n_traj=0, n_iter_per_rot=0, do_ret_plot=False)

Generate a mass locus polar plot.

Note

Altair does not currently support projections, so we have to use matplotlib.

Parameters
  • size (tuple[int,int]) – Figure size.

  • filepath (str) – Destination filepath.

  • iter_range (tuple[int,int]) – Range of iterations.

  • n_traj (int) – Number of trajectories to sample from the ensemble. All trajectories will be plotted if the value is non-positive or if it exceeds the total number of trajectories in the ensemble. plotted; the more there are, the more transparent the lines will be.

  • n_iter_per_rot (int) – Number of iterations that one rotation should comprise. If zero, it gets determined automatically based on iter_range.

  • do_ret_plot (bool) – Return plot? If False, self is returned.

Returns

self if do_ret_plot is False; matplotlib figure object otherwise.

plot_mass_locus_recurrence(traj, size, filepath, iter_range=- 1, - 1, neighbourhood=pyrqa.neighbourhood.FixedRadius, embedding_dimension=1, time_delay=2, do_ret_plot=False)

Generate a mass locus recurrence plot.

See PyRQA for information on parameterizing the plot.

Todo

Implement multivariate extensions of recurrence plots (including cross recurrence plots and joint recurrence plots).

Parameters
  • traj (Trajectory) – The trajectory.

  • size (tuple[int,int]) – Figure size.

  • filepath (str) – Destination filepath.

  • iter_range (tuple[int,int]) – Range of iterations.

  • neighbourhood (pyrqa.abstract_classes.AbstractNeighbourhood) – Neighbourhood condition.

  • embedding_dimension (int) – Embedding dimension.

  • time_delay (int) – Time delay.

  • do_ret_plot (bool) – Return plot? If False, self is returned.

Returns

self if do_ret_plot is False; pyrqa RPComputation object otherwise.

plot_mass_locus_scaleogram(traj, size, filepath, iter_range=- 1, - 1, sampling_rate=1, do_ret_plot=False)

Generate a mass locus scalegram.

Currently, Image Mark in not supported in Vega-Lite. Consequently, raster images cannot be displayed via Altair. The relevant issue is: https://github.com/vega/vega-lite/issues/3758

Parameters
  • traj (Trajectory) – The trajectory.

  • size (tuple[int,int]) – Figure size.

  • filepath (str) – Destination filepath.

  • iter_range (tuple[int,int]) – Range of iterations.

  • sampling_rate (int) – Sampling rate.

  • do_ret_plot (bool) – Return plot? If False, self is returned.

Returns

self if do_ret_plot is False; matplotlib figure object otherwise.

plot_mass_locus_spectrogram(traj, size, filepath, iter_range=- 1, - 1, sampling_rate=None, win_len=None, noverlap=None, do_ret_plot=False)

Generate a mass locus spectrogram (Short-Time Fourier Transform).

Parameters
  • traj (Trajectory) – The trajectory.

  • size (tuple[int,int]) – Figure size.

  • filepath (str) – Destination filepath.

  • iter_range (tuple[int,int]) – Range of iterations.

  • sampling_rate (int) – Sampling rate.

  • win_len (int) – Length of the windowing segments.

  • noverlap (int) – Windowing segment overlap.

  • do_ret_plot (bool) – Return plot? If False, self is returned.

Returns

self if do_ret_plot is False; matplotlib figure object otherwise.

plot_mass_locus_streamgraph(traj, size, filepath, iter_range=- 1, - 1, do_ret_plot=False)

Generate a mass locus steamgraph.

Parameters
  • traj (Trajectory) – The trajectory.

  • size (tuple[int,int]) – Figure size.

  • filepath (str) – Destination filepath.

  • iter_range (tuple[int,int]) – Range of iterations.

  • do_ret_plot (bool) – Return plot? If False, self is returned.

Returns

self if do_ret_plot is False; altair chart object otherwise.

run(iter_or_dur=1)

Run the ensemble.

The ensemble will be executed on a computational cluster if the cluster info has been associated with it or sequentially otherwise.

Parameters

iter_or_dur (int or str) – Number of iterations or a string representation of duration (see util.Time.dur2ms())

Returns

self

run__par(iter_or_dur=1)

Run the ensemble on a computational cluster.

Parameters

iter_or_dur (int or str) – Number of iterations or a string representation of duration (see util.Time.dur2ms())

Returns

self

run__seq(iter_or_dur=1)

Run the ensemble sequentially.

Parameters

iter_or_dur (int or str) – Number of iterations or a string representation of duration (see util.Time.dur2ms())

Returns

self

save_groups(sim, iter_id, conn)

Persist all groups of the designated simulation and iteration in the trajectory ensemble database.

Note

Currently unused.

Parameters
  • traj_id (int or str) – The trajectory’s database ID.

  • iter (int) – Iteration.

  • host_name (str) – Name of host executing the iteration.

  • host_ip (str) – IP address of host executing the iteration.

  • conn (sqlite.Connection) – The SQLite3 connection object.

Returns

self

save_iter(traj_id, iter, host_name, host_ip, conn)

Persist the simulation associated with the designated trajectory in the trajectory ensemble database.

Parameters
  • traj_id (int or str) – The trajectory’s database ID.

  • iter (int) – Iteration.

  • host_name (str) – Name of host executing the iteration.

  • host_ip (str) – IP address of host executing the iteration.

  • conn (sqlite3.Connection) – The SQLite3 connection object.

Returns

Iteration database ID.

Return type

int

save_mass_flow(iter_id, mass_flow_specs, conn)

Persist the mass flow in the designated simulation and iteration in the trajectory ensemble database.

Mass flow is present for all but the initial state of a simulation.

Note

This method has to be called after either save_mass_locus__seq() or save_mass_locus__par() which add all the groups to the ensemble database.

Parameters
  • iter_id (int or str) – Iteration database ID.

  • mass_flow_specs (MassFlowSpec) – Mass flow specs.

  • conn (sqlite3.Connection) – The SQLite3 connection object.

Returns

self

save_mass_locus__par(pop_m, groups, iter_id, conn)

Persist all new groups (and their attributes and relations) as well as masses of all groups participating in the designated iteration (parallelized execution).

Note

This method has to be called before save_mass_flow() to ensure all groups are already present in the database.

Todo

Currently, group attributes and relations aren’t added to the database. This is to increase network bandwidth. Should there be another actor responsible for collecting all group info and adding them to the database at the end of an ensemble execution?

Parameters
  • pop_m (float) – Total population mass.

  • groups (Iterable[Mapping[str,Any]]) – Each item is a dict with keys hash, m, attr, and rel.

  • iter_id (int or str) – Iteration database ID.

  • conn (sqlite3.Connection) – The SQLite3 connection object.

Returns

self

save_mass_locus__seq(pop, iter_id, conn)

Persist all new groups (and their attributes and relations) as well as masses of all groups participating in the designated iteration (sequential execution).

Note

This method has to be called before save_mass_flow() to ensure all groups are already present in the database.

Parameters
  • pop (GroupPopulation) – The group population.

  • iter_id (int or str) – Iteration database ID.

  • conn (sqlite3.Connection) – The SQLite3 connection object.

Returns

self

save_sim(traj)

Persist the simulation associated with the designated trajectory in the trajectory ensemble database.

Parameters

traj (Trajectory) – The trajectory.

Returns

self

save_sims()

Persist simulations associated with all ensemble trajectories in the trajectory ensemble database.

Returns

self

save_work(work)

Persist payload delivered by a remote worker.

Two types of payload are persisted: Simulation state or probe-recorded information. Those payloads are delivered as dictionaries in the following formats:

{ 'type': 'state', 'host_name': '...', 'host_ip': '...', 'traj_id': 3, 'iter': 4, 'pop_m': 10, 'groups': [...], 'mass_flow_specs': MassFlowSpec(...) }
{ 'type': 'probe', 'qry': '...', 'vals': ['...', ...] }
Parameters

work (Iterable[Mapping[str,Any]]) – The payload.

Returns

self

set_group_name(ord, name, hash)

Set one group hash-to-name association.

If names are present in the trajectory ensemble database, they will be used when plotting or exporting mass dynamics time series.

Parameters
  • ord (int) – Desired ordinal number of the group.

  • name (str) – Name.

  • hash (int or str) – Hash. The best way to obtain a hash is by calling Group.get_hash()

Returns

self

set_group_names(ord_name_hash)

Set multiple group hash-to-name associations.

If names are present in the trajectory ensemble database, they will be used when plotting or exporting mass dynamics time series.

Parameters

ord_name_hash (Iterable[tuple[int,str,int or str]]) – Each item is a tuple corresponding to the arguments of the set_group_name>() method.

Returns

self

set_pragma_memoize_group_ids(value)

Set value of the memoize_group_ids pragma.

Group databased IDs can be memoized (i.e., kept in memory). That yields faster ensemble runs, especially that ensembles share group IDs because they are assumed to contain similar trajectories. The downside is increased memory utilization.

Parameters

value (bool) – The value.

Returns

self

show_stats()

Display ensemble statistics.

Returns

self

exception pram.traj.TrajectoryError

Bases: Exception

pram.util module

Contains utilities code.

class pram.util.DB

Bases: abc.ABC

Database interface base class.

PATT_VALID_NAME = re.compile('^[a-zA-Z][a-zA-Z0-9_]*$')
VALID_CHARS = '_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
static blob2obj(b, do_decompress=True)
exec(qry)
exec_get(qry)
abstract get_cols(schema, tbl)
abstract get_fk(schema, tbl, col_from)

Get the foreign key constraint for the specified table and column.

abstract get_id(tbl, col='rowid', where=None)
abstract get_name()
abstract get_new_conn()
abstract get_num(tbl, col, where=None)
get_row_cnt(tbl, where=None)
static obj2blob(o, do_compress=True)
open_conn()
static str_to_name(s, do_raise_on_empty=True)
abstract str_to_type()
class pram.util.DB_FK(schema_from, schema_to)

Bases: tuple

schema_from

Alias for field number 0

schema_to

Alias for field number 1

class pram.util.Data

Bases: object

Data utilities.

static rand_bin_lst(n)
static rand_float_lst(l, u, n)
class pram.util.Err

Bases: object

static type(arg, arg_name, type, can_be_none=False)

Raises a TypeError exception if the argument isn’t of the required type. Returns ‘True’ which enables it to be used as a logical condition.

class pram.util.FS

Bases: object

Filesystem utilities.

static bz2(fpath_src, fpath_dst=None, compress_lvl=9, do_del=False)
static bz2_decomp(fpath_src, fpath_dst=None, do_del=False)
static dir_mk(path)
static gz(fpath_src, fpath_dst=None, compress_lvl=9, do_del=False)
static gz_decomp(fpath_src, fpath_dst=None, do_del=False)
static load(fpath, mode='r')
static load_bz2(fpath)
static load_gz(fpath)
static load_or_gen(fpath, fn_gen, name='data', is_verbose=False, hostname_gen={})

If the ‘fpath’ file exists, it is ungzipped and unpickled. If it does not exist, ‘fn_gen()’ is called and the result is pickled and gzipped in ‘fpath’ and returned. Name can be redefined for customized progress messages. No filesystem interactions are made if ‘fpath’ is None.

Generation of the data can be restricted to a set of machines designated by hostname.

static req_file(fpath, msg)
static save(fpath, data, mode='w', compress_lvl=9)
static save_bz2(fpath, data, compress_lvl=9)
static save_gz(fpath, data, compress_lvl=9)
class pram.util.MPCounter(val_init=0)

Bases: object

Fixes issues with locking of multiprocessing’s Value object.

Source: eli.thegreenplace.net/2012/01/04/shared-counter-with-pythons-multiprocessing

dec()
inc()
value()
class pram.util.PgDB(host, port, usr, pwd, db, cursor_factory=psycopg2.extras.DictCursor)

Bases: pram.util.DB

PostgreSQL database interface.

get_cols(schema, tbl)
get_fk(schema, tbl, col_from)

Get the foreign key constraint for the specified table and column.

get_id(tbl, col='rowid', where=None)
get_name()
get_new_conn()
get_num(tbl, col, where=None)
static str_to_type(s)
class pram.util.SQLiteDB(fpath)

Bases: pram.util.DB

SQLite3 database interface.

get_cols(schema, tbl)
get_fk(schema, tbl, col_from)

Get the foreign key constraint for the specified table and column.

get_id(tbl, col='rowid', where=None)
get_name()
get_new_conn()
get_num(tbl, col, where=None)
static str_to_type(s)
class pram.util.Size

Bases: object

File size utilities.

PREFIX_BIN = {'E': 1152921504606846976, 'G': 1073741824, 'K': 1024, 'M': 1048576, 'P': 1125899906842624, 'T': 1099511627776, 'Y': 1208925819614629174706176, 'Z': 1180591620717411303424}
PREFIX_DEC = {'E': 1000000000000000000, 'G': 1000000000, 'K': 1000, 'M': 1000000, 'P': 1000000000000000, 'T': 1000000000000, 'Y': 1000000000000000000000000, 'Z': 1000000000000000000000}
static b2h(b, do_bin=True, dec_places=1, do_ret_tuple=False)
static bytes2human(b, do_bin=True, dec_places=1, do_ret_tuple=False)
static get_size(obj0)

https://stackoverflow.com/questions/449560/how-do-i-determine-the-size-of-an-object-in-python/30316760#30316760

class pram.util.Str

Bases: object

String utilities.

static float(s)

Formats a string containing a floating point number to suppress scientific notation and strip trailing zeros.

class pram.util.Tee(fname, fmode='a')

Bases: object

Script output forker.

When instantiated, this class writes the output of the script to stdout and to a file at the same time (much like the UNIX command line utility by the same name).

end()
flush()
write(data)
class pram.util.Time

Bases: object

Time utilities.

POSIX (or UNIX) time (i.e., Jan 1, 1970) is the point of reference for this class.

All timestamps and datetime differences default to milliseconds (as opposed to seconds, which is what the datetime module seems to prefer).

DOTW_NUM2STR = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
PATT_STR_DUR = re.compile('^(\\d+)\\s*(\\w+)$')
POSIX_DT = datetime.datetime(1970, 1, 1, 0, 0)
POSIX_TS = datetime.datetime(1970, 1, 1, 0, 0)
static day_of_year_to_dt(year, day, format=None)
static diff(dt_0, dt_1, do_ms=True)

Difference between two datetime objects (‘dt_0’ being the earlier one). There is no point in providing a ‘diff’ method for timestamps because being floats they can simply be subtracted.

static diffs(dt_0, dt_1, do_ms=True)

Casts the return of diff() to string.

This method is useful because it guarantees a proper formatting of the resulting float (i.e., no scientific notation and trailing zeros stripped) making it a good choice for the purpose of display, log, etc.

static dotw(dt)

String short name of day-of-the-week.

static dt()

Datetime now.

static dt2ts(dt, do_ms=True)

Datetime to timestamp.

static dur2ms(s)
static sec2time(sec, n_msec=0)

Convert seconds to ‘D days, HH:MM:SS.FFF’

References

  • stackoverflow.com/questions/775049/python-time-seconds-to-hms

  • humanfriendly.readthedocs.io/en/latest/#humanfriendly.format_timespan

  • stackoverflow.com/questions/41635547/convert-python-datetime-to-timestamp-in-milliseconds/41635888

  • datetime.datetime.fromtimestamp(self.pop.sim.last_iter.t).strftime(‘%H:%M:%S.%f’)

static ts(do_ms=True)

Timestamp now.

static ts2dt(dt, is_ts_ms=True)

Timestamp to datetime.

static ts_sec(sec, do_ms=True)

Timestamp at the specified number of seconds.

static tsdiff2human(ts_diff, do_print_ms=True)

Convert timestamp difference to ‘D days, HH:MM:SS.FFF’.

Module contents