Latest Threat Research:SANDWORM_MODE: Shai-Hulud-Style npm Worm Hijacks CI Workflows and Poisons AI Toolchains.Details
Socket
Book a DemoInstallSign in
Socket

bptk-py

Package Overview
Dependencies
Maintainers
1
Versions
109
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

bptk-py - npm Package Compare versions

Comparing version
1.9.0
to
1.9.2
+1
bptk_py.egg-info/dependency_links.txt

Sorry, the diff of this file is not supported yet

Metadata-Version: 2.1
Name: bptk-py
Version: 1.9.2
Summary: A python simulation engine for System Dynamics & Agent based models
Author-email: transentis <support@transentis.com>
Maintainer-email: transentis <support@transentis.com>
Project-URL: Homepage, https://bptk.transentis.com
Project-URL: Documentation, https://bptk.transentis.com
Project-URL: Repository, https://github.com/transentis/bptk_py
Keywords: system dynamics,agent based modeling
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pandas==2.2.3
Requires-Dist: matplotlib==3.9.2
Requires-Dist: scipy==1.14.1
Requires-Dist: numpy==2.1.2
Requires-Dist: ipywidgets==8.1.5
Requires-Dist: pyyaml==6.0.1
Requires-Dist: xlsxwriter==3.1.9
Requires-Dist: parsimonious==0.10.0
Requires-Dist: xmltodict==0.12.0
Requires-Dist: jinja2==3.1.4
Requires-Dist: sympy==1.13.3
Requires-Dist: distlib==0.3.8
Requires-Dist: cachetools==5.5.0
Requires-Dist: requests==2.31.0
Requires-Dist: flask==3.0.3
Requires-Dist: jsonpickle==3.0.2
Provides-Extra: test
Requires-Dist: pytest; extra == "test"
# Business Prototyping Toolkit for Python
[![Coverage Status](https://coveralls.io/repos/github/transentis/bptk_py/badge.svg)](https://coveralls.io/github/transentis/bptk_py)
__System Dynamics and Agent-based Modeling in Python__
The Business Prototyping Toolkit for Python (BPTK-Py) is a computational modeling framework that enables you to build simulation models using System Dynamics (SD) and/or agent-based modeling (ABM) natively in Python and manage simulation scenarios with ease.
Next to providing the necessary SD and ABM language constructs to build simulation models directly in Python, the framework also includes a compiler for transpiling System Dynamics models conforming to the XMILE standard into Python code.
This means you can build models in a XMILE-compatible visual modeling environment (such as [Stella](https://www.iseesystems.com) or [iThink](https://www.iseesystems.com)) and then use them _independently_ in an Python environment.
The best way to get started with BPTK-Py is to read the [Quickstart](https://bptk.transentis.com/quickstart/quickstart.html) that is part ot the extensive [online documentation](https://bptk.transentis.com). The Quickstart provides a _single page_ overview of all the computational modeling techniques supported by BPTK.
## Main Features
* The objective of the framework is to let the modeller concentrate on building simulation models by providing a seamless interface for managing model settings and scenarios and for plotting simulation results.
* The BPTK-Py framework supports System Dynamics models in XMILE Format, native SD models using a domain-specific language for System Dynamics (SD DSL) and native Agent-based models. You can also build hybrid SD-ABM-Models natively in Python.
* All plotting is done using [Matplotlib](https://www.matplotlib.org).
* Simulation results are returned as [Pandas dataframes](https://pandas.pydata.org) and thus can easily be used for analytics.
* Model settings and scenarios are kept in JSON files. These settings are automatically loaded by the framework upon initialization, as are the model classes themselves. This makes interactive modeling, coding and testing very painless, especially if using the Jupyter notebook environment.
## Getting Help
BPTK-Py is developed and maintained by [transentis labs](https://www.transentis.com/business-prototyping-toolki/en/).
The first place to go to for help and installation instructions is the [online documentation](https://bptk.transentis.com).
The [Quickstart](https://bptk.transentis.com/quickstart/quickstart.html) provides a _single page_ overview of all the modeling techniques supported by BPTK.
The online documentation is generated from an extensive set of Jupyter notebooks, the __BPTK Tutorial__. The tutorial is available as a [git repository](https://github.com/transentis/bptk_py_tutorial) on GitHub.
Our [Business Prototyping Toolkit Meetup Group](https://www.transentis.com/business-prototyping-toolkit-meetup/en/) gathers online regularly. This is a good place to see BPTK in action, ask questions and suggest new features. We record every session and you can _view past recordings_ on the [meetup homepage](https://www.transentis.com/resources/business-prototyping-toolkit-meetup).
We used BPTK to build our implementation of the infamous [Beer Distribution Game](https://beergame.transentis.com).
Our [beergame repository](https://github.com/transentis/bptk_py_tutorial/tree/master/model_library/beergame) contains Jupyter notebooks that analyse the Beergame in-depth and also provides XMILE, SD DSL and Agent-based versions of the Beergame.
For any questions our suggestions you have regarding BPTK, please contact us at: [support@transentis.com](mailto:support@transentis.com).
## Changelog
### 1.9.2
* Fix to build script
### 1.9.1
* Bump versions of key dependencies
* Update XMILE parser grammar to remove depreciation warning
* Remove obsolete documentation files
* Update setup to use pyproject.toml
* Bump Python Version to 3.11
### 1.9.0
* BPTKServer: `run` endpoint now also works for agent-based models
* Model: Add `configure_agent`, `configure_properties` and `delete_agent(s)` methods
* Bump versions of key dependencies
### 1.8.0
* BPTKServer: Add new endpoint `start-instances` that starts multiple instances in one goo
### 1.7.6
* BPTK: Improve handling of floating point numbers when using small DTs
* ScenarioManagerSD: Fixed an issue that caused models with biflows to be cloned incorrectly
### 1.7.5
* BPTK: Fix that caused a crash when using multiple scenario files for hybrid models
### 1.7.4
* BPTK: Fix bug in reset_scenarios for Hybrid Scenario Managers
### 1.7.3
* BPTK: Update dependencies of Pandas/Matplotlib/Sympy/Parsimonious/Pyyaml/Xlsxwriter/Jinja2/Requests/Jsonpickle/Flask
* Successfully tested with Python 3.11
### 1.7.2
* BPTK: Fix imports of SimpleDashboard class
* BPTK: Update dependency of Scipy, Numpy and Pyyaml
### 1.7.1
* BPTK: reset_cache now also resets the data collector in agent based models
* BPTK: reset_cache calls the reset_cache method on all agents
* BPTK: agents now have a reset_cache method that can be used to reset agent state
* BPTK: Updated dependency on ipywidgets to 8.0.4
### 1.7.0
* BPTK Server: Remote authorization for root, full-metrics and metrics endpoints
* BPTK Server: Add /healthy endpoint
* BPTK Server: stop-instance and load-state are now POST resources
* Bug Fix: Remove debug print message
### 1.6.6
* BPTK: Defer import of matplotlib and ipywidgets until they are needed
### 1.6.5
* BPTK: Hybrid scenarios can now be spread accross multiple scenario files
* BPTK: Remove filename attribute from hybrid scenario manager as it is obsolete
* BPTK: Scenario definitions for SD DSL scenarios now accept a runspecs setting to override starttime, stoptime and dt
* BPTK: begin_session now accepts a settings parameter to override scenario settings
* BPTK Server: begin_session now accepts a settings parameter to override scenario settings
### 1.6.4
* BPTK Server: Simplified bearer token authentication
### 1.6.3
* BPTK Server: Added optional bearer token authentication
### 1.6.2
* BPTK Server: Fixed unsafe external state adapter code
* BPTK Server: start_instance now returns correct content type
### 1.6.1
* SimpleDashboard: Deleted superfluous import statement
* bptk: Small improvements to documentation
### 1.6.0
* BPTK Server: The run_step methods now also support agent-based models
* BPTK Server: A new endpoint streams_steps runs all the steps of a model and streams the results, especially useful for models that run for a long-time.
* SimpleDashboard: A new utility class that allows easy creation of dashboards based on Jupyter Widgets.
### 1.5.3
* BPTK Server: Since v 1.5.0, BPTK Server requires a Python version >= 3.9. The package now informs the user about this upon import. Other parts of the BPTK framework should work fine with older Python3 versions.
### 1.5.2
* BPTK Server: Added file adapter as a concrete example of an external adapter
* BPTK: Improve cleanup of resources when bptk instance is destroyed
### 1.5.1
* BPTK Server: Improvements to the new state externalisation feature
* BPTK Server: Improve cleanup of resources when an instance times out
### 1.5.0
* SD DSL: Added a new module class that makes it easy to structure large models
* BPTK Server: Add new endpoints to allow externalising the instance state
* BPTK Server: Changed the default timeout for equations for instances to 12h
### 1.4.3
* SD DSL: fix to delay function
### 1.4.2
* Small bugfixes in prometheus metrics.
### 1.4.1
* BPTK: Fix to plot_lookup
* BPTK Server: 'flat' version of session results
* SD DSL: small changes to SD functions pulse and delay to make them more robust.
### 1.4.0
* BPTK Server: add metrics endpoint
* SD DSL: fixed missing imports that caused some sddsl functions to throw an exception
### 1.3.12
* BPTK Server: fixed an issue that could lead to race conditions leading to server crashes
### 1.3.11
* BPTK Server: add a keep-alive method to keep instances from timing out
* BPTK Server: start-instances now accepts a timeout structure so that instance timeouts can be set flexibly.
* BPTK Server: fixed an issue that could lead to race conditions leading to server crashes
* XMILE: fixed an issue regarding lookups (graphical functions) that do not contain values on the x-axis
### 1.3.10
* BPTK: fixed an issue in train_scenarios which caused an exception in recent versions of bptk-py
### 1.3.9
* XMILE: Array arithmetic (such as array multiplication,...) within array functions such as SUM is now handled correctly.
### 1.3.8
* XMILE: Arrayed variables that have non-arrayed inputs with "apply to all" set are now handled correctly
### 1.3.7
* XMILE: Ensure the startime and stoptime in transpiled XMILE models are floating point values (e.g. 1.0, not 1)
* XMILE: Top level variables in a model that contains modules are now referenced correctly from submodules
* XMILE: Nested modules are now handled correctly
* XMILE: Array dimensions of length <3 are now handled correctly
### 1.3.6
* Add new method session_results to bptk and corresponding endpoint session-results to Bptk server that allows the session results so far to be retrieved.
### 1.3.5
* Fixed an issue that caused bptk-server to crash if start-instance was called after a previous instance had timed out
### 1.3.4
* Small improvements to the XMILE/SMILE parser regarding element names that include special characters and regarding operators surrounded by newlines.
### 1.3.3
* Return message from end-session resource now correctly reads "session terminated"
### 1.3.2
* Rename package due to issues with test pypi
### 1.3.1
* Add missing package in setup.py
### 1.3.0
* Fix bug in run_scenarios that arose with multiple scenario managers and when return_format was json or dict
* Add begin_session, end_session and run_step methods to bptk
* Add agent endpoint to BptkServer
* BptksServer now takes a bptk_factory function instead of a bptk object in its constructor
* Add start-instance endpoint to BptkServer
* Add begin-session, end-session and run-step endpoint to BptkServer
### 1.2.1
* Improve documentation
* Bugfix for bptk.export_scenarios
### 1.2.0
* Major tidy up of the bptk API, including a number of breaking changes. In particular the run_simulation method has been renamed to run_scenarios and reset_simulation_model was renamed to reset_scenario_cache. A number of rarely used methods have been removed.
* Documentation improved and extended.
* Internal refactoring.
### 1.1.27
* Fix bug in XMILE compiler regrading parsing of names that start with a keyword
### 1.1.26
* Fix bug in XMILE compiler that causes parsing of if/then/else structures to fail under some circumstances
* Fix bug in XMILE pulse function that causes the function to misbehave in some circumstances
* Fix bug in XMILE previous function that causes the function to misbehave in some circumstances
### 1.1.25
* Improve error handling and fault tolerance on BptkServer
### 1.1.24
* Update to BptkServer internals
### 1.1.23
* Add a new experimental feature that allows REST APIs for simulation models to be set up easily.
### 1.1.22
* SD DSL: Add python power operator (**) to all SD DSL operators
* XMILE: Ensure SAFEDIV works in complex expressions
### 1.1.21
* Improve handling of SAFEDIV in SD compiler
### 1.1.20
* Fix for the SD compiler regarding dimension names usage
### 1.1.19
* Little fix regarding the SD-Compiler
### 1.1.18
* Improvement of SD compiler: Support for empty initial value of ``DELAY`` function. Support for dimension names as arguments for functions (e.g. ``SIZE(<dimension>)``)
### 1.1.17
* Improvement of Extended Data Collector: Renamed to Agent Data Collector and code optimizations
### 1.1.16
* Bugfix for the plotting component that solves compatibility issues with newer versions of matplotlib
### 1.1.15
* New dataCollector for retrieving agent-wise data (Refer to [BPTK-Py Tutorial](https://github.com/transentis/bptk_py_tutorial) for more info)
### 1.1.14
* Fixed a bug in the interactive scenario component that caused scenarios being plotted multiple times
* Fixed a bug that caused the SD operator ``delay`` to not accept floating point values and fixed a bug that caused the same to be parsed incorrectly in some cases.
### 1.1.13
* Fixed a bug in the XMILE Converter that prevented the SAFEDIV operator to be parsed correctly
### 1.1.12
* SD-DSL: Fixed a bug that caused converter equations (subtraction and division) to be computed incorrectly.
### 1.1.11
* SD-DSL: Added support for right-hand side addition and subtraction to support equations such as ``converter.equation = 1 - b``
* Visualisation for SD-DSL elements now follows conventions to work properly with Matplotlib 3.3+
### 1.1.10
* Visualisation using matplotlib now follows conventions to work properly with Matplotlib 3.3+
### 1.1.9
* SD-DSL: System Dynamics element such as converters did not implement comparison operators (">", "<", ">=", "==", "!="). They have been added
### 1.1.8
* Another bugfix for series renaming. Simplified the code for renaming by using Pandas' standard method ``rename``
### 1.1.7
* Bugfix for ``plot_scenarios``: The ``series_names`` replacer did not work properly for when only one scenario manager / scenario is given.
### 1.1.6
* Bugfix for XMILE compiler: A little error in the parser prevented certain models being parsed correctly
* Bugfix for ``plot_scenarios``: The new error messages showed up for Agent based models although the scenarios were present
### 1.1.5
* The XMILE compiler is a great tool that handles model conversion from XMILE SD Models to Python. For compatibility and readability, we change the equation names to camelCasing upon conversion. This might be confusing for some users. That's why we decided to give you a new function call that lists all equations for System Dynamics Models. Simply run ``bptk.list_equations()`` (optionally add scenario manager(s) and scenario(s)) and get an overview over available model elements. More details [in our documentation](https://bptk.transentis.com/en/latest/docs/xmile/how-to/how_to_working_with_XMILE/how_to_working_with_XMILE.html).
* Improved error messages. In previous versions, a long error trace was printed when an equation was not found. Now you get a neat error message output wiht hints as to why the plotting failed.
* If an equation / scenario / scenario manager is not found, ``BPTK_Py`` gives hints on which similar equations / scenarios / scenario managers might be available for use.
* Register XMILE models without having to follow the directory structure: ``BPTK_PY`` scans the ``scenarios`` folder upon startup to find new scenario managers and XMILE / ABM models. We developed a simpler way to add simulation models during runtime without having to add scenarios beforehand: ``bptk.register_model("<path_to_itmx_stmx>","<modelname>")``. You can then easily simulate the model just as you're used to.
### 1.1.4
XMILE equations make use of double-quote enclosed identifiers in case it actually looks like a function call. For example, ``100*"Identifier(enclosed)"`` is a valid equation where one element (stock/flow) is called ``Identifier(enclosed)``. However, we were not able to parse this, until now.
Update BPTK-Py using the new update mechanism: [documentation](https://bptk.transentis.com/en/latest/docs/usage/installation.html#keeping-bptk-py-up-to-date)
### 1.1.3
We figured that the update mechanisms via ``pip`` might be confusing sometimes, especially for non-programmers. This is
why we decided to implement an update mechanism. Details are available in the [documentation](https://bptk.transentis.com/en/latest/docs/usage/installation.html#keeping-bptk-py-up-to-date)
### 1.1.2
* Bugfix to (XMILE) SD Compiler: Added support for array expressions within function calls. We had trouble with equations that contain another expression within a function call. E.g. ``DELAY(arrayedElement[1,2]*5, 1, 1)`` was not supported.
* Improvement to (XMILE) SD Compiler: Removed replacement of currency symbols (``€``, ``$`` etc.) and percentage signs with abbreviations. We had implemented this in earlier releases but figured it leads to confusion with modellers.
### 1.1.1
* The SD DSL now differentiates flows and biflows. Simply add a biflow using ```biflow = model.biflow(<name>)```.
* The SD DSL now supports: RANDOM, IF, NOT, AND, OR, NAN, SQRT, ROUND and all trigonometric and statistical builtins you know from XMILE. Furthermore the operators support Comparison Operators (>, <, >=, <=, ==, !=) and the modulo operator (x % y).
* RANDOM: ``converter.equation = sd.Random(<min>, <max>)`` draws a uniformly distributed float random number between <min> and <max>
* ROUND: ``converter.equation = sd.Round(sd.random(0,1),2))`` rounds a random number between 0 and 1 to a 2 digit float
* IF: ```converter.equation = sd.If( <condition>, <then> , <else> ) ``` corresponds to ```IF <condition> THEN <then> ELSE <else>```. Each term inside the IF clause can be a SD term again. Example for a valid If clause: ``equation = sd.If(sd.time()>10,sd.random(1,2), 100)``
* AND/OR: ```sd.Or(<left hand side>, <right hand side>)``` and ```sd.And(<left hand side>, <right hand side>)``` for multiple conditions
* NOT: Use ```sd.Not(<condition>)``` for "not" conditions, e.g: ```sd.If(sd.Not(sd.time()>10), 1, 0 )```
* NAN / INF / PI: ``sd.nan()`` returns a NAN value, ``sd.Inf()`` gives you the infinity value, ```sd.pi()``` returns the number pi.
* SQRT: ``sd.sqrt(<value of function>)`` computes the square root
* SIN / TAN / COS: ``sd.sin(x) / sd.cos(x) / sd.tan(x)`` for sinus, cosinus or tangent of x (radians) and of course we also support ARCCOS, ARCSIN, ARCTAN with the same syntax
* SINWAVE / COSWAVE: ``sd.sinwave(amplitude,period)`` / ``sd.coswave(amplitude,period)`` to generate sine / cosine waves with given amplitude and period
* More documentation and how to use the __statistical (random numbers from various distributions) and trigonometric operators__ can be found in our [online documentation](https://bptk.transentis.com/en/latest/docs/sd-dsl/in-depth/in_depth_sd_dsl_functions/in_depth_sd_dsl_functions.html)
* We fixed a bug that caused BPTK to crash when an XMILE model was updated while BPTK was monitoring it
* We fixed SINWAVE in the XMILE transpiler and added support for COSWAVE
### 1.1.0
* We are supporting all XMILE operators now. Note that random numbers with seed are **never** the same as when using Stella Architect's seed! This is due to different random number generators in Python and Stella. We neither support the min / max arguments for the random number operators. Refer to the [documentation](https://bptk.transentis.com/en/latest/docs/usage/limitations.html))
* RUNCOUNT and SENSIRUNCOUNT are not supported and support is not planned.
### 1.0.2
* Bugfix release: Better support for multidimensional arrays
### 1.0.1
* Bugfix release: Fixed an issue with plot_lookup
### 1.0.0
* SD Compiler: Added new operators
* Arrays and Array Operators (MIN, MAX, SUM, MEAN, SELF, SIZE, PROD)
* Statistical operators (COMBINATIONS, BETA, BINOMIAL, FACTORIAL, GAMMA, GAMMALN, EXPRND, GEOMETRIC)
* Trigonometric operators (ARCSIN, ARCCOS, ARCTAN)
* The ``plot_scenarios`` API now supports array calls such as ``stock[*]`` or ``stock[dim1,dim2]``
* SD DSL: ABS, DT, PULSE, STARTTIME, STOPTIME
pandas==2.2.3
matplotlib==3.9.2
scipy==1.14.1
numpy==2.1.2
ipywidgets==8.1.5
pyyaml==6.0.1
xlsxwriter==3.1.9
parsimonious==0.10.0
xmltodict==0.12.0
jinja2==3.1.4
sympy==1.13.3
distlib==0.3.8
cachetools==5.5.0
requests==2.31.0
flask==3.0.3
jsonpickle==3.0.2
[test]
pytest
LICENSE
README.md
pyproject.toml
setup.cfg
setup.py
BPTK_Py/__init__.py
BPTK_Py/bptk.py
BPTK_Py/config/__init__.py
BPTK_Py/config/config.py
BPTK_Py/exceptions/__init__.py
BPTK_Py/exceptions/exceptions.py
BPTK_Py/externalstateadapter/__init__.py
BPTK_Py/externalstateadapter/externalStateAdapter.py
BPTK_Py/logger/__init__.py
BPTK_Py/logger/logger.py
BPTK_Py/modeling/__init__.py
BPTK_Py/modeling/agent.py
BPTK_Py/modeling/dataCollector.py
BPTK_Py/modeling/event.py
BPTK_Py/modeling/model.py
BPTK_Py/modeling/scheduler.py
BPTK_Py/modeling/simultaneousScheduler.py
BPTK_Py/modeling/datacollectors/__init__.py
BPTK_Py/modeling/datacollectors/agent_datacollector.py
BPTK_Py/modeling/datacollectors/csv_datacollector.py
BPTK_Py/modeling/datacollectors/kinesis_datacollector.py
BPTK_Py/modelmonitor/__init__.py
BPTK_Py/modelmonitor/file_monitor.py
BPTK_Py/modelmonitor/model_monitor.py
BPTK_Py/modelparser/__init__.py
BPTK_Py/modelparser/json_model_parser.py
BPTK_Py/modelparser/meta_model_creator.py
BPTK_Py/modelparser/parser_factory.py
BPTK_Py/modelparser/yaml_model_parser.py
BPTK_Py/scenariomanager/__init__.py
BPTK_Py/scenariomanager/scenario.py
BPTK_Py/scenariomanager/scenario_manager.py
BPTK_Py/scenariomanager/scenario_manager_factory.py
BPTK_Py/scenariomanager/scenario_manager_hybrid.py
BPTK_Py/scenariomanager/scenario_manager_sd.py
BPTK_Py/scenariorunners/__init__.py
BPTK_Py/scenariorunners/hybrid_runner.py
BPTK_Py/scenariorunners/scenario_runner.py
BPTK_Py/scenariorunners/sd_runner.py
BPTK_Py/sdcompiler/compile.py
BPTK_Py/sdcompiler/sdmodel.py
BPTK_Py/sdcompiler/generator/__init__.py
BPTK_Py/sdcompiler/generator/contextBuilder.py
BPTK_Py/sdcompiler/generator/py/__init__.py
BPTK_Py/sdcompiler/generator/py/jinja_template.py
BPTK_Py/sdcompiler/generator/py/py.py
BPTK_Py/sdcompiler/parsers/__init__.py
BPTK_Py/sdcompiler/parsers/smile/__init__.py
BPTK_Py/sdcompiler/parsers/smile/grammar.py
BPTK_Py/sdcompiler/parsers/xmile/__init__.py
BPTK_Py/sdcompiler/parsers/xmile/xmile.py
BPTK_Py/sdcompiler/plugins/__init__.py
BPTK_Py/sdcompiler/plugins/complexFunctions.py
BPTK_Py/sdcompiler/plugins/expandArrays.py
BPTK_Py/sdcompiler/plugins/filterGhosts.py
BPTK_Py/sdcompiler/plugins/fixLabels.py
BPTK_Py/sdcompiler/plugins/makeAbsolute.py
BPTK_Py/sdcompiler/plugins/replaceDimensionNames.py
BPTK_Py/sdcompiler/plugins/resolveAsterisk.py
BPTK_Py/sdcompiler/plugins/resolveSelf.py
BPTK_Py/sdcompiler/plugins/sanitizeNames.py
BPTK_Py/sdcompiler/plugins/sortEntities.py
BPTK_Py/sdcompiler/plugins/stockExpressions.py
BPTK_Py/sddsl/__init__.py
BPTK_Py/sddsl/biflow.py
BPTK_Py/sddsl/constant.py
BPTK_Py/sddsl/converter.py
BPTK_Py/sddsl/element.py
BPTK_Py/sddsl/flow.py
BPTK_Py/sddsl/functions.py
BPTK_Py/sddsl/module.py
BPTK_Py/sddsl/operators.py
BPTK_Py/sddsl/stock.py
BPTK_Py/sdsimulation/__init__.py
BPTK_Py/sdsimulation/sd_simulation.py
BPTK_Py/server/__init__.py
BPTK_Py/server/bptkServer.py
BPTK_Py/util/__init__.py
BPTK_Py/util/didyoumean.py
BPTK_Py/util/floating_point.py
BPTK_Py/util/lookup_data.py
BPTK_Py/util/serializer.py
BPTK_Py/util/statecompression.py
BPTK_Py/visualizations/__init__.py
BPTK_Py/visualizations/simple_dashboard.py
BPTK_Py/visualizations/visualize.py
BPTK_Py/widgets/__init__.py
BPTK_Py/widgets/agentstatuswidget.py
BPTK_Py/widgets/widget.py
bptk_py.egg-info/PKG-INFO
bptk_py.egg-info/SOURCES.txt
bptk_py.egg-info/dependency_links.txt
bptk_py.egg-info/not-zip-safe
bptk_py.egg-info/requires.txt
bptk_py.egg-info/top_level.txt
tests/test_bptk.py
tests/test_external_state.py
tests/test_sddsl.py
tests/test_server.py
tests/test_xmile.py
[build-system]
requires = ["setuptools >= 65.0"]
build-backend = "setuptools.build_meta"
[project]
name = "bptk-py"
dynamic = ["version"]
dependencies = [
"pandas==2.2.3",
"matplotlib==3.9.2",
"scipy==1.14.1",
"numpy==2.1.2",
"ipywidgets==8.1.5",
"pyyaml==6.0.1",
"xlsxwriter==3.1.9",
"parsimonious==0.10.0",
"xmltodict==0.12.0",
"jinja2==3.1.4",
"sympy==1.13.3",
"distlib==0.3.8",
"cachetools==5.5.0",
"requests==2.31.0",
"flask==3.0.3",
"jsonpickle==3.0.2"
]
requires-python = ">=3.11"
authors = [
{name = "transentis", email = "support@transentis.com"}
]
maintainers = [
{name = "transentis", email = "support@transentis.com"}
]
description = "A python simulation engine for System Dynamics & Agent based models"
readme = "README.md"
keywords = ["system dynamics", "agent based modeling"]
classifiers = [
"Programming Language :: Python :: 3",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent"
]
[project.optional-dependencies]
test = [
"pytest",
]
[project.urls]
Homepage = "https://bptk.transentis.com"
Documentation = "https://bptk.transentis.com"
Repository = "https://github.com/transentis/bptk_py"
+5
-7

@@ -1,5 +0,3 @@

import pkg_resources
import BPTK_Py.sddsl.functions as sd_functions
from importlib.metadata import version
from .modeling import Event, DelayedEvent, Agent, DataCollector, Model, Scheduler, SimultaneousScheduler

@@ -11,5 +9,5 @@ from .sddsl import Module

import sys
version = sys.version_info
if(version[0] < 3 or (version[0] == 3 and version[1] < 9)):
print("BPTK Server requires Python 3.9 or later. Please update Python to use the BPTK Server!")
sys_version = sys.version_info
if(sys_version[0] < 3 or (sys_version[0] == 3 and sys_version[1] < 11)):
print("BPTK Server requires Python 3.11 or later. Please update Python to use the BPTK Server!")
else:

@@ -20,3 +18,3 @@ from .server import BptkServer

try:
__version__ = pkg_resources.get_distribution("BPTK_Py").version
__version__ = version("wheel")

@@ -23,0 +21,0 @@ except:

from abc import ABCMeta, abstractmethod
import datetime
from typing import Any

@@ -11,6 +12,6 @@ import jsonpickle

class InstanceState:
state: 'typing.Any'
state: Any
instance_id: str
time: str
timeout: 'typing.Any'
timeout: Any
step: int

@@ -22,3 +23,3 @@

self.compress = compress
def save_state(self, state: list[InstanceState]):

@@ -31,3 +32,3 @@ if(self.compress):

return self._save_state(state)
def save_instance(self, state: InstanceState):

@@ -38,3 +39,3 @@ if(self.compress and state is not None and state.state is not None):

return self._save_instance(state)
def load_state(self) -> list[InstanceState]:

@@ -48,3 +49,3 @@ state = self._load_state()

return state
def load_instance(self, instance_uuid: str) -> InstanceState:

@@ -86,8 +87,8 @@ state = self._load_instance(instance_uuid)

self._save_instance(state)
def _save_instance(self, state: InstanceState):
data = {
"data": {
"state": jsonpickle.dumps(state.state),
data = {
"data": {
"state": jsonpickle.dumps(state.state),
"instance_id": state.instance_id,

@@ -103,5 +104,5 @@ "time": str(state.time),

f.close()
def _load_state(self) -> list[InstanceState]:
def _load_state(self) -> list[InstanceState]:
instances = []

@@ -119,3 +120,3 @@ instance_paths = os.listdir(self.path)

instance_data = jsonpickle.loads(f.read())
decoded_data = jsonpickle.loads(instance_data["data"]["state"])

@@ -125,3 +126,3 @@ instance_id = instance_data["data"]["instance_id"]

step = instance_data["data"]["step"]
return InstanceState(decoded_data, instance_id, datetime.datetime.now(), timeout, step)

@@ -128,0 +129,0 @@ except Exception as e:

@@ -16,3 +16,5 @@ # /`-

import os
from pathlib import Path
import BPTK_Py.config.config as config

@@ -99,3 +101,3 @@ from ..modelmonitor import FileMonitor

self.scenario_managers[scenario_manager_name].add_scenarios(model_dictionary[scenario_manager_name]["scenarios"])
if filename not in self.scenario_managers[scenario_manager_name].filenames:
if filename not in self.scenario_managers[scenario_manager_name].filenames:
self.scenario_managers[scenario_manager_name].filenames +=[filename]

@@ -123,9 +125,15 @@

model_file = model_dictionary[scenario_manager_name]["model"]
source = None
try:
source = model_dictionary[scenario_manager_name]["source"]
except:
pass
source = model_dictionary[scenario_manager_name].get(
"source", None)
# this holds if there is a scenarios and a models folder in the
# project directory
main_dir = Path(filename).parent.parent
if source:
source = str(main_dir / source)
model_file = str(main_dir / model_file)
# Create simulation scenarios from structure

@@ -132,0 +140,0 @@ manager.load_scenarios(scen_dict=scen_dict, model_file=model_file, source=source)

@@ -16,2 +16,3 @@ # /`-

import os
from pathlib import Path

@@ -223,10 +224,18 @@ import BPTK_Py.config.config as config

if not os.path.isfile(self.model_file + ".py") or last_stamp_source > last_stamp_model:
py_model_file_path = self.model_file + ".py"
if not os.path.isfile(py_model_file_path) or last_stamp_source > last_stamp_model:
if not self.source is None and os.path.isfile(self.source): ## <- Only do if the source actually exists
compile(target="py", src=self.source, dest=self.model_file + ".py")
compile(target="py", src=self.source, dest=py_model_file_path)
try:
## FROM "model/model_name" I have to come to python-specific notation "model.model_name"
package_link = self.model_file.replace("/", ".").replace("\\",
".") # The last change is for windows path notation
full_file_path = Path(py_model_file_path)
## need to check whether this is in model/model_name notation (XMILE) or model.model_name notation (SDDSL)
if full_file_path.parent.name:
package_link = full_file_path.parent.name + "." + full_file_path.stem
else:
package_link = full_file_path.stem
class_link = "simulation_model"

@@ -233,0 +242,0 @@

@@ -1007,3 +1007,3 @@ # /`-

'lookuparea' : lambda *args : "(np.trapz([LERP( i , self.points[\"{}\"]) for i in np.arange(self.starttime,{} + self.dt,self.dt)], dx=self.dt)) ".format(remove_nesting(args)[0]["name"],parseExpression(remove_nesting(args)[1])),
'lookuparea' : lambda *args : "(np.trapezoid([LERP( i , self.points[\"{}\"]) for i in np.arange(self.starttime,{} + self.dt,self.dt)], dx=self.dt)) ".format(remove_nesting(args)[0]["name"],parseExpression(remove_nesting(args)[1])),

@@ -1010,0 +1010,0 @@ 'ramp' : lambda *args : ramp_(args),

@@ -285,3 +285,3 @@ # /`-

Sentence = _ ( Comment / ConditionalExpression / ConditionalStatement / Expression / nothing ) _
Comment = _ "{" ~"[\w\d\s]*"iu "}" _
Comment = _ "{" ~r"[\w\s]*"iu "}" _
ConditionalExpression = (if _ Sentence _ then _ Sentence _ else _ Sentence) / (if _ Sentence _ then _ Sentence)

@@ -311,3 +311,3 @@ ConditionalStatement = (ComparisonExpression BooleanOperator ConditionalStatement) / (ComparisonExpression)

digits = ~"[\d]+"
digits = ~r"[\d]+"

@@ -347,4 +347,4 @@ AdditiveOperator = _ ('+' / '-' ) _

Name = ~r"[\w\d_%$€£¥&§#']+"
NameWithSpecialChars = ~r"([\w\d_%$€£¥&§#'+\-*#<>\\.,;:–()]|(\\\"))+"
Name = ~r"[\w_%$€£¥&§#']+"
NameWithSpecialChars = ~r"([\w_%$€£¥&§#'+\-*#<>\\.,;:–()]|(\\\"))+"
Separator = strict_whitespace / bracket_open

@@ -351,0 +351,0 @@ bracket_open = '('

@@ -1,2 +0,2 @@

Copyright (c) 2021 transentis labs GmbH <support@transentis.com>
Copyright (c) 2024 transentis labs GmbH <support@transentis.com>

@@ -3,0 +3,0 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),

+61
-26
Metadata-Version: 2.1
Name: BPTK_Py
Version: 1.9.0
Name: bptk-py
Version: 1.9.2
Summary: A python simulation engine for System Dynamics & Agent based models
Home-page: https://www.transentis.com/business-prototyping-toolkit/en
Author: transentis labs GmbH
Author-email: support@transentis.com
License: MIT
Author-email: transentis <support@transentis.com>
Maintainer-email: transentis <support@transentis.com>
Project-URL: Homepage, https://bptk.transentis.com
Project-URL: Documentation, https://bptk.transentis.com
Project-URL: Repository, https://github.com/transentis/bptk_py
Keywords: system dynamics,agent based modeling
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pandas==2.2.3
Requires-Dist: matplotlib==3.9.2
Requires-Dist: scipy==1.14.1
Requires-Dist: numpy==2.1.2
Requires-Dist: ipywidgets==8.1.5
Requires-Dist: pyyaml==6.0.1
Requires-Dist: xlsxwriter==3.1.9
Requires-Dist: parsimonious==0.10.0
Requires-Dist: xmltodict==0.12.0
Requires-Dist: jinja2==3.1.4
Requires-Dist: sympy==1.13.3
Requires-Dist: distlib==0.3.8
Requires-Dist: cachetools==5.5.0
Requires-Dist: requests==2.31.0
Requires-Dist: flask==3.0.3
Requires-Dist: jsonpickle==3.0.2
Provides-Extra: test
Requires-Dist: pytest; extra == "test"
# Business Prototyping Toolkit for Python
# Business Prototyping Toolkit for Python
[![Coverage Status](https://coveralls.io/repos/github/transentis/bptk_py/badge.svg)](https://coveralls.io/github/transentis/bptk_py)
__System Dynamics and Agent-based Modeling in Python__

@@ -23,7 +46,7 @@

This means you can build models in a XMILE-compatible visual modeling environment (such as [Stella](http://www.iseesystems.com) or [iThink](http://www.iseesystems.com)) and then use them _independently_ in an Python environment.
This means you can build models in a XMILE-compatible visual modeling environment (such as [Stella](https://www.iseesystems.com) or [iThink](https://www.iseesystems.com)) and then use them _independently_ in an Python environment.
The best way to get started with BPTK-Py is to read the [Quickstart](https://bptk.transentis.com/quickstart/quickstart.html) that is part ot the extensive [online documentation](http://bptk.transentis.com). The Quickstart provides a _single page_ overview of all the computational modeling techniques supported by BPTK.
The best way to get started with BPTK-Py is to read the [Quickstart](https://bptk.transentis.com/quickstart/quickstart.html) that is part ot the extensive [online documentation](https://bptk.transentis.com). The Quickstart provides a _single page_ overview of all the computational modeling techniques supported by BPTK.
## Main Features

@@ -33,4 +56,4 @@

* The BPTK-Py framework supports System Dynamics models in XMILE Format, native SD models using a domain-specific language for System Dynamics (SD DSL) and native Agent-based models. You can also build hybrid SD-ABM-Models natively in Python.
* All plotting is done using [Matplotlib](http://www.matplotlib.org).
* Simulation results are returned as [Pandas dataframes](http://pandas.pydata.org) and thus can easily be used for analytics.
* All plotting is done using [Matplotlib](https://www.matplotlib.org).
* Simulation results are returned as [Pandas dataframes](https://pandas.pydata.org) and thus can easily be used for analytics.
* Model settings and scenarios are kept in JSON files. These settings are automatically loaded by the framework upon initialization, as are the model classes themselves. This makes interactive modeling, coding and testing very painless, especially if using the Jupyter notebook environment.

@@ -40,9 +63,9 @@

BPTK-Py is developed and maintained by [transentis labs](http://www.transentis.com/business-prototyping-toolki/en/).
BPTK-Py is developed and maintained by [transentis labs](https://www.transentis.com/business-prototyping-toolki/en/).
The first place to go to for help and installation instructions is the [online documentation](http://bptk.transentis.com).
The first place to go to for help and installation instructions is the [online documentation](https://bptk.transentis.com).
The [Quickstart](https://bptk.transentis.com/quickstart/quickstart.html) provides a _single page_ overview of all the modeling techniques supported by BPTK.
The [Quickstart](https://bptk.transentis.com/quickstart/quickstart.html) provides a _single page_ overview of all the modeling techniques supported by BPTK.
The online documentation is generated from an extensive set of Jupyter notebooks, the __BPTK Tutorial__. The tutorial is available as a [git repository](https://github.com/transentis/bptk_py_tutorial) on GitHub.
The online documentation is generated from an extensive set of Jupyter notebooks, the __BPTK Tutorial__. The tutorial is available as a [git repository](https://github.com/transentis/bptk_py_tutorial) on GitHub.

@@ -59,2 +82,14 @@ Our [Business Prototyping Toolkit Meetup Group](https://www.transentis.com/business-prototyping-toolkit-meetup/en/) gathers online regularly. This is a good place to see BPTK in action, ask questions and suggest new features. We record every session and you can _view past recordings_ on the [meetup homepage](https://www.transentis.com/resources/business-prototyping-toolkit-meetup).

### 1.9.2
* Fix to build script
### 1.9.1
* Bump versions of key dependencies
* Update XMILE parser grammar to remove depreciation warning
* Remove obsolete documentation files
* Update setup to use pyproject.toml
* Bump Python Version to 3.11
### 1.9.0

@@ -142,3 +177,3 @@ * BPTKServer: `run` endpoint now also works for agent-based models

* BPTK Server: Improvements to the new state externalisation feature
* BPTK Server: Improve cleanup of resources when an instance times out
* BPTK Server: Improve cleanup of resources when an instance times out

@@ -283,6 +318,6 @@ ### 1.5.0

* SD-DSL: Added support for right-hand side addition and subtraction to support equations such as ``converter.equation = 1 - b``
* Visualisation for SD-DSL elements now follows conventions to work properly with Matplotlib 3.3+
* Visualisation for SD-DSL elements now follows conventions to work properly with Matplotlib 3.3+
### 1.1.10
* Visualisation using matplotlib now follows conventions to work properly with Matplotlib 3.3+
* Visualisation using matplotlib now follows conventions to work properly with Matplotlib 3.3+

@@ -292,3 +327,3 @@ ### 1.1.9

### 1.1.8
### 1.1.8
* Another bugfix for series renaming. Simplified the code for renaming by using Pandas' standard method ``rename``

@@ -314,3 +349,3 @@

### 1.1.3
We figured that the update mechanisms via ``pip`` might be confusing sometimes, especially for non-programmers. This is
We figured that the update mechanisms via ``pip`` might be confusing sometimes, especially for non-programmers. This is
why we decided to implement an update mechanism. Details are available in the [documentation](https://bptk.transentis.com/en/latest/docs/usage/installation.html#keeping-bptk-py-up-to-date)

@@ -322,10 +357,10 @@

### 1.1.1
### 1.1.1
* The SD DSL now differentiates flows and biflows. Simply add a biflow using ```biflow = model.biflow(<name>)```.
* The SD DSL now supports: RANDOM, IF, NOT, AND, OR, NAN, SQRT, ROUND and all trigonometric and statistical builtins you know from XMILE. Furthermore the operators support Comparison Operators (>, <, >=, <=, ==, !=) and the modulo operator (x % y).
* The SD DSL now supports: RANDOM, IF, NOT, AND, OR, NAN, SQRT, ROUND and all trigonometric and statistical builtins you know from XMILE. Furthermore the operators support Comparison Operators (>, <, >=, <=, ==, !=) and the modulo operator (x % y).
* RANDOM: ``converter.equation = sd.Random(<min>, <max>)`` draws a uniformly distributed float random number between <min> and <max>
* ROUND: ``converter.equation = sd.Round(sd.random(0,1),2))`` rounds a random number between 0 and 1 to a 2 digit float
* IF: ```converter.equation = sd.If( <condition>, <then> , <else> ) ``` corresponds to ```IF <condition> THEN <then> ELSE <else>```. Each term inside the IF clause can be a SD term again. Example for a valid If clause: ``equation = sd.If(sd.time()>10,sd.random(1,2), 100)``
* IF: ```converter.equation = sd.If( <condition>, <then> , <else> ) ``` corresponds to ```IF <condition> THEN <then> ELSE <else>```. Each term inside the IF clause can be a SD term again. Example for a valid If clause: ``equation = sd.If(sd.time()>10,sd.random(1,2), 100)``
* AND/OR: ```sd.Or(<left hand side>, <right hand side>)``` and ```sd.And(<left hand side>, <right hand side>)``` for multiple conditions
* NOT: Use ```sd.Not(<condition>)``` for "not" conditions, e.g: ```sd.If(sd.Not(sd.time()>10), 1, 0 )```
* NOT: Use ```sd.Not(<condition>)``` for "not" conditions, e.g: ```sd.If(sd.Not(sd.time()>10), 1, 0 )```
* NAN / INF / PI: ``sd.nan()`` returns a NAN value, ``sd.Inf()`` gives you the infinity value, ```sd.pi()``` returns the number pi.

@@ -348,3 +383,3 @@ * SQRT: ``sd.sqrt(<value of function>)`` computes the square root

* Bugfix release: Fixed an issue with plot_lookup
* Bugfix release: Fixed an issue with plot_lookup

@@ -351,0 +386,0 @@ ### 1.0.0

+34
-20

@@ -1,3 +0,5 @@

# Business Prototyping Toolkit for Python
# Business Prototyping Toolkit for Python
[![Coverage Status](https://coveralls.io/repos/github/transentis/bptk_py/badge.svg)](https://coveralls.io/github/transentis/bptk_py)
__System Dynamics and Agent-based Modeling in Python__

@@ -9,7 +11,7 @@

This means you can build models in a XMILE-compatible visual modeling environment (such as [Stella](http://www.iseesystems.com) or [iThink](http://www.iseesystems.com)) and then use them _independently_ in an Python environment.
This means you can build models in a XMILE-compatible visual modeling environment (such as [Stella](https://www.iseesystems.com) or [iThink](https://www.iseesystems.com)) and then use them _independently_ in an Python environment.
The best way to get started with BPTK-Py is to read the [Quickstart](https://bptk.transentis.com/quickstart/quickstart.html) that is part ot the extensive [online documentation](http://bptk.transentis.com). The Quickstart provides a _single page_ overview of all the computational modeling techniques supported by BPTK.
The best way to get started with BPTK-Py is to read the [Quickstart](https://bptk.transentis.com/quickstart/quickstart.html) that is part ot the extensive [online documentation](https://bptk.transentis.com). The Quickstart provides a _single page_ overview of all the computational modeling techniques supported by BPTK.
## Main Features

@@ -19,4 +21,4 @@

* The BPTK-Py framework supports System Dynamics models in XMILE Format, native SD models using a domain-specific language for System Dynamics (SD DSL) and native Agent-based models. You can also build hybrid SD-ABM-Models natively in Python.
* All plotting is done using [Matplotlib](http://www.matplotlib.org).
* Simulation results are returned as [Pandas dataframes](http://pandas.pydata.org) and thus can easily be used for analytics.
* All plotting is done using [Matplotlib](https://www.matplotlib.org).
* Simulation results are returned as [Pandas dataframes](https://pandas.pydata.org) and thus can easily be used for analytics.
* Model settings and scenarios are kept in JSON files. These settings are automatically loaded by the framework upon initialization, as are the model classes themselves. This makes interactive modeling, coding and testing very painless, especially if using the Jupyter notebook environment.

@@ -26,9 +28,9 @@

BPTK-Py is developed and maintained by [transentis labs](http://www.transentis.com/business-prototyping-toolki/en/).
BPTK-Py is developed and maintained by [transentis labs](https://www.transentis.com/business-prototyping-toolki/en/).
The first place to go to for help and installation instructions is the [online documentation](http://bptk.transentis.com).
The first place to go to for help and installation instructions is the [online documentation](https://bptk.transentis.com).
The [Quickstart](https://bptk.transentis.com/quickstart/quickstart.html) provides a _single page_ overview of all the modeling techniques supported by BPTK.
The [Quickstart](https://bptk.transentis.com/quickstart/quickstart.html) provides a _single page_ overview of all the modeling techniques supported by BPTK.
The online documentation is generated from an extensive set of Jupyter notebooks, the __BPTK Tutorial__. The tutorial is available as a [git repository](https://github.com/transentis/bptk_py_tutorial) on GitHub.
The online documentation is generated from an extensive set of Jupyter notebooks, the __BPTK Tutorial__. The tutorial is available as a [git repository](https://github.com/transentis/bptk_py_tutorial) on GitHub.

@@ -45,2 +47,14 @@ Our [Business Prototyping Toolkit Meetup Group](https://www.transentis.com/business-prototyping-toolkit-meetup/en/) gathers online regularly. This is a good place to see BPTK in action, ask questions and suggest new features. We record every session and you can _view past recordings_ on the [meetup homepage](https://www.transentis.com/resources/business-prototyping-toolkit-meetup).

### 1.9.2
* Fix to build script
### 1.9.1
* Bump versions of key dependencies
* Update XMILE parser grammar to remove depreciation warning
* Remove obsolete documentation files
* Update setup to use pyproject.toml
* Bump Python Version to 3.11
### 1.9.0

@@ -128,3 +142,3 @@ * BPTKServer: `run` endpoint now also works for agent-based models

* BPTK Server: Improvements to the new state externalisation feature
* BPTK Server: Improve cleanup of resources when an instance times out
* BPTK Server: Improve cleanup of resources when an instance times out

@@ -269,6 +283,6 @@ ### 1.5.0

* SD-DSL: Added support for right-hand side addition and subtraction to support equations such as ``converter.equation = 1 - b``
* Visualisation for SD-DSL elements now follows conventions to work properly with Matplotlib 3.3+
* Visualisation for SD-DSL elements now follows conventions to work properly with Matplotlib 3.3+
### 1.1.10
* Visualisation using matplotlib now follows conventions to work properly with Matplotlib 3.3+
* Visualisation using matplotlib now follows conventions to work properly with Matplotlib 3.3+

@@ -278,3 +292,3 @@ ### 1.1.9

### 1.1.8
### 1.1.8
* Another bugfix for series renaming. Simplified the code for renaming by using Pandas' standard method ``rename``

@@ -300,3 +314,3 @@

### 1.1.3
We figured that the update mechanisms via ``pip`` might be confusing sometimes, especially for non-programmers. This is
We figured that the update mechanisms via ``pip`` might be confusing sometimes, especially for non-programmers. This is
why we decided to implement an update mechanism. Details are available in the [documentation](https://bptk.transentis.com/en/latest/docs/usage/installation.html#keeping-bptk-py-up-to-date)

@@ -308,10 +322,10 @@

### 1.1.1
### 1.1.1
* The SD DSL now differentiates flows and biflows. Simply add a biflow using ```biflow = model.biflow(<name>)```.
* The SD DSL now supports: RANDOM, IF, NOT, AND, OR, NAN, SQRT, ROUND and all trigonometric and statistical builtins you know from XMILE. Furthermore the operators support Comparison Operators (>, <, >=, <=, ==, !=) and the modulo operator (x % y).
* The SD DSL now supports: RANDOM, IF, NOT, AND, OR, NAN, SQRT, ROUND and all trigonometric and statistical builtins you know from XMILE. Furthermore the operators support Comparison Operators (>, <, >=, <=, ==, !=) and the modulo operator (x % y).
* RANDOM: ``converter.equation = sd.Random(<min>, <max>)`` draws a uniformly distributed float random number between <min> and <max>
* ROUND: ``converter.equation = sd.Round(sd.random(0,1),2))`` rounds a random number between 0 and 1 to a 2 digit float
* IF: ```converter.equation = sd.If( <condition>, <then> , <else> ) ``` corresponds to ```IF <condition> THEN <then> ELSE <else>```. Each term inside the IF clause can be a SD term again. Example for a valid If clause: ``equation = sd.If(sd.time()>10,sd.random(1,2), 100)``
* IF: ```converter.equation = sd.If( <condition>, <then> , <else> ) ``` corresponds to ```IF <condition> THEN <then> ELSE <else>```. Each term inside the IF clause can be a SD term again. Example for a valid If clause: ``equation = sd.If(sd.time()>10,sd.random(1,2), 100)``
* AND/OR: ```sd.Or(<left hand side>, <right hand side>)``` and ```sd.And(<left hand side>, <right hand side>)``` for multiple conditions
* NOT: Use ```sd.Not(<condition>)``` for "not" conditions, e.g: ```sd.If(sd.Not(sd.time()>10), 1, 0 )```
* NOT: Use ```sd.Not(<condition>)``` for "not" conditions, e.g: ```sd.If(sd.Not(sd.time()>10), 1, 0 )```
* NAN / INF / PI: ``sd.nan()`` returns a NAN value, ``sd.Inf()`` gives you the infinity value, ```sd.pi()``` returns the number pi.

@@ -334,3 +348,3 @@ * SQRT: ``sd.sqrt(<value of function>)`` computes the square root

* Bugfix release: Fixed an issue with plot_lookup
* Bugfix release: Fixed an issue with plot_lookup

@@ -337,0 +351,0 @@ ### 1.0.0

from setuptools import setup
import conf, pytest
#########################
### LOAD REQUIREMENTS ###
#########################
requirements = []
req_file = open("requirements.txt","r")
for line in req_file.readlines():
requirements += [line.replace("\n","")]
###################

@@ -25,13 +14,7 @@ ### LOAD README ###

def get_version():
return '1.9.2'
setup(name='BPTK_Py',
version=conf.release,
description='A python simulation engine for System Dynamics & Agent based models',
long_description=long_description,
long_description_content_type="text/markdown",
url='https://www.transentis.com/business-prototyping-toolkit/en',
author='transentis labs GmbH',
author_email='support@transentis.com',
license='MIT',
packages=['BPTK_Py',
setup(version=get_version(),
packages=['BPTK_Py',
'BPTK_Py.scenariomanager',

@@ -61,13 +44,3 @@ "BPTK_Py.logger",

],
install_requires=requirements,
setup_requires=["pytest-runner"],
tests_require=["pytest"],
include_package_data=True,
classifiers=[
"Programming Language :: Python :: 3",
'License :: OSI Approved :: MIT License',
"Operating System :: OS Independent",
],
zip_safe=False)
import pytest
from pathlib import Path
import pandas as pd
from pandas._testing import assert_frame_equal
from unittest import TestCase
import json
from BPTK_Py import Model
from BPTK_Py import sd_functions as sd
import BPTK_Py

@@ -14,3 +12,2 @@ from BPTK_Py.util import timerange, normalize

@pytest.fixture

@@ -35,6 +32,5 @@ def sd_model():

bptk = BPTK_Py.bptk()
bptk.register_scenario_manager({"firstManager": {"model": model}})
bptk = BPTK_Py.bptk()
bptk.register_scenario_manager({"firstManager":{"model":model}})
bptk.register_scenarios(

@@ -50,5 +46,5 @@ scenarios=

}
}, scenario_manager = "firstManager")
bptk.register_scenario_manager({"secondManager": {"model":model}})

@@ -76,2 +72,3 @@ bptk.register_scenarios(

def sd_results(bptk):

@@ -93,6 +90,7 @@ """

def test_floating_point():
assert normalize(3.6,base=0.25,offset=0.0,precision=2) == 3.5
assert normalize(3.6,base=0.25,offset=0.1,precision=2) == 3.6
assert normalize(3.6,base=0.25,offset=0.3,precision=2) == 3.55
assert normalize(3.6,base=0.25,offset=0.3,precision=2) == 3.55
assert timerange(1,10,1) == [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]

@@ -104,4 +102,4 @@ assert timerange(3.3,7,0.25) == [3.3,3.55,3.8,4.05,4.3,4.55,4.8,5.05,5.3,5.55,5.8,6.05,6.3,6.55,6.8]

assert timerange(0.0,0.0005,0.0001,exclusive=False) == [0.0,0.0001,0.0002,0.0003,0.0004,0.0005]
def test_sd_model_results_data_type(sd_model):

@@ -116,3 +114,4 @@ """

assert isinstance(results, pd.DataFrame)
def test_sd_model_results_col_names(sd_model):

@@ -130,3 +129,4 @@ """

assert all(col in equations for col in columns_names) # making sure that the column names exist
def test_sd_model_results_content(sd_model):

@@ -144,5 +144,6 @@ """

test_df.index += 1.0
assert_frame_equal(results, test_df)
def sd_run_scenarios_results(bptk):

@@ -163,3 +164,4 @@ """

return results
def test_sd_run_scenarios_df_results(sd_model):

@@ -177,5 +179,6 @@ """

test_df.index += 1.0
assert_frame_equal(results, test_df)
def test_sd_run_scenarios_json_results(sd_model):

@@ -194,3 +197,3 @@ """

)
firstManager_stock_df=sd_run_scenarios_results(bptk).rename(columns={"stock": "firstManager_1_stock"})

@@ -215,7 +218,7 @@ secondManager_stock_df=sd_run_scenarios_results(bptk).rename(columns={"stock": "secondManager_1_stock"})

}
expected_json = json.dumps(expected_json, indent=2)
assert results==expected_json
def test_sd_run_scenario_step(sd_model):

@@ -238,3 +241,3 @@ bptk = sd_model

{
"constant":7.0
"constant":7.0
}

@@ -244,3 +247,3 @@ }

})
assert result["firstManager"]["1"]["flow"] == {2.0:7.0}

@@ -263,3 +266,4 @@ assert result["secondManager"]["2"]["stock"] == {2.0:2.0}

################################
@pytest.fixture
@pytest.fixture
def abm_model():

@@ -273,3 +277,5 @@ """

yield bptk
bptk.destroy()
def abm_results(bptk):

@@ -292,7 +298,10 @@ """

return_df=True
)
)
return results
def test_abm_get_scenarios(abm_model):
assert abm_model.get_scenario_names(scenario_managers=["testAbmManager"])==["testScenario2","testScenario"]
scenarios_path = Path(__file__).resolve().parent / "scenarios"
result = abm_model.get_scenario_names(scenario_managers=["testAbmManager"], path=scenarios_path)
assert set(result) == set(["testScenario", "testScenario2"])

@@ -308,3 +317,4 @@

assert isinstance(results, pd.DataFrame)
def test_abm_results_col_names(abm_model):

@@ -319,5 +329,5 @@ """

scenario = bptk.get_scenario("testAbmManager", "testScenario")
columns_names = list(results.columns)
expected_column_names = []

@@ -328,5 +338,6 @@ for agent in scenario.model.agents:

expected_column_names.append(col_name)
assert all(col in expected_column_names for col in columns_names) # making sure that the column names exist
def test_abm_results_content(abm_model):

@@ -343,6 +354,6 @@ """

test_df.index += 1
assert_frame_equal(results, test_df)
def abm_run_scenarios_results(bptk, agent_property_type):

@@ -366,4 +377,4 @@ """

return results
def test_abm_run_scenarios_df_results(abm_model):

@@ -381,5 +392,6 @@ """

test_df.index += 1
assert_frame_equal(results, test_df)
def test_abm_run_scenarios_json_results(abm_model):

@@ -401,3 +413,3 @@ """

)
total_df = abm_run_scenarios_results(bptk, "total").rename(columns={"testAbmManager_testScenario_agent_1_open_x_total": "open_x_total"})

@@ -407,4 +419,4 @@ min_df = abm_run_scenarios_results(bptk, "min").rename(columns={"testAbmManager_testScenario_agent_1_open_x_min": "open_x_min"})

max_df = abm_run_scenarios_results(bptk, "max").rename(columns={"testAbmManager_testScenario_agent_1_open_x_max": "open_x_max"})
total_df.index.name=None

@@ -414,3 +426,3 @@ min_df.index.name=None

max_df.index.name=None
expected_json={

@@ -439,2 +451,3 @@ "testAbmManager": {

def test_abm_delete_agent(abm_model):

@@ -446,3 +459,3 @@ model = abm_model.get_scenario(scenario_manager="testAbmManager",scenario="testScenario2")

assert len(model.agent_type_map["agent_2"])==3
agentIds=[]

@@ -462,3 +475,3 @@ agents=[]

agentIds.pop(0)
model.delete_agents(agentIds)

@@ -468,4 +481,1 @@ assert len(model.agents)==2

assert len(model.agent_type_map["agent_2"])==1

@@ -40,3 +40,3 @@ from BPTK_Py.server import BptkServer

bptk.register_scenarios(
scenario_manager="firstManager",

@@ -51,10 +51,10 @@ scenarios=

}
}
)
bptk.register_scenarios(
scenario_manager="secondManager",

@@ -79,6 +79,6 @@ scenarios=

}
}
)

@@ -100,3 +100,3 @@

return app.test_client()
def test_instance_timeouts(app, client):

@@ -131,3 +131,3 @@ def assert_in_full_metrics(instance_id, contains: bool):

instance_id = json.loads(response.data)['instance_uuid']
content = {

@@ -170,3 +170,3 @@ "scenario_managers": [

assert_in_full_metrics(instance_id, True)
time.sleep(4)

@@ -196,3 +196,3 @@

assert instance_id + ".json" in dir_content
response = client.post('http://localhost:5000/load-state')

@@ -205,3 +205,3 @@ assert response.status_code == 200, "load-state should return 200"

assert response.status_code == 200, "stop-instance should return 200"
assert_in_full_metrics(instance_id, False)

@@ -208,0 +208,0 @@

from BPTK_Py.server import BptkServer
import requests
import json

@@ -42,3 +41,3 @@ import pytest

bptk.register_scenarios(
scenario_manager="firstManager",

@@ -53,10 +52,10 @@ scenarios=

}
}
)
bptk.register_scenarios(
scenario_manager="secondManager",

@@ -81,6 +80,6 @@ scenarios=

}
}
)

@@ -99,6 +98,6 @@

return app.test_client()
def test_home_resource(app, client):
response = client.get('/')
assert response.status_code == 200
assert response.status_code == 200
assert response.data == b"<h1>BPTK REST API Server</h1>"

@@ -108,6 +107,6 @@

response = client.get('/healthy')
assert response.status_code == 200
assert response.status_code == 200
assert response.data == b"<h1>BPTK Health Check</h1>"
def test_run_resource(app, client):

@@ -119,3 +118,3 @@ query={

"settings":{
"firstManager":

@@ -127,3 +126,3 @@ {

{
"constant":7.0
"constant":7.0
}

@@ -133,8 +132,8 @@ }

}
}
response = client.post('/run', data=json.dumps(query), content_type = 'application/json',headers={"Authorization": f"Bearer {token}"})
assert response.status_code == 200 # checking the status code

@@ -182,3 +181,3 @@

"constants": {
"constant":7.0
"constant":7.0
}

@@ -234,3 +233,3 @@ }

"constants": {
"constant":7.0
"constant":7.0
}

@@ -251,3 +250,3 @@ }

assert response.status_code == 200 # checking the status code
def test_equations_resource(app, client):

@@ -263,6 +262,6 @@ query = {

assert equation in response.data
def test_agents_resource(app, client):
response = client.post('/agents', content_type = 'application/json',headers={"Authorization": f"Bearer {token}"})
assert response.status_code == 400 # System dynamics systems shouldn't have agents
assert response.status_code == 400 # System dynamics systems shouldn't have agents

@@ -298,3 +297,3 @@ def test_metrics(app, client):

id = json.loads(response.data)['instance_uuid']
response = client.get('/full-metrics')

@@ -305,3 +304,3 @@ assert response.status_code == 200

time.sleep(6)
response = client.get('/full-metrics')

@@ -312,3 +311,3 @@ assert response.status_code == 200

time.sleep(6)
response = client.get('/full-metrics')

@@ -318,4 +317,4 @@ assert response.status_code == 200

assert result['instanceCount'] == 0
def test_keep_alive(app, client):

@@ -353,3 +352,3 @@ import time

id = json.loads(response.data)['instance_uuid']
response = client.post('/start-instance', data=json.dumps(timeout_data), content_type='application/json',headers={"Authorization": f"Bearer {token}"})

@@ -364,3 +363,3 @@ assert response.status_code == 200

response = client.get('/full-metrics')

@@ -371,6 +370,6 @@ assert response.status_code == 200

time.sleep(3)
response = client.post('/' + id + "/keep-alive",headers={"Authorization": f"Bearer {token}"})
assert response.status_code == 200
response = client.get('/full-metrics')

@@ -381,3 +380,3 @@ assert response.status_code == 200

time.sleep(3)
response = client.get('/full-metrics')

@@ -388,3 +387,3 @@ assert response.status_code == 200

time.sleep(3)
response = client.get('/full-metrics')

@@ -395,7 +394,7 @@ assert response.status_code == 200

def test_instance_timeouts(app, client):

@@ -420,3 +419,3 @@ import time

id = json.loads(response.data)['instance_uuid']
response = client.get('/full-metrics')

@@ -427,3 +426,3 @@ assert response.status_code == 200

time.sleep(6)
response = client.get('/full-metrics')

@@ -434,3 +433,3 @@ assert response.status_code == 200

time.sleep(6)
response = client.get('/full-metrics')

@@ -440,5 +439,5 @@ assert response.status_code == 200

assert result['instanceCount'] == 0
def test_run_steps(app, client):

@@ -485,3 +484,3 @@

"constants": {
"constant":7.0
"constant":7.0
}

@@ -507,7 +506,3 @@ }

def test_run_steps_lock(app, client):

@@ -553,3 +548,3 @@

"constants": {
"constant":7.0
"constant":7.0
}

@@ -569,4 +564,4 @@ }

import time
t1 = threading.Thread(target=_run_steps_lock, args=[thread_results, 0])
t2 = threading.Thread(target=_run_steps_lock, args=[thread_results, 1])
t1 = threading.Thread(target=_run_steps_lock, daemon=True, args=[thread_results, 0])
t2 = threading.Thread(target=_run_steps_lock, daemon=True, args=[thread_results, 1])
t1.start()

@@ -580,3 +575,3 @@ t2.start()

assert thread_results[1].status_code == 500
result = json.loads(thread_results[0].data)

@@ -591,6 +586,3 @@ assert len(result) == 20

def test_stream_steps_lock(app, client):

@@ -631,3 +623,3 @@

query={

@@ -638,3 +630,3 @@ "settings": {

"constants": {
"constant":7.0
"constant":7.0
}

@@ -653,4 +645,4 @@ }

import time
t1 = threading.Thread(target=_stream_steps_lock, args=[thread_results, 0])
t2 = threading.Thread(target=_stream_steps_lock, args=[thread_results, 1])
t1 = threading.Thread(target=_stream_steps_lock, daemon=True, args=[thread_results, 0])
t2 = threading.Thread(target=_stream_steps_lock, daemon=True, args=[thread_results, 1])
t1.start()

@@ -664,4 +656,4 @@ t2.start()

assert thread_results[1].status_code == 500
result = json.loads(thread_results[0].data)
assert len(result) == 50

@@ -1,6 +0,15 @@

import os
from pathlib import Path
import pytest
import numpy as np
from BPTK_Py.sdcompiler.compile import compile_xmile
def test_compilation():
@pytest.fixture
def test_models_path():
# Construct the path to the data file dynamically
current_directory = Path(__file__).resolve().parent
return current_directory / 'test_models'
def test_compilation(test_models_path):
"""

@@ -11,397 +20,313 @@ Compile models and make sure they exist afterwards. Not more, not less

import os
src = "./test_models/test_expressions.stmx"
dest = "./test_models/test_expressions.py"
src = test_models_path / "test_expressions.stmx"
dest = test_models_path / "test_expressions.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
import os
src = "./test_models/test_safediv.stmx"
dest = "./test_models/test_safediv.py"
src = test_models_path / "test_safediv.stmx"
dest = test_models_path / "test_safediv.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
import os
src = "./test_models/test_pareto.stmx"
dest = "./test_models/test_pareto.py"
src = test_models_path / "test_pareto.stmx"
dest = test_models_path / "test_pareto.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
import os
src = "./test_models/test_weibull.stmx"
dest = "./test_models/test_weibull.py"
src = test_models_path / "test_weibull.stmx"
dest = test_models_path / "test_weibull.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
import os
src = "./test_models/test_delayn.stmx"
dest = "./test_models/test_delayn.py"
src = test_models_path / "test_delayn.stmx"
dest = test_models_path / "test_delayn.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
import os
src = "./test_models/test_sinwave.stmx"
dest = "./test_models/test_sinwave.py"
src = test_models_path / "test_sinwave.stmx"
dest = test_models_path / "test_sinwave.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
import os
src = "./test_models/test_smthn.stmx"
dest = "./test_models/test_smthn.py"
src = test_models_path / "test_smthn.stmx"
dest = test_models_path / "test_smthn.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
import os
import numpy as np
src = "./test_models/test_lookup.stmx"
dest = "./test_models/test_lookup.py"
src = test_models_path / "test_lookup.stmx"
dest = test_models_path / "test_lookup.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
import os
src = "./test_models/test_ramp.stmx"
dest = "./test_models/test_ramp.py"
src = test_models_path / "test_ramp.stmx"
dest = test_models_path / "test_ramp.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
import os
src = "./test_models/test_trend.stmx"
dest = "./test_models/test_trend.py"
src = test_models_path / "test_trend.stmx"
dest = test_models_path / "test_trend.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
import os
src = "./test_models/test_poisson.stmx"
dest = "./test_models/test_poisson.py"
src = test_models_path / "test_poisson.stmx"
dest = test_models_path / "test_poisson.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
import os
src = "./test_models/test_logistic.stmx"
dest = "./test_models/test_logistic.py"
src = test_models_path / "test_logistic.stmx"
dest = test_models_path / "test_logistic.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
os.remove("./test_models/test_logistic.py")
dest.unlink()
import os
import numpy as np
src = "./test_models/test_negbinomial.stmx"
dest = "./test_models/test_negbinomial.py"
src = test_models_path / "test_negbinomial.stmx"
dest = test_models_path / "test_negbinomial.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
import os
import numpy as np
src = "./test_models/test_lognormal.stmx"
dest = "./test_models/test_lognormal.py"
src = test_models_path / "test_lognormal.stmx"
dest = test_models_path / "test_lognormal.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
os.remove( "./test_models/test_lognormal.py")
assert dest.is_file()
dest.unlink()
import os
src = "./test_models/test_financials.stmx"
dest = "./test_models/test_financials.py"
src = test_models_path / "test_financials.stmx"
dest = test_models_path / "test_financials.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
import os
src = "./test_models/test_log10.stmx"
dest = "./test_models/test_log10.py"
src = test_models_path / "test_log10.stmx"
dest = test_models_path / "test_log10.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
import os
src = "./test_models/test_lookuparea.stmx"
dest = "./test_models/test_lookuparea.py"
src = test_models_path / "test_lookuparea.stmx"
dest = test_models_path / "test_lookuparea.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
import os
src = "./test_models/test_sqrt.stmx"
dest = "./test_models/test_sqrt.py"
src = test_models_path / "test_sqrt.stmx"
dest = test_models_path / "test_sqrt.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
import os
src = "./test_models/test_percent.stmx"
dest = "./test_models/test_percent.py"
src = test_models_path / "test_percent.stmx"
dest = test_models_path / "test_percent.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
import os
src = "./test_models/test_clocktime.stmx"
dest = "./test_models/test_clocktime.py"
src = test_models_path / "test_clocktime.stmx"
dest = test_models_path / "test_clocktime.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
import os
src = "./test_models/test_if.stmx"
dest = "./test_models/test_if.py"
src = test_models_path / "test_if.stmx"
dest = test_models_path / "test_if.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
import os
import numpy as np
src = "./test_models/test_triangular.stmx"
dest = "./test_models/test_triangular.py"
src = test_models_path / "test_triangular.stmx"
dest = test_models_path / "test_triangular.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
import os
src = "./test_models/test_step.stmx"
dest = "./test_models/test_step.py"
src = test_models_path / "test_step.stmx"
dest = test_models_path / "test_step.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
src = "./test_models/test_dt_fraction.stmx"
dest = "./test_models/test_dt_fraction.py"
src = test_models_path / "test_dt_fraction.stmx"
dest = test_models_path / "test_dt_fraction.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
src = "./test_models/test_dt_rational.stmx"
dest = "./test_models/test_dt_rational.py"
src = test_models_path / "test_dt_rational.stmx"
dest = test_models_path / "test_dt_rational.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
src = "./test_models/test_no_dimensions.stmx"
dest = "./test_models/test_no_dimensions.py"
src = test_models_path / "test_no_dimensions.stmx"
dest = test_models_path / "test_no_dimensions.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
import os
src = "./test_models/test_rootn.stmx"
dest = "./test_models/test_rootn.py"
src = test_models_path / "test_rootn.stmx"
dest = test_models_path / "test_rootn.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
src = "./test_models/test_time.stmx"
dest = "./test_models/test_time.py"
src = test_models_path / "test_time.stmx"
dest = test_models_path / "test_time.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
src = "./test_models/test_smooth.stmx"
dest = "./test_models/test_smooth.py"
src = test_models_path / "test_smooth.stmx"
dest = test_models_path / "test_smooth.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
src = "./test_models/test_abs.stmx"
dest = "./test_models/test_abs.py"
src = test_models_path / "test_abs.stmx"
dest = test_models_path / "test_abs.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
src = "./test_models/test_npv.stmx"
# src ="./test_models/delay_example.itmx"
dest = "./test_models/test_npv.py"
src = test_models_path / "test_npv.stmx"
# src =test_models_path / "delay_example.itmx"
dest = test_models_path / "test_npv.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
src = "./test_models/test_cos.stmx"
dest = "./test_models/test_cos.py"
src = test_models_path / "test_cos.stmx"
dest = test_models_path / "test_cos.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
import os
src = "./test_models/test_tan.stmx"
dest = "./test_models/test_tan.py"
src = test_models_path / "test_tan.stmx"
dest = test_models_path / "test_tan.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
import os
src = "./test_models/test_sim_builtins.stmx"
dest = "./test_models/test_sim_builtins.py"
src = test_models_path / "test_sim_builtins.stmx"
dest = test_models_path / "test_sim_builtins.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
src = "./test_models/test_random.stmx"
dest = "./test_models/test_random.py"
src = test_models_path / "test_random.stmx"
dest = test_models_path / "test_random.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
import os
src = "./test_models/test_array.stmx"
dest = "./test_models/test_array.py"
src = test_models_path / "test_array.stmx"
dest = test_models_path / "test_array.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
import os
src = "./test_models/test_delay.stmx"
dest = "./test_models/test_delay.py"
src = test_models_path / "test_delay.stmx"
dest = test_models_path / "test_delay.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
import os
import numpy as np
src = "./test_models/test_endval.stmx"
dest = "./test_models/test_endval.py"
src = test_models_path / "test_endval.stmx"
dest = test_models_path / "test_endval.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
import os
src = "./test_models/test_array_extended.stmx"
dest = "./test_models/test_array_extended.py"
src = test_models_path / "test_array_extended.stmx"
dest = test_models_path / "test_array_extended.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
import os
src = "./test_models/test_array_3dimensional.stmx"
dest = "./test_models/test_array_3dimensional.py"
src = test_models_path / "test_array_3dimensional.stmx"
dest = test_models_path / "test_array_3dimensional.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
import os
src = "./test_models/test_array_2dimensional.stmx"
dest = "./test_models/test_array_2dimensional.py"
src = test_models_path / "test_array_2dimensional.stmx"
dest = test_models_path / "test_array_2dimensional.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
import os
src = "./test_models/test_permutation.stmx"
dest = "./test_models/test_permutation.py"
src = test_models_path / "test_permutation.stmx"
dest = test_models_path / "test_permutation.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
import os
src = "./test_models/test_forecast.stmx"
dest = "./test_models/test_forecast.py"
src = test_models_path / "test_forecast.stmx"
dest = test_models_path / "test_forecast.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
import os
src = "./test_models/test_smth3.stmx"
dest = "./test_models/test_smth3.py"
src = test_models_path / "test_smth3.stmx"
dest = test_models_path / "test_smth3.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()

@@ -513,3 +438,2 @@

def test_smooth():

@@ -530,3 +454,2 @@ """

def test_abs():

@@ -537,4 +460,2 @@ """

"""
import numpy as np
import os
from test_models.test_abs import simulation_model

@@ -550,3 +471,2 @@ sim = simulation_model()

def test_dt_fraction():

@@ -620,4 +540,2 @@ """

"""
import numpy as np
import os
from test_models.test_cos import simulation_model

@@ -638,4 +556,2 @@ sim = simulation_model()

"""
import numpy as np
import os
from test_models.test_tan import simulation_model

@@ -656,4 +572,2 @@ sim = simulation_model()

"""
import numpy as np
import os
from test_models.test_sim_builtins import simulation_model

@@ -676,4 +590,2 @@ sim = simulation_model()

'''
import numpy as np
import os
from test_models.test_random import simulation_model

@@ -698,4 +610,2 @@ sim = simulation_model()

def test_step():
import numpy as np
import os
from test_models.test_step import simulation_model

@@ -713,4 +623,2 @@ sim = simulation_model()

def test_delay():
import numpy as np
import os
from test_models.test_delay import simulation_model

@@ -728,4 +636,2 @@ sim = simulation_model()

def test_if():
import numpy as np
import os
from test_models.test_if import simulation_model

@@ -796,3 +702,2 @@ sim = simulation_model()

13.0: 12.0}
import numpy as np
result = {}

@@ -956,3 +861,2 @@ from test_models.test_array import simulation_model

import numpy as np
result_counter = []

@@ -968,3 +872,2 @@ for t in np.arange(starttime, stoptime + dt, dt):

from test_models.test_npv import simulation_model
import numpy as np

@@ -987,3 +890,2 @@ sim = simulation_model()

from test_models.test_financials import simulation_model
import numpy as np

@@ -1007,3 +909,2 @@ sim = simulation_model()

from test_models.test_percent import simulation_model
import numpy as np

@@ -1022,3 +923,2 @@ sim = simulation_model()

from test_models.test_sqrt import simulation_model
import numpy as np

@@ -1036,3 +936,2 @@ sim = simulation_model()

from test_models.test_log10 import simulation_model
import numpy as np

@@ -1051,3 +950,2 @@ sim = simulation_model()

from test_models.test_permutation import simulation_model
import numpy as np

@@ -1067,3 +965,2 @@ sim = simulation_model()

from test_models.test_forecast import simulation_model
import numpy as np

@@ -1133,3 +1030,2 @@ sim = simulation_model()

def test_lookup():
import numpy as np
from test_models.test_lookup import simulation_model

@@ -1150,3 +1046,2 @@ sim = simulation_model()

def test_lookuparea():
import numpy as np
from test_models.test_lookuparea import simulation_model

@@ -1173,3 +1068,2 @@ sim = simulation_model()

def test_poisson():
import numpy as np
from test_models.test_poisson import simulation_model

@@ -1190,3 +1084,2 @@ sim = simulation_model()

def test_ramp():
import numpy as np
from test_models.test_ramp import simulation_model

@@ -1215,3 +1108,2 @@ sim = simulation_model()

def test_rootn():
import numpy as np
from test_models.test_rootn import simulation_model

@@ -1231,3 +1123,2 @@ sim = simulation_model()

def test_sinwave():
import numpy as np
from test_models.test_sinwave import simulation_model

@@ -1252,3 +1143,2 @@ sim = simulation_model()

def test_smth3():
import numpy as np
from test_models.test_smth3 import simulation_model

@@ -1272,3 +1162,2 @@ sim = simulation_model()

def test_smthn():
import numpy as np
from test_models.test_smthn import simulation_model

@@ -1293,3 +1182,2 @@ sim = simulation_model()

def test_delayn():
import numpy as np
from test_models.test_delayn import simulation_model

@@ -1332,3 +1220,2 @@ sim = simulation_model()

def test_weibull():
import numpy as np
from test_models.test_weibull import simulation_model

@@ -1367,3 +1254,2 @@ sim = simulation_model()

def test_pareto():
import numpy as np
from test_models.test_pareto import simulation_model

@@ -1397,13 +1283,12 @@ sim = simulation_model()

def test_cgrowth():
import os
src = "./test_models/test_cgrowth.stmx"
dest = "./test_models/test_cgrowth.py"
def test_cgrowth(test_models_path):
src = test_models_path / "test_cgrowth.stmx"
dest = test_models_path / "test_cgrowth.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
import numpy as np
from test_models.test_cgrowth import simulation_model

@@ -1422,13 +1307,12 @@ sim = simulation_model()

def test_derivn():
import os
src = "./test_models/test_derivn.stmx"
dest = "./test_models/test_derivn.py"
def test_derivn(test_models_path):
src = test_models_path / "test_derivn.stmx"
dest = test_models_path / "test_derivn.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
import numpy as np
from test_models.test_derivn import simulation_model

@@ -1448,13 +1332,11 @@ sim = simulation_model()

def test_interpolate():
import os
def test_interpolate(test_models_path):
src = "./test_models/test_interpolate.stmx"
dest = "./test_models/test_interpolate.py"
src = test_models_path / "test_interpolate.stmx"
dest = test_models_path / "test_interpolate.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
import numpy as np
from test_models.test_interpolate import simulation_model

@@ -1467,13 +1349,12 @@ sim = simulation_model()

def test_normalcdf():
import os
src = "./test_models/test_normalcdf.stmx"
dest = "./test_models/test_normalcdf.py"
def test_normalcdf(test_models_path):
src = test_models_path / "test_normalcdf.stmx"
dest = test_models_path / "test_normalcdf.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
import numpy as np
from test_models.test_normalcdf import simulation_model

@@ -1493,14 +1374,13 @@ sim = simulation_model()

def test_invnorm():
import os
src = "./test_models/test_invnorm.stmx"
dest = "./test_models/test_invnorm.py"
def test_invnorm(test_models_path):
src = test_models_path / "test_invnorm.stmx"
dest = test_models_path / "test_invnorm.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
from scipy.stats import norm
import numpy as np
from test_models.test_invnorm import simulation_model

@@ -1517,14 +1397,11 @@ sim = simulation_model()

def test_safediv():
import os
def test_safediv(test_models_path):
src = "./test_models/test_safediv.stmx"
dest = "./test_models/test_safediv.py"
src = test_models_path / "test_safediv.stmx"
dest = test_models_path / "test_safediv.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
from scipy.stats import norm
import numpy as np
from test_models.test_safediv import simulation_model

@@ -1539,15 +1416,12 @@ sim = simulation_model()

def test_doublequote(test_models_path):
from BPTK_Py.sdcompiler.compile import compile_xmile
def test_doublequote():
import os
import numpy as np
from BPTK_Py.sdcompiler.compile import compile_xmile
src = "./test_models/test_doublequote.stmx"
dest = "./test_models/test_doublequote.py"
src = test_models_path / "test_doublequote.stmx"
dest = test_models_path / "test_doublequote.py"
target = "py"
compile_xmile(src, dest, target)
assert os.path.isfile(dest)
assert dest.is_file()
import numpy as np
from test_models.test_doublequote import simulation_model

@@ -1561,8 +1435,5 @@ sim = simulation_model()

def test_teardown():
import os
files = os.listdir("test_models/")
def test_teardown(test_models_path):
for file in files:
if file.endswith(".py"):
os.remove("test_models/" + file)
for file_path in test_models_path.glob("*.py"):
file_path.unlink()

Sorry, the diff of this file is not supported yet

Metadata-Version: 2.1
Name: BPTK-Py
Version: 1.9.0
Summary: A python simulation engine for System Dynamics & Agent based models
Home-page: https://www.transentis.com/business-prototyping-toolkit/en
Author: transentis labs GmbH
Author-email: support@transentis.com
License: MIT
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Description-Content-Type: text/markdown
License-File: LICENSE
# Business Prototyping Toolkit for Python
__System Dynamics and Agent-based Modeling in Python__
The Business Prototyping Toolkit for Python (BPTK-Py) is a computational modeling framework that enables you to build simulation models using System Dynamics (SD) and/or agent-based modeling (ABM) natively in Python and manage simulation scenarios with ease.
Next to providing the necessary SD and ABM language constructs to build simulation models directly in Python, the framework also includes a compiler for transpiling System Dynamics models conforming to the XMILE standard into Python code.
This means you can build models in a XMILE-compatible visual modeling environment (such as [Stella](http://www.iseesystems.com) or [iThink](http://www.iseesystems.com)) and then use them _independently_ in an Python environment.
The best way to get started with BPTK-Py is to read the [Quickstart](https://bptk.transentis.com/quickstart/quickstart.html) that is part ot the extensive [online documentation](http://bptk.transentis.com). The Quickstart provides a _single page_ overview of all the computational modeling techniques supported by BPTK.
## Main Features
* The objective of the framework is to let the modeller concentrate on building simulation models by providing a seamless interface for managing model settings and scenarios and for plotting simulation results.
* The BPTK-Py framework supports System Dynamics models in XMILE Format, native SD models using a domain-specific language for System Dynamics (SD DSL) and native Agent-based models. You can also build hybrid SD-ABM-Models natively in Python.
* All plotting is done using [Matplotlib](http://www.matplotlib.org).
* Simulation results are returned as [Pandas dataframes](http://pandas.pydata.org) and thus can easily be used for analytics.
* Model settings and scenarios are kept in JSON files. These settings are automatically loaded by the framework upon initialization, as are the model classes themselves. This makes interactive modeling, coding and testing very painless, especially if using the Jupyter notebook environment.
## Getting Help
BPTK-Py is developed and maintained by [transentis labs](http://www.transentis.com/business-prototyping-toolki/en/).
The first place to go to for help and installation instructions is the [online documentation](http://bptk.transentis.com).
The [Quickstart](https://bptk.transentis.com/quickstart/quickstart.html) provides a _single page_ overview of all the modeling techniques supported by BPTK.
The online documentation is generated from an extensive set of Jupyter notebooks, the __BPTK Tutorial__. The tutorial is available as a [git repository](https://github.com/transentis/bptk_py_tutorial) on GitHub.
Our [Business Prototyping Toolkit Meetup Group](https://www.transentis.com/business-prototyping-toolkit-meetup/en/) gathers online regularly. This is a good place to see BPTK in action, ask questions and suggest new features. We record every session and you can _view past recordings_ on the [meetup homepage](https://www.transentis.com/resources/business-prototyping-toolkit-meetup).
We used BPTK to build our implementation of the infamous [Beer Distribution Game](https://beergame.transentis.com).
Our [beergame repository](https://github.com/transentis/bptk_py_tutorial/tree/master/model_library/beergame) contains Jupyter notebooks that analyse the Beergame in-depth and also provides XMILE, SD DSL and Agent-based versions of the Beergame.
For any questions our suggestions you have regarding BPTK, please contact us at: [support@transentis.com](mailto:support@transentis.com).
## Changelog
### 1.9.0
* BPTKServer: `run` endpoint now also works for agent-based models
* Model: Add `configure_agent`, `configure_properties` and `delete_agent(s)` methods
* Bump versions of key dependencies
### 1.8.0
* BPTKServer: Add new endpoint `start-instances` that starts multiple instances in one goo
### 1.7.6
* BPTK: Improve handling of floating point numbers when using small DTs
* ScenarioManagerSD: Fixed an issue that caused models with biflows to be cloned incorrectly
### 1.7.5
* BPTK: Fix that caused a crash when using multiple scenario files for hybrid models
### 1.7.4
* BPTK: Fix bug in reset_scenarios for Hybrid Scenario Managers
### 1.7.3
* BPTK: Update dependencies of Pandas/Matplotlib/Sympy/Parsimonious/Pyyaml/Xlsxwriter/Jinja2/Requests/Jsonpickle/Flask
* Successfully tested with Python 3.11
### 1.7.2
* BPTK: Fix imports of SimpleDashboard class
* BPTK: Update dependency of Scipy, Numpy and Pyyaml
### 1.7.1
* BPTK: reset_cache now also resets the data collector in agent based models
* BPTK: reset_cache calls the reset_cache method on all agents
* BPTK: agents now have a reset_cache method that can be used to reset agent state
* BPTK: Updated dependency on ipywidgets to 8.0.4
### 1.7.0
* BPTK Server: Remote authorization for root, full-metrics and metrics endpoints
* BPTK Server: Add /healthy endpoint
* BPTK Server: stop-instance and load-state are now POST resources
* Bug Fix: Remove debug print message
### 1.6.6
* BPTK: Defer import of matplotlib and ipywidgets until they are needed
### 1.6.5
* BPTK: Hybrid scenarios can now be spread accross multiple scenario files
* BPTK: Remove filename attribute from hybrid scenario manager as it is obsolete
* BPTK: Scenario definitions for SD DSL scenarios now accept a runspecs setting to override starttime, stoptime and dt
* BPTK: begin_session now accepts a settings parameter to override scenario settings
* BPTK Server: begin_session now accepts a settings parameter to override scenario settings
### 1.6.4
* BPTK Server: Simplified bearer token authentication
### 1.6.3
* BPTK Server: Added optional bearer token authentication
### 1.6.2
* BPTK Server: Fixed unsafe external state adapter code
* BPTK Server: start_instance now returns correct content type
### 1.6.1
* SimpleDashboard: Deleted superfluous import statement
* bptk: Small improvements to documentation
### 1.6.0
* BPTK Server: The run_step methods now also support agent-based models
* BPTK Server: A new endpoint streams_steps runs all the steps of a model and streams the results, especially useful for models that run for a long-time.
* SimpleDashboard: A new utility class that allows easy creation of dashboards based on Jupyter Widgets.
### 1.5.3
* BPTK Server: Since v 1.5.0, BPTK Server requires a Python version >= 3.9. The package now informs the user about this upon import. Other parts of the BPTK framework should work fine with older Python3 versions.
### 1.5.2
* BPTK Server: Added file adapter as a concrete example of an external adapter
* BPTK: Improve cleanup of resources when bptk instance is destroyed
### 1.5.1
* BPTK Server: Improvements to the new state externalisation feature
* BPTK Server: Improve cleanup of resources when an instance times out
### 1.5.0
* SD DSL: Added a new module class that makes it easy to structure large models
* BPTK Server: Add new endpoints to allow externalising the instance state
* BPTK Server: Changed the default timeout for equations for instances to 12h
### 1.4.3
* SD DSL: fix to delay function
### 1.4.2
* Small bugfixes in prometheus metrics.
### 1.4.1
* BPTK: Fix to plot_lookup
* BPTK Server: 'flat' version of session results
* SD DSL: small changes to SD functions pulse and delay to make them more robust.
### 1.4.0
* BPTK Server: add metrics endpoint
* SD DSL: fixed missing imports that caused some sddsl functions to throw an exception
### 1.3.12
* BPTK Server: fixed an issue that could lead to race conditions leading to server crashes
### 1.3.11
* BPTK Server: add a keep-alive method to keep instances from timing out
* BPTK Server: start-instances now accepts a timeout structure so that instance timeouts can be set flexibly.
* BPTK Server: fixed an issue that could lead to race conditions leading to server crashes
* XMILE: fixed an issue regarding lookups (graphical functions) that do not contain values on the x-axis
### 1.3.10
* BPTK: fixed an issue in train_scenarios which caused an exception in recent versions of bptk-py
### 1.3.9
* XMILE: Array arithmetic (such as array multiplication,...) within array functions such as SUM is now handled correctly.
### 1.3.8
* XMILE: Arrayed variables that have non-arrayed inputs with "apply to all" set are now handled correctly
### 1.3.7
* XMILE: Ensure the startime and stoptime in transpiled XMILE models are floating point values (e.g. 1.0, not 1)
* XMILE: Top level variables in a model that contains modules are now referenced correctly from submodules
* XMILE: Nested modules are now handled correctly
* XMILE: Array dimensions of length <3 are now handled correctly
### 1.3.6
* Add new method session_results to bptk and corresponding endpoint session-results to Bptk server that allows the session results so far to be retrieved.
### 1.3.5
* Fixed an issue that caused bptk-server to crash if start-instance was called after a previous instance had timed out
### 1.3.4
* Small improvements to the XMILE/SMILE parser regarding element names that include special characters and regarding operators surrounded by newlines.
### 1.3.3
* Return message from end-session resource now correctly reads "session terminated"
### 1.3.2
* Rename package due to issues with test pypi
### 1.3.1
* Add missing package in setup.py
### 1.3.0
* Fix bug in run_scenarios that arose with multiple scenario managers and when return_format was json or dict
* Add begin_session, end_session and run_step methods to bptk
* Add agent endpoint to BptkServer
* BptksServer now takes a bptk_factory function instead of a bptk object in its constructor
* Add start-instance endpoint to BptkServer
* Add begin-session, end-session and run-step endpoint to BptkServer
### 1.2.1
* Improve documentation
* Bugfix for bptk.export_scenarios
### 1.2.0
* Major tidy up of the bptk API, including a number of breaking changes. In particular the run_simulation method has been renamed to run_scenarios and reset_simulation_model was renamed to reset_scenario_cache. A number of rarely used methods have been removed.
* Documentation improved and extended.
* Internal refactoring.
### 1.1.27
* Fix bug in XMILE compiler regrading parsing of names that start with a keyword
### 1.1.26
* Fix bug in XMILE compiler that causes parsing of if/then/else structures to fail under some circumstances
* Fix bug in XMILE pulse function that causes the function to misbehave in some circumstances
* Fix bug in XMILE previous function that causes the function to misbehave in some circumstances
### 1.1.25
* Improve error handling and fault tolerance on BptkServer
### 1.1.24
* Update to BptkServer internals
### 1.1.23
* Add a new experimental feature that allows REST APIs for simulation models to be set up easily.
### 1.1.22
* SD DSL: Add python power operator (**) to all SD DSL operators
* XMILE: Ensure SAFEDIV works in complex expressions
### 1.1.21
* Improve handling of SAFEDIV in SD compiler
### 1.1.20
* Fix for the SD compiler regarding dimension names usage
### 1.1.19
* Little fix regarding the SD-Compiler
### 1.1.18
* Improvement of SD compiler: Support for empty initial value of ``DELAY`` function. Support for dimension names as arguments for functions (e.g. ``SIZE(<dimension>)``)
### 1.1.17
* Improvement of Extended Data Collector: Renamed to Agent Data Collector and code optimizations
### 1.1.16
* Bugfix for the plotting component that solves compatibility issues with newer versions of matplotlib
### 1.1.15
* New dataCollector for retrieving agent-wise data (Refer to [BPTK-Py Tutorial](https://github.com/transentis/bptk_py_tutorial) for more info)
### 1.1.14
* Fixed a bug in the interactive scenario component that caused scenarios being plotted multiple times
* Fixed a bug that caused the SD operator ``delay`` to not accept floating point values and fixed a bug that caused the same to be parsed incorrectly in some cases.
### 1.1.13
* Fixed a bug in the XMILE Converter that prevented the SAFEDIV operator to be parsed correctly
### 1.1.12
* SD-DSL: Fixed a bug that caused converter equations (subtraction and division) to be computed incorrectly.
### 1.1.11
* SD-DSL: Added support for right-hand side addition and subtraction to support equations such as ``converter.equation = 1 - b``
* Visualisation for SD-DSL elements now follows conventions to work properly with Matplotlib 3.3+
### 1.1.10
* Visualisation using matplotlib now follows conventions to work properly with Matplotlib 3.3+
### 1.1.9
* SD-DSL: System Dynamics element such as converters did not implement comparison operators (">", "<", ">=", "==", "!="). They have been added
### 1.1.8
* Another bugfix for series renaming. Simplified the code for renaming by using Pandas' standard method ``rename``
### 1.1.7
* Bugfix for ``plot_scenarios``: The ``series_names`` replacer did not work properly for when only one scenario manager / scenario is given.
### 1.1.6
* Bugfix for XMILE compiler: A little error in the parser prevented certain models being parsed correctly
* Bugfix for ``plot_scenarios``: The new error messages showed up for Agent based models although the scenarios were present
### 1.1.5
* The XMILE compiler is a great tool that handles model conversion from XMILE SD Models to Python. For compatibility and readability, we change the equation names to camelCasing upon conversion. This might be confusing for some users. That's why we decided to give you a new function call that lists all equations for System Dynamics Models. Simply run ``bptk.list_equations()`` (optionally add scenario manager(s) and scenario(s)) and get an overview over available model elements. More details [in our documentation](https://bptk.transentis.com/en/latest/docs/xmile/how-to/how_to_working_with_XMILE/how_to_working_with_XMILE.html).
* Improved error messages. In previous versions, a long error trace was printed when an equation was not found. Now you get a neat error message output wiht hints as to why the plotting failed.
* If an equation / scenario / scenario manager is not found, ``BPTK_Py`` gives hints on which similar equations / scenarios / scenario managers might be available for use.
* Register XMILE models without having to follow the directory structure: ``BPTK_PY`` scans the ``scenarios`` folder upon startup to find new scenario managers and XMILE / ABM models. We developed a simpler way to add simulation models during runtime without having to add scenarios beforehand: ``bptk.register_model("<path_to_itmx_stmx>","<modelname>")``. You can then easily simulate the model just as you're used to.
### 1.1.4
XMILE equations make use of double-quote enclosed identifiers in case it actually looks like a function call. For example, ``100*"Identifier(enclosed)"`` is a valid equation where one element (stock/flow) is called ``Identifier(enclosed)``. However, we were not able to parse this, until now.
Update BPTK-Py using the new update mechanism: [documentation](https://bptk.transentis.com/en/latest/docs/usage/installation.html#keeping-bptk-py-up-to-date)
### 1.1.3
We figured that the update mechanisms via ``pip`` might be confusing sometimes, especially for non-programmers. This is
why we decided to implement an update mechanism. Details are available in the [documentation](https://bptk.transentis.com/en/latest/docs/usage/installation.html#keeping-bptk-py-up-to-date)
### 1.1.2
* Bugfix to (XMILE) SD Compiler: Added support for array expressions within function calls. We had trouble with equations that contain another expression within a function call. E.g. ``DELAY(arrayedElement[1,2]*5, 1, 1)`` was not supported.
* Improvement to (XMILE) SD Compiler: Removed replacement of currency symbols (``€``, ``$`` etc.) and percentage signs with abbreviations. We had implemented this in earlier releases but figured it leads to confusion with modellers.
### 1.1.1
* The SD DSL now differentiates flows and biflows. Simply add a biflow using ```biflow = model.biflow(<name>)```.
* The SD DSL now supports: RANDOM, IF, NOT, AND, OR, NAN, SQRT, ROUND and all trigonometric and statistical builtins you know from XMILE. Furthermore the operators support Comparison Operators (>, <, >=, <=, ==, !=) and the modulo operator (x % y).
* RANDOM: ``converter.equation = sd.Random(<min>, <max>)`` draws a uniformly distributed float random number between <min> and <max>
* ROUND: ``converter.equation = sd.Round(sd.random(0,1),2))`` rounds a random number between 0 and 1 to a 2 digit float
* IF: ```converter.equation = sd.If( <condition>, <then> , <else> ) ``` corresponds to ```IF <condition> THEN <then> ELSE <else>```. Each term inside the IF clause can be a SD term again. Example for a valid If clause: ``equation = sd.If(sd.time()>10,sd.random(1,2), 100)``
* AND/OR: ```sd.Or(<left hand side>, <right hand side>)``` and ```sd.And(<left hand side>, <right hand side>)``` for multiple conditions
* NOT: Use ```sd.Not(<condition>)``` for "not" conditions, e.g: ```sd.If(sd.Not(sd.time()>10), 1, 0 )```
* NAN / INF / PI: ``sd.nan()`` returns a NAN value, ``sd.Inf()`` gives you the infinity value, ```sd.pi()``` returns the number pi.
* SQRT: ``sd.sqrt(<value of function>)`` computes the square root
* SIN / TAN / COS: ``sd.sin(x) / sd.cos(x) / sd.tan(x)`` for sinus, cosinus or tangent of x (radians) and of course we also support ARCCOS, ARCSIN, ARCTAN with the same syntax
* SINWAVE / COSWAVE: ``sd.sinwave(amplitude,period)`` / ``sd.coswave(amplitude,period)`` to generate sine / cosine waves with given amplitude and period
* More documentation and how to use the __statistical (random numbers from various distributions) and trigonometric operators__ can be found in our [online documentation](https://bptk.transentis.com/en/latest/docs/sd-dsl/in-depth/in_depth_sd_dsl_functions/in_depth_sd_dsl_functions.html)
* We fixed a bug that caused BPTK to crash when an XMILE model was updated while BPTK was monitoring it
* We fixed SINWAVE in the XMILE transpiler and added support for COSWAVE
### 1.1.0
* We are supporting all XMILE operators now. Note that random numbers with seed are **never** the same as when using Stella Architect's seed! This is due to different random number generators in Python and Stella. We neither support the min / max arguments for the random number operators. Refer to the [documentation](https://bptk.transentis.com/en/latest/docs/usage/limitations.html))
* RUNCOUNT and SENSIRUNCOUNT are not supported and support is not planned.
### 1.0.2
* Bugfix release: Better support for multidimensional arrays
### 1.0.1
* Bugfix release: Fixed an issue with plot_lookup
### 1.0.0
* SD Compiler: Added new operators
* Arrays and Array Operators (MIN, MAX, SUM, MEAN, SELF, SIZE, PROD)
* Statistical operators (COMBINATIONS, BETA, BINOMIAL, FACTORIAL, GAMMA, GAMMALN, EXPRND, GEOMETRIC)
* Trigonometric operators (ARCSIN, ARCCOS, ARCTAN)
* The ``plot_scenarios`` API now supports array calls such as ``stock[*]`` or ``stock[dim1,dim2]``
* SD DSL: ABS, DT, PULSE, STARTTIME, STOPTIME
pandas==2.1.3
matplotlib==3.8.2
scipy==1.11.4
numpy==1.26.2
ipywidgets==8.1.1
pyyaml==6.0.1
xlsxwriter==3.1.9
parsimonious==0.10.0
xmltodict==0.12.0
jinja2==3.1.2
sympy==1.12
distlib==0.3.7
cachetools==5.3.2
requests==2.31.0
flask==3.0.0
jsonpickle==3.0.2
LICENSE
README.md
setup.cfg
setup.py
BPTK_Py/__init__.py
BPTK_Py/bptk.py
BPTK_Py.egg-info/PKG-INFO
BPTK_Py.egg-info/SOURCES.txt
BPTK_Py.egg-info/dependency_links.txt
BPTK_Py.egg-info/not-zip-safe
BPTK_Py.egg-info/requires.txt
BPTK_Py.egg-info/top_level.txt
BPTK_Py/config/__init__.py
BPTK_Py/config/config.py
BPTK_Py/exceptions/__init__.py
BPTK_Py/exceptions/exceptions.py
BPTK_Py/externalstateadapter/__init__.py
BPTK_Py/externalstateadapter/externalStateAdapter.py
BPTK_Py/logger/__init__.py
BPTK_Py/logger/logger.py
BPTK_Py/modeling/__init__.py
BPTK_Py/modeling/agent.py
BPTK_Py/modeling/dataCollector.py
BPTK_Py/modeling/event.py
BPTK_Py/modeling/model.py
BPTK_Py/modeling/scheduler.py
BPTK_Py/modeling/simultaneousScheduler.py
BPTK_Py/modeling/datacollectors/__init__.py
BPTK_Py/modeling/datacollectors/agent_datacollector.py
BPTK_Py/modeling/datacollectors/csv_datacollector.py
BPTK_Py/modeling/datacollectors/kinesis_datacollector.py
BPTK_Py/modelmonitor/__init__.py
BPTK_Py/modelmonitor/file_monitor.py
BPTK_Py/modelmonitor/model_monitor.py
BPTK_Py/modelparser/__init__.py
BPTK_Py/modelparser/json_model_parser.py
BPTK_Py/modelparser/meta_model_creator.py
BPTK_Py/modelparser/parser_factory.py
BPTK_Py/modelparser/yaml_model_parser.py
BPTK_Py/scenariomanager/__init__.py
BPTK_Py/scenariomanager/scenario.py
BPTK_Py/scenariomanager/scenario_manager.py
BPTK_Py/scenariomanager/scenario_manager_factory.py
BPTK_Py/scenariomanager/scenario_manager_hybrid.py
BPTK_Py/scenariomanager/scenario_manager_sd.py
BPTK_Py/scenariorunners/__init__.py
BPTK_Py/scenariorunners/hybrid_runner.py
BPTK_Py/scenariorunners/scenario_runner.py
BPTK_Py/scenariorunners/sd_runner.py
BPTK_Py/sdcompiler/compile.py
BPTK_Py/sdcompiler/sdmodel.py
BPTK_Py/sdcompiler/generator/__init__.py
BPTK_Py/sdcompiler/generator/contextBuilder.py
BPTK_Py/sdcompiler/generator/py/__init__.py
BPTK_Py/sdcompiler/generator/py/jinja_template.py
BPTK_Py/sdcompiler/generator/py/py.py
BPTK_Py/sdcompiler/parsers/__init__.py
BPTK_Py/sdcompiler/parsers/smile/__init__.py
BPTK_Py/sdcompiler/parsers/smile/grammar.py
BPTK_Py/sdcompiler/parsers/xmile/__init__.py
BPTK_Py/sdcompiler/parsers/xmile/xmile.py
BPTK_Py/sdcompiler/plugins/__init__.py
BPTK_Py/sdcompiler/plugins/complexFunctions.py
BPTK_Py/sdcompiler/plugins/expandArrays.py
BPTK_Py/sdcompiler/plugins/filterGhosts.py
BPTK_Py/sdcompiler/plugins/fixLabels.py
BPTK_Py/sdcompiler/plugins/makeAbsolute.py
BPTK_Py/sdcompiler/plugins/replaceDimensionNames.py
BPTK_Py/sdcompiler/plugins/resolveAsterisk.py
BPTK_Py/sdcompiler/plugins/resolveSelf.py
BPTK_Py/sdcompiler/plugins/sanitizeNames.py
BPTK_Py/sdcompiler/plugins/sortEntities.py
BPTK_Py/sdcompiler/plugins/stockExpressions.py
BPTK_Py/sddsl/__init__.py
BPTK_Py/sddsl/biflow.py
BPTK_Py/sddsl/constant.py
BPTK_Py/sddsl/converter.py
BPTK_Py/sddsl/element.py
BPTK_Py/sddsl/flow.py
BPTK_Py/sddsl/functions.py
BPTK_Py/sddsl/module.py
BPTK_Py/sddsl/operators.py
BPTK_Py/sddsl/stock.py
BPTK_Py/sdsimulation/__init__.py
BPTK_Py/sdsimulation/sd_simulation.py
BPTK_Py/server/__init__.py
BPTK_Py/server/bptkServer.py
BPTK_Py/util/__init__.py
BPTK_Py/util/didyoumean.py
BPTK_Py/util/floating_point.py
BPTK_Py/util/lookup_data.py
BPTK_Py/util/serializer.py
BPTK_Py/util/statecompression.py
BPTK_Py/visualizations/__init__.py
BPTK_Py/visualizations/simple_dashboard.py
BPTK_Py/visualizations/visualize.py
BPTK_Py/widgets/__init__.py
BPTK_Py/widgets/agentstatuswidget.py
BPTK_Py/widgets/widget.py
tests/test_bptk.py
tests/test_external_state.py
tests/test_sddsl.py
tests/test_server.py
tests/test_xmile.py

Sorry, the diff of this file is too big to display