qprsim


Nameqprsim JSON
Version 0.2.0 PyPI version JSON
download
home_pageNone
SummaryNone
upload_time2024-04-04 13:17:10
maintainerNone
docs_urlNone
authorLeah Tacke genannt Unterberg
requires_python<4.0,>=3.11
licenseMIT
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            ## QPRsim
_Queueing Processes with Resources Simulator_

This is a package for discrete-event simulation of traditional as well as object-centric event logs.
Generated logs can be converted to and exported in XES or OCEL 2.0 format respectively.
It is based on the interaction of a global event queue and a graph structure which controls the flow of cases/objects.
Activities use an internal queue which along with strict respecting of resource capacities enables waiting times and cascading dynamics to emerge.  
The event system uses discrete time steps but produces real timezone-aware time stamps. It also makes 'business hours', i.e., periodic availability variation a key aspect of arrival processes, activities and resources. 
There is also rudimentary what-if capability implemented via an interface with which users can schedule points in simulation-time when activity/resource/object birthplace properties are changed or arrival processes added/swapped/removed. 

The philosophy of the component structure is that the control flow is separated from the logic of its nodes which is separated from its configuration.
This is to keep everything as flexible as possible and particularly to make the configuration easily exchangeable.
Furthermore, configurable parameters are separated from their base implementations, to facilitate the quick development of new, more complex, key parameters like processing time samplers, routing classifiers, queueing discipline, etc.
Any of these can be extended by subclassing the appropriate base classes.
This is reflected in the package structure. Each main package _core_, _model_, _config_ and _execution_ is set up for traditional event log simulation, while the sub-packages '.oc' include the object-centric versions of components where they have to differ. 

- [qprsim.core[.oc]](src/qprsim/core) contains the deep internals like the event system and case/object definitions.
- [qprsim.model[.oc]](src/qprsim/model) contains the simulation graph and models. The configurable properties of the models are also declared here, i.e., the queueing discipline of an activity.
- [qprsim.config[.oc]](src/qprsim/config) contains configuration classes for each of the models which bundle all the aforementioned properties/parameters. This package also contains the reference/base implementations of these properties. 
- [qprsim.execution[.oc]](src/qprsim/execution) contains the simulation 'builder' itself that applies a given configuration to a model to synthesize a complete simulation model. In contrast to a graph or model configuration, which are more-or-less immutable, a packed simulation model is use-once and contains all the state that emerges during simulation, i.e, created cases/objects and events. This package also contains the _ButWhatIf_ functionality mentioned before. 
- [qprsim.utils](src/qprsim/utils) contains miscellaneous utility functions used in the above packages. Worth mentioning are the _time_utils_ which can ease working with timezone aware datetimes.

The defined package imports are setup such that by importing from the config and execution packages, you get most of everything you might need to set up a simulation.
Additionally, the sub package _impls_ of _config_ bundles all reference parameter implementations which can be used to populate the configuration.

```
from qprsim.config[.oc] import *
from qprsim.execution[.oc] import *
from qprsim.config import impls
```
There are also classes prefixed by ```Lambda``` which can wrap any user defined function with the correct signature to easily externalize logic to the user.  
Throughout the tool, we make ample usage of ```**kwargs``` to pass optional information to, in particular, parameter implementations.
Though it can be a bit 'dangerous' to use not statically existence-checked arguments, they provide a way pass around optional objects.
Advanced users can also thus slightly more easily adapt the simulation software itself by passing required objects via these keyword arguments.  

### Usage
There are three sample simulation setups included in this repository.
- [traditional_test](sample/traditional_test.py). In these tests are ultra-basic toy configurations of traditional event log simulations. 
- [ocel_sample](sample/ocel_sample.py). This is the first object-centric simulation setup showcasing a basic process and how to work with object creation, routing and attribute access.
- [udonya](sample/udonya.ipynb). Based on a previous version of this package, this setup showcases all the ways the traditional event log simulation can be used and abused to create interesting dynamics.

As a brief example, the following is a code snippet shows how one can define an 'object birthplace' node which creates objects of type _my_object_type_.
A caveat is that even object attribute initializations have to have a timestamp due to the OCEL 2.0 specification. 

```
mb = ModelBuilder()

def object_creation(object_id: obd.ObjectId, time, **kwargs):
    return obd.Object.with_initial_attributes(object_id, 'my_object_type', initialization_timestamp=time,
                                              my_attribute='Hello')

birthplace = mb.add_birthplace('my_birthplace', ObjectBirthplaceConfig('my_object_type', ocpi.LambdaObjectCreator('my_object_type', object_creation)))
```

### Simulation Models

Simulation models can be built manually using the ModelBuilder. It provides a somewhat simple interface to populate a _simulation graph_ and _model configuration_ object.
The simulation graph is (sadly) not Petri net based but rather a simplified and recursively defined "push-forward" graph.
The idea is that in arrival/birthplace nodes, control-flow tokens enter into the system and are then routed by the graph nodes to a terminal/graveyard node.

The control-flow object in traditional simulation is straightforwardly a case to which activities add events. Routing to different terminal nodes allows simulation of different "types" of cases that still interact, and most importantly, share resources but still end up in separate event logs.
This can be used to simulate cancelled/abandoned cases.
For object-centric simulation, so-called _carrier_ objects are used. They represent (synchronized) sets of objects. They can be split and objects be added or removed from them.
Easily accessible synchronization of separate carrier "streams" is currently limited.

In contrast to Petri nets, there is no global synchronization (yet) on the graph level.
It is, however, a key aspect via the resource management system which strictly respects resource availability and capacity. 
Each node locally decides which successor(s) to route an incoming control-flow token to.
Though all executions are eager, the behavior of nodes can be dynamic:
- Activity nodes access the event system as well as resource management system to either wait a specified amount of time (delay, processing) or until a resource is available (waiting) before forwarding a control-flow token.
- AND split/join constructs wait until a control-flow token has arrived {number of splits}-times before forwarding.
- OC split/join constructs wait until all constituents of a carrier have arrived at the join before forwarding it. 
- Custom nodes can do anything. There are some building off-points and examples in the code, especially the latest traditional sim model extensions but this is advanced topic.

### Model Configuration

For traditional event log simulation, the basic relevant configurable items are:
- Arrival processes which are one-to-one connected to arrival nodes
  - business hours
  - inter arrival time sampler
  - creation count limit
  - initial case attribute generator
- Activities
  - business hours
  - queueing discipline
  - delay & processing time sampler
  - event attribute generator
  - (dangerous and requires extra, extra care) max queue size and discard-on-full handler 
- Resources
  - capacity
  - business hours
- Decision nodes
  - case classifier (decides which successor a case is routed to)
- Activity <=> Resource mapping
  - definition of assignable resources and their assignment propensity

For object-centric simulation they are:
- Arrival Processes which are connected to object birthplaces
  - business hours
  - inter arrival time sampler
  - target birthplaces
- Birthplaces
  - object type
  - object generator (decides initial attributes and o2o relations)
  - creation count limit
- Activities
  - business hours
  - queueing discipline
  - processing time sampler
  - event attribute generator
  - event object qualifier (decides which objects are linked to the event by which qualifier)
  - carrier attribute generator (can optionally override/add attributes to any involved objects)
- Resources
  - capacity
  - business hours
- Decision nodes
  - carrier classifier (decides which successor a carrier is routed to)
- Split nodes
  - carrier splitter (decides which objects within a carrier are routed to which successor)
- Transformation nodes
  - carrier generator (can generate any set of objects to be added to the carrier)
- Activity <=> Resource mapping
  - definition of assignable resources and their assignment propensity

All arrival, activity and resource properties can be scheduled to change within the simulation horizon via the _whatif_ functionality.

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "qprsim",
    "maintainer": null,
    "docs_url": null,
    "requires_python": "<4.0,>=3.11",
    "maintainer_email": null,
    "keywords": null,
    "author": "Leah Tacke genannt Unterberg",
    "author_email": "leah.tgu@pads.rwth-aachen.de",
    "download_url": "https://files.pythonhosted.org/packages/81/56/bbd36f6eefb77d243f62c982b743f0be527938b2c1278e56c385e19d3a41/qprsim-0.2.0.tar.gz",
    "platform": null,
    "description": "## QPRsim\n_Queueing Processes with Resources Simulator_\n\nThis is a package for discrete-event simulation of traditional as well as object-centric event logs.\nGenerated logs can be converted to and exported in XES or OCEL 2.0 format respectively.\nIt is based on the interaction of a global event queue and a graph structure which controls the flow of cases/objects.\nActivities use an internal queue which along with strict respecting of resource capacities enables waiting times and cascading dynamics to emerge.  \nThe event system uses discrete time steps but produces real timezone-aware time stamps. It also makes 'business hours', i.e., periodic availability variation a key aspect of arrival processes, activities and resources. \nThere is also rudimentary what-if capability implemented via an interface with which users can schedule points in simulation-time when activity/resource/object birthplace properties are changed or arrival processes added/swapped/removed. \n\nThe philosophy of the component structure is that the control flow is separated from the logic of its nodes which is separated from its configuration.\nThis is to keep everything as flexible as possible and particularly to make the configuration easily exchangeable.\nFurthermore, configurable parameters are separated from their base implementations, to facilitate the quick development of new, more complex, key parameters like processing time samplers, routing classifiers, queueing discipline, etc.\nAny of these can be extended by subclassing the appropriate base classes.\nThis is reflected in the package structure. Each main package _core_, _model_, _config_ and _execution_ is set up for traditional event log simulation, while the sub-packages '.oc' include the object-centric versions of components where they have to differ. \n\n- [qprsim.core[.oc]](src/qprsim/core) contains the deep internals like the event system and case/object definitions.\n- [qprsim.model[.oc]](src/qprsim/model) contains the simulation graph and models. The configurable properties of the models are also declared here, i.e., the queueing discipline of an activity.\n- [qprsim.config[.oc]](src/qprsim/config) contains configuration classes for each of the models which bundle all the aforementioned properties/parameters. This package also contains the reference/base implementations of these properties. \n- [qprsim.execution[.oc]](src/qprsim/execution) contains the simulation 'builder' itself that applies a given configuration to a model to synthesize a complete simulation model. In contrast to a graph or model configuration, which are more-or-less immutable, a packed simulation model is use-once and contains all the state that emerges during simulation, i.e, created cases/objects and events. This package also contains the _ButWhatIf_ functionality mentioned before. \n- [qprsim.utils](src/qprsim/utils) contains miscellaneous utility functions used in the above packages. Worth mentioning are the _time_utils_ which can ease working with timezone aware datetimes.\n\nThe defined package imports are setup such that by importing from the config and execution packages, you get most of everything you might need to set up a simulation.\nAdditionally, the sub package _impls_ of _config_ bundles all reference parameter implementations which can be used to populate the configuration.\n\n```\nfrom qprsim.config[.oc] import *\nfrom qprsim.execution[.oc] import *\nfrom qprsim.config import impls\n```\nThere are also classes prefixed by ```Lambda``` which can wrap any user defined function with the correct signature to easily externalize logic to the user.  \nThroughout the tool, we make ample usage of ```**kwargs``` to pass optional information to, in particular, parameter implementations.\nThough it can be a bit 'dangerous' to use not statically existence-checked arguments, they provide a way pass around optional objects.\nAdvanced users can also thus slightly more easily adapt the simulation software itself by passing required objects via these keyword arguments.  \n\n### Usage\nThere are three sample simulation setups included in this repository.\n- [traditional_test](sample/traditional_test.py). In these tests are ultra-basic toy configurations of traditional event log simulations. \n- [ocel_sample](sample/ocel_sample.py). This is the first object-centric simulation setup showcasing a basic process and how to work with object creation, routing and attribute access.\n- [udonya](sample/udonya.ipynb). Based on a previous version of this package, this setup showcases all the ways the traditional event log simulation can be used and abused to create interesting dynamics.\n\nAs a brief example, the following is a code snippet shows how one can define an 'object birthplace' node which creates objects of type _my_object_type_.\nA caveat is that even object attribute initializations have to have a timestamp due to the OCEL 2.0 specification. \n\n```\nmb = ModelBuilder()\n\ndef object_creation(object_id: obd.ObjectId, time, **kwargs):\n    return obd.Object.with_initial_attributes(object_id, 'my_object_type', initialization_timestamp=time,\n                                              my_attribute='Hello')\n\nbirthplace = mb.add_birthplace('my_birthplace', ObjectBirthplaceConfig('my_object_type', ocpi.LambdaObjectCreator('my_object_type', object_creation)))\n```\n\n### Simulation Models\n\nSimulation models can be built manually using the ModelBuilder. It provides a somewhat simple interface to populate a _simulation graph_ and _model configuration_ object.\nThe simulation graph is (sadly) not Petri net based but rather a simplified and recursively defined \"push-forward\" graph.\nThe idea is that in arrival/birthplace nodes, control-flow tokens enter into the system and are then routed by the graph nodes to a terminal/graveyard node.\n\nThe control-flow object in traditional simulation is straightforwardly a case to which activities add events. Routing to different terminal nodes allows simulation of different \"types\" of cases that still interact, and most importantly, share resources but still end up in separate event logs.\nThis can be used to simulate cancelled/abandoned cases.\nFor object-centric simulation, so-called _carrier_ objects are used. They represent (synchronized) sets of objects. They can be split and objects be added or removed from them.\nEasily accessible synchronization of separate carrier \"streams\" is currently limited.\n\nIn contrast to Petri nets, there is no global synchronization (yet) on the graph level.\nIt is, however, a key aspect via the resource management system which strictly respects resource availability and capacity. \nEach node locally decides which successor(s) to route an incoming control-flow token to.\nThough all executions are eager, the behavior of nodes can be dynamic:\n- Activity nodes access the event system as well as resource management system to either wait a specified amount of time (delay, processing) or until a resource is available (waiting) before forwarding a control-flow token.\n- AND split/join constructs wait until a control-flow token has arrived {number of splits}-times before forwarding.\n- OC split/join constructs wait until all constituents of a carrier have arrived at the join before forwarding it. \n- Custom nodes can do anything. There are some building off-points and examples in the code, especially the latest traditional sim model extensions but this is advanced topic.\n\n### Model Configuration\n\nFor traditional event log simulation, the basic relevant configurable items are:\n- Arrival processes which are one-to-one connected to arrival nodes\n  - business hours\n  - inter arrival time sampler\n  - creation count limit\n  - initial case attribute generator\n- Activities\n  - business hours\n  - queueing discipline\n  - delay & processing time sampler\n  - event attribute generator\n  - (dangerous and requires extra, extra care) max queue size and discard-on-full handler \n- Resources\n  - capacity\n  - business hours\n- Decision nodes\n  - case classifier (decides which successor a case is routed to)\n- Activity <=> Resource mapping\n  - definition of assignable resources and their assignment propensity\n\nFor object-centric simulation they are:\n- Arrival Processes which are connected to object birthplaces\n  - business hours\n  - inter arrival time sampler\n  - target birthplaces\n- Birthplaces\n  - object type\n  - object generator (decides initial attributes and o2o relations)\n  - creation count limit\n- Activities\n  - business hours\n  - queueing discipline\n  - processing time sampler\n  - event attribute generator\n  - event object qualifier (decides which objects are linked to the event by which qualifier)\n  - carrier attribute generator (can optionally override/add attributes to any involved objects)\n- Resources\n  - capacity\n  - business hours\n- Decision nodes\n  - carrier classifier (decides which successor a carrier is routed to)\n- Split nodes\n  - carrier splitter (decides which objects within a carrier are routed to which successor)\n- Transformation nodes\n  - carrier generator (can generate any set of objects to be added to the carrier)\n- Activity <=> Resource mapping\n  - definition of assignable resources and their assignment propensity\n\nAll arrival, activity and resource properties can be scheduled to change within the simulation horizon via the _whatif_ functionality.\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": null,
    "version": "0.2.0",
    "project_urls": null,
    "split_keywords": [],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "cf357b5ac57f7465d52c1f7013f6baefff755dc14d75efbe5764a9f85ed01917",
                "md5": "ff6088c2877830e9678ca6bcbaa25b0a",
                "sha256": "14aed70cdbc8eae3f3ac50fae900026901e426c868e071ef27bdc77648b87f2f"
            },
            "downloads": -1,
            "filename": "qprsim-0.2.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "ff6088c2877830e9678ca6bcbaa25b0a",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": "<4.0,>=3.11",
            "size": 77510,
            "upload_time": "2024-04-04T13:17:07",
            "upload_time_iso_8601": "2024-04-04T13:17:07.781513Z",
            "url": "https://files.pythonhosted.org/packages/cf/35/7b5ac57f7465d52c1f7013f6baefff755dc14d75efbe5764a9f85ed01917/qprsim-0.2.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "8156bbd36f6eefb77d243f62c982b743f0be527938b2c1278e56c385e19d3a41",
                "md5": "56d693a4a213073fe2e1073c62155cb2",
                "sha256": "1e425d7b48f848e3e57119d891356ee3f5ec8b56b98baa1cd28e050931c569da"
            },
            "downloads": -1,
            "filename": "qprsim-0.2.0.tar.gz",
            "has_sig": false,
            "md5_digest": "56d693a4a213073fe2e1073c62155cb2",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": "<4.0,>=3.11",
            "size": 243382,
            "upload_time": "2024-04-04T13:17:10",
            "upload_time_iso_8601": "2024-04-04T13:17:10.448445Z",
            "url": "https://files.pythonhosted.org/packages/81/56/bbd36f6eefb77d243f62c982b743f0be527938b2c1278e56c385e19d3a41/qprsim-0.2.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-04-04 13:17:10",
    "github": false,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "lcname": "qprsim"
}
        
Elapsed time: 0.44899s