Repository: BlockScience/cadCAD Branch: master Commit: dff463842775 Files: 101 Total size: 840.0 KB Directory structure: gitextract_5t5ec52q/ ├── .github/ │ ├── FUNDING.yml │ └── workflows/ │ ├── cadcad-ci.yml │ └── cadcad-publish.yml ├── .gitignore ├── AUTHORS.txt ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE.txt ├── README.md ├── ascii_art.py ├── cadCAD/ │ ├── __init__.py │ ├── configuration/ │ │ ├── __init__.py │ │ └── utils/ │ │ ├── __init__.py │ │ ├── depreciationHandler.py │ │ ├── policyAggregation.py │ │ └── userDefinedObject.py │ ├── diagram/ │ │ ├── __init__.py │ │ └── config_diagram.py │ ├── engine/ │ │ ├── __init__.py │ │ ├── execution.py │ │ ├── simulation.py │ │ └── utils.py │ ├── tools/ │ │ ├── __init__.py │ │ ├── execution/ │ │ │ ├── __init__.py │ │ │ └── easy_run.py │ │ ├── preparation.py │ │ ├── profiling/ │ │ │ ├── __init__.py │ │ │ ├── profile_run.py │ │ │ └── visualizations.py │ │ ├── types.py │ │ └── utils.py │ ├── types.py │ └── utils/ │ ├── __init__.py │ ├── execution.py │ ├── jupyter.py │ └── sys_config.py ├── documentation/ │ ├── Historically_State_Access.md │ ├── Policy_Aggregation.md │ ├── README.md │ ├── Simulation_Execution.md │ ├── System_Configuration.md │ ├── System_Model_Parameter_Sweep.md │ ├── __init__.py │ ├── cadCAD-v0.4.23-Model-Upgrade-Guide.md │ ├── cadCAD-v0.4.27-Model-Upgrade-Guide.md │ ├── cadCAD-v0.4.28-Model-Upgrade-Guide.md │ └── examples/ │ ├── __init__.py │ ├── cadCAD_diagram.ipynb │ ├── cadCAD_tools_example.ipynb │ ├── example_1.py │ ├── historical_state_access.py │ ├── param_sweep.py │ ├── policy_aggregation.py │ ├── sys_model_A.py │ ├── sys_model_AB_exec.py │ ├── sys_model_A_exec.py │ ├── sys_model_B.py │ └── sys_model_B_exec.py ├── expected_results/ │ ├── param_sweep_4.pkl │ ├── param_sweep_5.pkl │ ├── param_sweep_psub0_4.pkl │ ├── param_sweep_timestep1_4.pkl │ ├── policy_agg_4.pkl │ └── policy_agg_5.pkl ├── requirements.txt ├── setup.py └── testing/ ├── __init__.py ├── experiments/ │ └── __init__.py ├── generic_test.py ├── models/ │ ├── __init__.py │ ├── param_sweep.py │ └── policy_aggregation.py ├── results_comparison.py ├── test_additional_objs.py ├── test_arg_count.py ├── test_param_count.py ├── test_print.py ├── test_results_signature.py ├── test_row_count.py ├── test_runs.py ├── tests/ │ ├── __init__.py │ ├── a_b_tests/ │ │ ├── 0_4_23_record_count.json │ │ └── multi_model_row_count_0_4_23.py │ ├── append_mod_test.py │ ├── expected_results/ │ │ ├── param_sweep_4.pkl │ │ ├── param_sweep_5.pkl │ │ ├── param_sweep_psub0_4.pkl │ │ ├── param_sweep_timestep1_4.pkl │ │ ├── policy_agg_4.pkl │ │ └── policy_agg_5.pkl │ ├── import_cadCAD.ipynb │ ├── test_cadCAD_exp.py │ ├── test_import_cadCAD_test.py │ ├── test_multi_model_row_count.py │ ├── test_param_sweep.py │ ├── test_policy_aggregation.py │ ├── test_run1psub0.py │ ├── test_runs_not_zero.py │ └── test_timestep1psub0.py ├── tools/ │ └── test_tools.py └── utils.py ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/FUNDING.yml ================================================ # These are supported funding model platforms github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] patreon: # Replace with a single Patreon username open_collective: cadcad1 ko_fi: # Replace with a single Ko-fi username tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry liberapay: # Replace with a single Liberapay username issuehunt: # Replace with a single IssueHunt username otechie: # Replace with a single Otechie username lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] ================================================ FILE: .github/workflows/cadcad-ci.yml ================================================ # This workflow will install Python dependencies and run tests with multiple versions of Python name: cadCAD CI on: push: branches: [ "master" ] pull_request: branches: [ "master" ] workflow_dispatch: permissions: contents: read jobs: windows-build: if: false continue-on-error: true runs-on: windows-latest strategy: matrix: python-version: ["3.9", "3.10", "3.11", "3.12"] steps: - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} cache: 'pip' - name: Display Python version run: python -c "import sys; print(sys.version)" - name: Install test and build dependencies run: | python -m pip install --upgrade pip python -m pip install jupyter pip install -r requirements.txt - name: Build cadCAD shell: cmd run: | python setup.py bdist_wheel for %%x in ("dist\*.whl") do python -m pip install %%x --force-reinstall - name: Run tests run: | python -m pytest build: continue-on-error: true strategy: matrix: python-version: ["3.9", "3.10", "3.11", "3.12"] os: [ubuntu-latest, macos-latest] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} cache: 'pip' - name: Display Python version run: python -c "import sys; print(sys.version)" - name: Install test and build dependencies run: | python -m pip install --upgrade pip python -m pip install jupyter pip install -r requirements.txt - name: Build cadCAD run: | python setup.py bdist_wheel python -m pip install dist/*.whl --force-reinstall - name: Run tests run: | python -m pytest ================================================ FILE: .github/workflows/cadcad-publish.yml ================================================ # This workflow will publish the cadCAD library to PyPI when a release is created name: cadCAD Publish on: release: types: [published] jobs: pypi-publish: name: Upload release to PyPI if: startsWith(github.ref, 'refs/tags/') runs-on: ubuntu-latest environment: name: pypi url: https://pypi.org/p/cadCAD permissions: id-token: write steps: - uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: '3.12' - name: Install dependencies run: | python -m pip install --upgrade pip pip install -r requirements.txt - name: Build cadCAD run: | python setup.py bdist_wheel - name: Publish package uses: pypa/gh-action-pypi-publish@release/v1 ================================================ FILE: .gitignore ================================================ *.idea *.vscode *.ipynb_checkpoints *.DS_Store *.eggs *.pytest_cache *.mypy_cache *.csv *.egg-info *.sqlite3 *.pyc *venv *external_data *sys_exec.py */__pycache__ *.DS_Store *notes.* *announcement.md *dist.py */poc __pycache__ Pipfile Pipfile.lock build results result notebooks client_work monkeytype venv notes.* announcement.md testing/tests/a_b_tests/venv_0_4_23 simulations/tickets simulations/validation simulations/poc/local/ simulations/regression_tests/poc simulations/regression_tests/poc_configs dist/* testing/tests/import_cadCAD.nbconvert.ipynb testing/tests/cadCAD_memory_address.json ================================================ FILE: AUTHORS.txt ================================================ Authors ======= cadCAD was originally implemented by Joshua E. Jodesty and designed by Michael Zargham, Markus B. Koch, and Matthew V. Barlin in 2018. Since then, upgrades and improvements were further committed by Danilo L. Bernardineli, Tyler D. Mace and Emanuel Lima. Current Project Maintainers: - Emanuel Lima @emanuellima1 - Michael Zargham @mzargham Active and Past Contributors: - Joshua E. Jodesty @JEJodesty - Markus B. Koch @markusbkoch - Matthew V. Barlin @matttyb80 - Michael Zargham @mzargham - Danilo L. Bernardineli @danlessa - Tyler D. Mace @tylerdmace - Emanuel Lima @emanuellima1 - Zixuan Zhang @zixuanzh - Charles Rice @charles-rice - Benjamin Scholz @BenSchZA We’d also like to thank: - Andrew Clark @aclarkData - Nick Hirannet @nick-phl-7 - Jonathan Gabler - Harry Goodnight @ - Charlie Hoppes - Nikhil Jamdade - Chris Frazier - Griff Green @GriffGreen - Isaac @eenti - Jonny Dubowsky @jonnydubowsky - Sem Brestels @sembrestels - @fjribi - Andrea Maria Piana @cammellos ================================================ FILE: CHANGELOG.md ================================================ # Changelog: ## 0.5.3 - April 19, 2024 ### Bugs fixed - Solve issue on which nested initial states are being copied from one run to another ([#357](https://github.com/cadCAD-org/cadCAD/pull/357)); - Created add_parameter_labels ([#360](https://github.com/cadCAD-org/cadCAD/pull/360)); - Add supress_print attribute to the Executor class for silencing prints and tqdm ([#361](https://github.com/cadCAD-org/cadCAD/pull/361)); ## 0.5.2 - April 11, 2024 ### Bugs fixed - fix: easy supports list/array/sequence type as parameter ([#348](https://github.com/cadCAD-org/cadCAD/pull/348)); - Update setup.py to include tqdm package ([#342](https://github.com/cadCAD-org/cadCAD/pull/342)); - Debug M dictionairy unpacking in utils ([#343](https://github.com/cadCAD-org/cadCAD/pull/343)); - Add test for counting the parameters argument inside policies and SUFs ([#345](https://github.com/cadCAD-org/cadCAD/pull/345)); - Fix sweep_cartesian_product such that it works nicely with easy_run ([#355](https://github.com/cadCAD-org/cadCAD/pull/355)); - Update easy_run.py ([#356](https://github.com/cadCAD-org/cadCAD/pull/356)); ## 0.5.1 - December 21, 2023 ### Bugs fixed - Fixed a bug where the single_proc mode would result in a missing simulation key ([#332](https://github.com/cadCAD-org/cadCAD/issues/332)); - Fixed a bug where the single_proc mode would not return results ([#335](https://github.com/cadCAD-org/cadCAD/issues/335)); - Fixed a wrong parameter order when doing single runs ([#337](https://github.com/cadCAD-org/cadCAD/issues/337)). - Added a Windows CI pipeline; ## 0.5.0 - December 20, 2023 ### New User Features - Added toggle for enabling users to deactivate deepcopying. This is done by passing an additional object on the `ExecutionContext`, eg. `ExecutionContext(mode, additional_objs={'deepcopy_off': True})` ### New Submodules - A collection of type annotations for encapsuling `cadCAD` projects is now implemented through the `cadCAD.types` submodules - Added `cadCAD.tools` as a submodule, which is originated from the `cadCAD_tools` Python package. This submodule contains several helper functions for making the simulation experience more straightforward as well as a collection of performance profiling tools. - Added `cadCAD.diagram` as a submodule, which is originated from the `cadCAD_diagram` Python package. This submodule contains functions for programatically generating block diagrams from existing models. - More informative error messages when policies and SUFs are wrongly implemented. (Issues #288 and #258) ### Backend Improvements - Merged repo with the `cadCAD_legacy_devel`, which includes performance improvements. In particular, simulations will start up faster due to code optimizations. - `cadCAD` now uses `pytest` as the testing framework. This was made possible by isolating the existing tests and wrapping them into functions. ### Fixes - cadCAD is now Python 3.10+ compatible (Issue #306 and #301) - Proper support for `ExecutionMode.single_mode` (Issue #253 and #254) ## September 28, 2021 ### New Features: * **ver. ≥ `0.4.28`:** * #### [Experiments](documentation#experiments) * #### System Model Configuration * Configurations (`cadCAD.utils.Configuration`'s) are now accessed via the `configs` member of `cadCAD.configuration.Experiment`. [Example:](documentation#experiments) `cadCAD.configuration.Experiment().configs` * `cadCAD.configs` has been re-included for backwards compatibility and has been assigned `cadCAD.experiment.configs` * #### Experiments * `cadCAD.configuration.Experiment()` is unique representation of an experiment of one or more configured System Models. * The `cadCAD` module now contains a default Experiment object `cadCAD.experiment` as an instantiation of `cadCAD.configuration.Experiment()` * An `Experiment`'s `append_model` method stores multiple system model `Configuration`'s for simulation execution within `cadCAD.configuration.Experiment().configs`. `cadCAD.configuration.Experiment().model_ids` contains system model labels and/or indexes for `cadCAD.configuration.Experiment().configs` * The `Experiment`'s `append_model` method is defined with `model_id` parameter that accepts a system model label. * If duplicate `model_id`'s are specified, an index is appended to the label after the `@` symbol. (Example: `cadCAD.configuration.Experiment().model_ids = ['sys_model', 'sys_model@1', 'sys_model@2', ...]`) * If `model_id`'s are not specified or duplicate, the label is auto-generated as a string indicating the system model index within `cadCAD.configuration.Experiment().configs`. (Example of unspecified system models at indexes 1, 3, and 4: `cadCAD.configuration.Experiment().model_ids = ['sys_model', '1', 'sys_model@2', '3', '4', ...]`) * #### [Upgrade Guide:](https://github.com/cadCAD-org/cadCAD/blob/master/documentation/cadCAD-v0.4.28-Model-Upgrade-Guide.md) specific to feature changes / additions ## August 25, 2021 ### New Features: * **ver. ≥ `0.4.27`:** * #### [Experiments](documentation#experiments) * #### System Model Configurations * Configurations (`cadCAD.utils.Configuration`'s) as are no longer a part of the `cadCAD` module (as `cadCAD.configs`) and are now accessed via the `configs` member of `cadCAD.configuration.Experiment`. [Example:](documentation#experiments) `cadCAD.configuration.Experiment().configs` * #### Experiments * `cadCAD.configuration.Experiment` is unique representation of an experiment of one or more configured System Models. An `Experiment`'s `append_model` method stores multiple system model `Configuration`'s for simulation execution. * The `Experiment`'s `append_model` method requires a `model_id` parameter that is auto-created as `'sys_model_#'`. * **Requirements:** * Users must use different `model_id`'s when appending multiple System Model Configurations. * Users can no longer use the `config_list` method of `cadCAD.configuration.Experiment` * **Backwards Compatibility:** The `append_model` method of `cadCAD.configuration.Experiment` can also be used as the `append_configs` method. * Removed [Nix](https://nixos.org/) * #### [Upgrade Guide:](https://github.com/cadCAD-org/cadCAD/blob/master/documentation/cadCAD-v0.4.27-Model-Upgrade-Guide.md) specific to feature changes / additions * **Fixes:** * [#248](https://github.com/cadCAD-org/cadCAD/issues/248) * The previous release was returning partial results. An A/B test for this has been included and will be for future releases * [#242](https://github.com/cadCAD-org/cadCAD/issues/242) * Parallelized simulations enabled with the re-inclusion of `ProcessPool`. * [#257](https://github.com/cadCAD-org/cadCAD/issues/257) * ValueError for runs accepted by the `cadCAD.configuration.Experiment().append_model` via the `sim_configs` no longer gives mis-leading error message if catching a non-related ValueError * [#252](https://github.com/cadCAD-org/cadCAD/issues/252) * Jupyter lab and Jupyter notebook recognises cadCAD module ## September 22, 2020 #### [Multi - System Model Execution](https://github.com/cadCAD-org/cadCAD/blob/master/documentation/Simulation_Execution.md#multiple-simulation-execution) * **ver. ≥ `0.4.23`:** * **Hot-Fix:** [#203](https://github.com/cadCAD-org/cadCAD/pull/203) (**No Breaking Changes**) * Multi - System Model simulation results will no longer return truncated results (exclude the results of the last `cadCAD.configuration.Configuration` appended to `cadCAD.configs`). * Issue: [#195](https://github.com/cadCAD-org/cadCAD/issues/195) * Parameter Sweep value `M` (Params) requires up to a maximum of 2 distinct lengths ## August 5, 2020 #### [Experiments](documentation#experiments) * `cadCAD.configuration.Experiment` (Alpha) is in development and needed to be released to support the implementation of web applications and proprietary feature extensions. It is intended to represent a unique identifier of an experiment of one or more configured System Models. For this reason, `append_configs` is a method of `cadCAD.configuration.Experiment`. As of now it does not support multi - system model simulation because configurations are still appended globally despite `append_config` being a method of Experiment. ##### Examples: * **ver. ≥ `0.4.22`:** ```python from cadCAD.configuration import Experiment exp = Experiment() exp.append_configs(...) ``` * **ver. `0.3.1`:** *Deprecated* ```python from cadCAD.configuration import append_configs append_configs(...) ``` ## June 22, 2020 * Bug Fix: Multiprocessing error for Windows ## June 19, 2020 ## New Features: #### [Local Execution Mode (Default)](documentation/Simulation_Execution.md#simulation-execution-modes) * Local Execution Mode (Default): Implicit parallelization of Monte-Carlo / Stochastic simulations (Automatically selects Multi-Threaded Mode if simulations are configured for more than a single run) * **Backwards Compatibility:** `cadCAD.engine.ExecutionMode` accepts legacy execution modes from ver. `0.3.1` ##### Examples: * **ver. ≥ `0.4.22`:** ```python from cadCAD.engine import ExecutionMode, ExecutionContext exec_mode = ExecutionMode() local_ctx = ExecutionContext(context=exec_mode.local_mode) ``` * **ver. `0.3.1`:** Multi-Threaded: ```python from cadCAD.engine import ExecutionMode, ExecutionContext exec_mode = ExecutionMode() single_ctx = ExecutionContext(context=exec_mode.multi_proc) ``` Single-Thread: ```python from cadCAD.engine import ExecutionMode, ExecutionContext exec_mode = ExecutionMode() multi_ctx = ExecutionContext(context=exec_mode.single_proc) ``` #### cadCAD Post-Processing Enhancements / Modifications * [**Single Result Dataset**](documentation/Simulation_Execution.md#4-execute-simulation--produce-system-event-dataset) as a 2 dimensional `list` * Returns a single dataset instead of multiple datasets per Monte Carlo simulation as in `0.3.1`: * New System Metrics as dataset attributes: * **Simulation** (Alpha) is a unique identifier being developed to represent Experiments as stated above and will be renamed accordingly * **Subset** is a unique identifier of Monte-Carlo simulations produced by parameter sweeps * Note: Returning a single dataset was originally specified during the project’s inception instead of multiple per simulation ##### Examples: * **ver. ≥ `0.4.22`:** ```python import pandas as pd from tabulate import tabulate from cadCAD.engine import ExecutionMode, ExecutionContext, Executor import system_model_A, system_model_B from cadCAD import configs exec_mode = ExecutionMode() local_ctx = ExecutionContext(context=exec_mode.local_mode) simulation = Executor(exec_context=local_ctx, configs=configs) raw_result, sys_model, _ = simulation.execute() result = pd.DataFrame(raw_result) print(tabulate(result, headers='keys', tablefmt='psql')) ``` Results: ``` +----+------------+-----------+----+---------------------+------------+--------+-----+---------+----------+ | | s1 | s2 | s3 | timestamp | simulation | subset | run | substep | timestep | |----+------------+-----------+----+---------------------+------------+--------+-----+---------+----------| | 0 | 0.0 | 0.0 | 1 | 2018-10-01 15:16:24 | 0 | 0 | 1 | 0 | 0 | | 1 | 1.0 | 4 | 5 | 2018-10-01 15:16:25 | 0 | 0 | 1 | 1 | 1 | | 2 | 2.0 | 6 | 5 | 2018-10-01 15:16:25 | 0 | 0 | 1 | 2 | 1 | | 3 | 3.0 | [ 30 300] | 5 | 2018-10-01 15:16:25 | 0 | 0 | 1 | 3 | 1 | | 4 | 0 | 0 | 1 | 2018-10-01 15:16:24 | 1 | 0 | 1 | 0 | 0 | | 5 | 1 | 0 | 5 | 2018-10-01 15:16:25 | 1 | 0 | 1 | 1 | 1 | | 6 | a | 0 | 5 | 2018-10-01 15:16:25 | 1 | 0 | 1 | 2 | 1 | | 7 | ['c', 'd'] | [ 30 300] | 5 | 2018-10-01 15:16:25 | 1 | 0 | 1 | 3 | 1 | +----+------------+-----------+----+---------------------+------------+--------+-----+---------+----------+ ``` * **ver. `0.3.1`:** ```python import pandas as pd from tabulate import tabulate from cadCAD.engine import ExecutionMode, ExecutionContext, Executor import system_model_A, system_model_B from cadCAD import configs exec_mode = ExecutionMode() multi_ctx = ExecutionContext(context=exec_mode.multi_proc) simulation = Executor(exec_context=multi_ctx, configs=configs) i = 0 config_names = ['sys_model_A', 'sys_model_B'] for raw_result, _ in simulation.execute(): result = pd.DataFrame(raw_result) print() print(f"{config_names[i]} Result: System Events DataFrame:") print(tabulate(result, headers='keys', tablefmt='psql')) print() i += 1 ``` Results: ``` +----+------------+-----------+----+---------------------+-----+---------+----------+ | | s1 | s2 | s3 | timestamp | run | substep | timestep | |----+------------+-----------+----+---------------------+-----+---------+----------| | 0 | 0.0 | 0.0 | 1 | 2018-10-01 15:16:24 | 1 | 0 | 0 | | 1 | 1.0 | 4 | 5 | 2018-10-01 15:16:25 | 1 | 1 | 1 | | 2 | 2.0 | 6 | 5 | 2018-10-01 15:16:25 | 1 | 2 | 1 | | 3 | 3.0 | [ 30 300] | 5 | 2018-10-01 15:16:25 | 1 | 3 | 1 | | 4 | 0 | 0 | 1 | 2018-10-01 15:16:24 | 1 | 0 | 0 | | 5 | 1 | 0 | 5 | 2018-10-01 15:16:25 | 1 | 1 | 1 | | 6 | a | 0 | 5 | 2018-10-01 15:16:25 | 1 | 2 | 1 | | 7 | ['c', 'd'] | [ 30 300] | 5 | 2018-10-01 15:16:25 | 1 | 3 | 1 | +----+------------+-----------+----+---------------------+-----+---------+----------+ ``` * **Flattened Configuration list:** The `cadCAD.configs` (System Model Configuration) `list` has been **temporarily** flattened to contain single run `cadCAD.configuration.Configuration` objects to both fault-tolerant simulation and elastic workloads. This functionality will be restored in a subsequent release by a class that returns `cadCAD.configs`'s original representation in ver. `0.3.1`. * The conversion utilities have been provided to restore its original representation of configurations with runs >= 1 * [System Configuration Conversions](documentation/System_Configuration.md) * Configuration as list of Configuration Objects (as in ver. `0.3.1`) * New: System Configuration as a Pandas DataFrame * New: System Configuration as list of Dictionaries ##### Examples: * Notes: * `configs` is temporarily returned in a flattened format and reformatted into its intended format * `Configuration` objects at `0x10790e470` and `0x1143dd630` are reconstituted into objects at `0x10790e7b8` and `0x116268908` respectively. * **ver. ≥ `0.4.22`:** ```python from pprint import pprint from documentation.examples import sys_model_A, sys_model_B from cadCAD.configuration.utils import configs_as_objs, configs_as_dataframe, configs_as_dicts from cadCAD import configs flattened_configs = configs print('Flattened Format: Temporary') pprint(flattened_configs) print() print('Intended Format:') intended_configs = configs_as_objs(flattened_configs) pprint(intended_configs) print() ``` Result: ```bash Flattened Format: Temporary [, , , ] Intended Format: [, ] ``` #### Expandable state and policy update parameter space: * Enables the development of feature enhancements that involve the use of additional parameters without requiring users to modify their update parameters spaces when upgrading to newer versions. For this reason state / policy update examples in documentation include an additional `**kwargs` parameter. * [State Updates](documentation/README.md#state-update-functions) * [Policy Updates](documentation/README.md#state-update-functions) ##### Examples: * **ver. ≥ `0.4.22`:** ```python def state_update(_params, substep, sH, s, _input, **kwargs): ... return 'state_variable_name', new_value def policy(_params, substep, sH, s, **kwargs): ... return {'signal_1': value_1, ..., 'signal_N': value_N} ``` * **ver. `0.3.1`:** ```python def state_update(_params, substep, sH, s, _input): ... return 'state_variable_name', new_value def policy(_params, substep, sH, s): ... return {'signal_1': value_1, ..., 'signal_N': value_N} ``` ## May 29, 2020 * Packaging: Add [Nix](https://nixos.org/) derivation and shell for local development and distribution of cadCAD package using Nix. Nix is a powerful package manager for Linux and other Unix systems that makes package management reliable and reproducible, allowing you to share your development and build environments across different machines. ================================================ FILE: CONTRIBUTING.md ================================================ # Contributing to cadCAD :+1::tada: First off, thanks for taking the time to contribute! :tada::+1: The following is a set of guidelines for contributing to cadCAD. Use your best judgment, and feel free to propose changes to this document in a pull request. ### Pull Requests: Pull Request (PR) presented as "->". General Template: `user:branch -> org:staging` Contributing a new feature: `user:feature -> org:staging` Contributing to an existing feature: `user:feature -> org:feature` ### General Advise for Forked Repositories: 1. `git pull fork staging` 2. `git checkout -b feature` (new feature) 3. Apply your awesomeness! (Commit Often) 4. `git push fork feature` 5. Apply a rebase/merge strategy you're comfortable with (Recommended Below). 6. Submit PR from `user:staging` into `org:staging` 7. PR is queued for review 8. PR Reviewed (Update necessary if rejected) 9. PR Approved (There may be circumstances delaying the merge.) 10. Your contribution merged into next feature release on `org:master` ### Recommended Strategy: [Rebase](https://git-scm.com/book/en/v2/Git-Branching-Rebasing) 1. Add cadCAD-org/cadCAD as remote within you forked project locally. 2. `git checkout remote/master` 3. `git pull remote master` 4. `git checkout your_branch` 5. `git rebase master` 6. Resolve merge conflicts (while leveraging rebase commands) 7. `git push fork your_branch` Thanks! :heart: ================================================ FILE: LICENSE.txt ================================================ MIT License Copyright (c) 2018-2020 BlockScience Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ ``` ___________ ____ ________ __ ___/ / ____/ | / __ \ / ___/ __` / __ / / / /| | / / / / / /__/ /_/ / /_/ / /___/ ___ |/ /_/ / \___/\__,_/\__,_/\____/_/ |_/_____/ by cadCAD ver. 0.5.3 ====================================== Complex Adaptive Dynamics o i e m d s p e i u d g t n e r ``` ***cadCAD*** is a Python package that assists in the processes of designing, testing and validating complex systems through simulation, with support for Monte Carlo methods, A/B testing and parameter sweeping. # Getting Started #### Change Log: [ver. 0.5.3](CHANGELOG.md) ## 0. Pre-installation Virtual Environments with [`venv`](https://docs.python.org/3/library/venv.html) (Optional): If you wish to create an easy to use virtual environment to install cadCAD within, please use python's built in `venv` package. ***Create** a virtual environment:* ```bash $ python3 -m venv ~/cadcad ``` ***Activate** an existing virtual environment:* ```bash $ source ~/cadcad/bin/activate (cadcad) $ ``` ***Deactivate** virtual environment:* ```bash (cadcad) $ deactivate $ ``` ## 1. Installation: Requires [>= Python 3.9.0](https://www.python.org/downloads/) **Option A:** Install Using **[pip](https://pypi.org/project/cadCAD/)** ```bash pip3 install cadCAD ``` **Option B:** Build From Source ``` pip3 install -r requirements.txt python3 setup.py sdist bdist_wheel pip3 install dist/*.whl ``` ## 2. Documentation: * [Simulation Configuration](documentation/README.md) * [Simulation Execution](documentation/Simulation_Execution.md) * [Policy Aggregation](documentation/Policy_Aggregation.md) * [Parameter Sweep](documentation/System_Model_Parameter_Sweep.md) * [Display System Model Configurations](documentation/System_Configuration.md) ## 3. Connect: * Website: https://www.cadcad.org * Discord: https://discord.gg/DX9uH8m4qY * Twitter: https://twitter.com/cadcad_org * Forum: https://community.cadcad.org * Github: https://github.com/cadCAD-org * Telegram: https://t.me/cadcad_org ## 4. Contribute to this repository: Follow [this document](CONTRIBUTING.md) to start contributing! ================================================ FILE: ascii_art.py ================================================ production = r''' __________ ____ ________ __ _____/ ____/ | / __ \ / ___/ __` / __ / / / /| | / / / / / /__/ /_/ / /_/ / /___/ ___ |/ /_/ / \___/\__,_/\__,_/\____/_/ |_/_____/ by BlockScience ====================================== Complex Adaptive Dynamics o i e m d s p e i u d g t n e r ''' text = r''' Complex Adaptive Dynamics o i e m d s p e i u d g t n e r ''' block_letters = r''' __________ ____ ________ __ _____/ ____/ | / __ \ / ___/ __` / __ / / / /| | / / / / / /__/ /_/ / /_/ / /___/ ___ |/ /_/ / \___/\__,_/\__,_/\____/_/ |_/_____/ by BlockScience ''' ================================================ FILE: cadCAD/__init__.py ================================================ import os import dill from cadCAD.configuration import Experiment name = "cadCAD" version = "0.5.3" experiment = Experiment() configs = experiment.configs if os.name == "nt": dill.settings["recurse"] = True logo = r""" ___________ ____ ________ __ ___/ / ____/ | / __ \ / ___/ __` / __ / / / /| | / / / / / /__/ /_/ / /_/ / /___/ ___ |/ /_/ / \___/\__,_/\__,_/\____/_/ |_/_____/ by cadCAD """ ================================================ FILE: cadCAD/configuration/__init__.py ================================================ from typing import Dict, Callable, List, Tuple from pandas.core.frame import DataFrame # type: ignore from datetime import datetime from collections import deque from copy import deepcopy import pandas as pd # type: ignore from cadCAD.utils import key_filter from cadCAD.configuration.utils import exo_update_per_ts, configs_as_objs from cadCAD.configuration.utils.depreciationHandler import sanitize_partial_state_updates, sanitize_config class Configuration(): def __init__(self, user_id, model_id, subset_id, subset_window, sim_config={}, initial_state={}, seeds={}, env_processes={}, exogenous_states={}, partial_state_update_blocks={}, policy_ops=[lambda a, b: a + b], session_id=0, simulation_id=0, run_id=1, experiment_id=0, exp_window=deque([0, None], 2), exp_creation_ts=None, **kwargs ) -> None: self.sim_config = sim_config self.initial_state = initial_state self.seeds = seeds self.env_processes = env_processes self.exogenous_states = exogenous_states self.partial_state_update_blocks = partial_state_update_blocks self.policy_ops = policy_ops self.kwargs = kwargs self.session_id = session_id # essentially config id self.experiment_id = experiment_id self.user_id = user_id self.model_id = model_id self.exp_creation_ts = exp_creation_ts self.labeled_jobs = {} self.simulation_id = simulation_id self.subset_id = subset_id self.run_id = run_id self.exp_window = exp_window self.subset_window = subset_window sanitize_config(self) class Experiment(object): def __init__(self): self.exp_creation_ts = str(datetime.utcnow()) self.configs = [] self.sys_configs = [] self.model_job_map, self.model_job_counts = {}, {} self.model_ids = list(self.model_job_map.keys()) self.model_id_queue = [] self.exp_id = 0 self.simulation_id = -1 self.subset_id = 0 self.exp_window = deque([self.exp_id, None], 2) self.subset_window = deque([self.subset_id, None], 2) def append_model( self, user_id='cadCAD_user', model_id=None, sim_configs={}, initial_state={}, seeds={}, raw_exogenous_states={}, env_processes={}, partial_state_update_blocks={}, policy_ops=[lambda a, b: a + b], _exo_update_per_ts: bool = True, **kwargs # config_list=deepcopy(global_configs) ) -> None: _sim_configs = deepcopy(sim_configs) # self.configs = config_list self.simulation_id += 1 try: max_runs = _sim_configs[0]['N'] except KeyError: max_runs = _sim_configs['N'] if _exo_update_per_ts is True: exogenous_states = exo_update_per_ts(raw_exogenous_states) else: exogenous_states = raw_exogenous_states if isinstance(_sim_configs, dict): _sim_configs = [_sim_configs] sim_cnt_local = 0 new_sim_configs = [] for subset_id, t in enumerate(list(zip(_sim_configs, list(range(len(_sim_configs)))))): sim_config = t[0] sim_config['subset_id'] = subset_id sim_config['subset_window'] = self.subset_window N: int = sim_config['N'] for n in range(0, N): sim_config['simulation_id'] = self.simulation_id sim_config['run_id'] = n sim_config['N'] = 1 new_sim_configs.append((sim_config.copy())) sim_cnt_local += 1 if model_id == None: new_model_id = str(len(self.model_ids)) if new_model_id in self.model_ids: model_id = f"model@{len(self.model_ids)}" else: model_id = str(new_model_id) elif model_id != None: if model_id in self.model_ids: model_id = f"{model_id}@{len(self.model_ids)}" else: model_id = str(model_id) run_id = 0 new_model_ids, new_configs = [], [] for sim_config in new_sim_configs: subset_id = sim_config['subset_id'] sim_config['N'] = run_id + 1 if max_runs == 1: sim_config['run_id'] = run_id elif max_runs >= 1: if run_id >= max_runs: sim_config['N'] = run_id - (max_runs - 1) self.exp_window = self.exp_window.copy() config = Configuration( exp_creation_ts=self.exp_creation_ts, sim_config=sim_config, initial_state=deepcopy(initial_state), seeds=seeds, exogenous_states=exogenous_states, env_processes=env_processes, partial_state_update_blocks=partial_state_update_blocks, policy_ops=policy_ops, # session_id=session_id, user_id=user_id, model_id=model_id, session_id=f"{user_id}={sim_config['simulation_id']}_{sim_config['run_id']}", experiment_id=self.exp_id, simulation_id=self.simulation_id, subset_id=subset_id, run_id=sim_config['run_id'], exp_window=self.exp_window, subset_window=self.subset_window ) # self.configs.append(config) new_configs.append(config) new_model_ids.append(model_id) run_id += 1 self.configs += new_configs self.model_id_queue += new_model_ids self.exp_id += 1 self.exp_window.appendleft(self.exp_id) self.sys_configs += configs_as_objs(new_configs) unique_new_model_ids = list(set(new_model_ids)) new_model_job_list = [(model_id, []) for model_id in unique_new_model_ids] for model_id, v in new_model_job_list: if model_id not in self.model_ids: self.model_job_map[model_id] = v self.model_ids.append(model_id) else: except_str = f""" Error: Duplicate model_id in Experiment - \'{model_id}\' in {self.model_ids} -- Specify unique model_id for each use of `.append_model` per `Experiment()` """ raise Exception(except_str) for model_id, job in list(zip(new_model_ids, new_configs)): self.model_job_map[model_id].append(job) self.model_job_counts = dict([(k, len(v)) for k, v in self.model_job_map.items()]) append_configs = append_model class Identity: def __init__(self, policy_id: Dict[str, int] = {'identity': 0}) -> None: self.beh_id_return_val = policy_id def p_identity(self, var_dict, sub_step, sL, s, **kwargs): return self.beh_id_return_val def policy_identity(self, k: str) -> callable: return self.p_identity def no_state_identity(self, var_dict, sub_step, sL, s, _input, **kwargs): return None def state_identity(self, k: str) -> callable: return lambda var_dict, sub_step, sL, s, _input, **kwargs: (k, s[k]) # state_identity = cloudpickle.dumps(state_identity) def apply_identity_funcs(self, identity: callable, df: DataFrame, cols: List[str]) -> DataFrame: """ Apply the identity on each df column, using its self value as the argument. """ fill_values = {col: identity(col) for col in cols} filled_df = df.fillna(fill_values) return filled_df class Processor: def __init__(self, id: Identity = Identity()) -> None: self.id = id self.p_identity = id.p_identity self.policy_identity = id.policy_identity self.no_state_identity = id.no_state_identity self.state_identity = id.state_identity self.apply_identity_funcs = id.apply_identity_funcs def create_matrix_field(self, partial_state_updates, key: str) -> DataFrame: if key == 'variables': identity = self.state_identity elif key == 'policies': identity = self.policy_identity df = pd.DataFrame(key_filter(partial_state_updates, key)) filled_df = self.apply_identity_funcs(identity, df, list(df.columns)) if len(filled_df) > 0: return filled_df else: return pd.DataFrame({'empty': []}) def generate_config(self, initial_state, partial_state_updates, exo_proc ) -> List[tuple[list[callable], List[callable]]]: def no_update_handler(bdf, sdf): if (bdf.empty == False) and (sdf.empty == True): bdf_values = bdf.values.tolist() sdf_values = [[self.no_state_identity] * len(bdf_values) for m in range(len(partial_state_updates))] return sdf_values, bdf_values elif (bdf.empty == True) and (sdf.empty == False): sdf_values = sdf.values.tolist() bdf_values = [[self.p_identity] * len(sdf_values) for m in range(len(partial_state_updates))] return sdf_values, bdf_values else: sdf_values = sdf.values.tolist() bdf_values = bdf.values.tolist() return sdf_values, bdf_values def only_ep_handler(state_dict): sdf_functions = [ lambda var_dict, sub_step, sL, s, _input, **kwargs: (k, v) for k, v in zip(state_dict.keys(), state_dict.values()) ] sdf_values = [sdf_functions] bdf_values = [[self.p_identity] * len(sdf_values)] return sdf_values, bdf_values if len(partial_state_updates) != 0: # backwards compatibility partial_state_updates = sanitize_partial_state_updates(partial_state_updates) bdf = self.create_matrix_field(partial_state_updates, 'policies') sdf = self.create_matrix_field(partial_state_updates, 'variables') sdf_values, bdf_values = no_update_handler(bdf, sdf) zipped_list = list(zip(sdf_values, bdf_values)) else: sdf_values, bdf_values = only_ep_handler(initial_state) zipped_list = list(zip(sdf_values, bdf_values)) return list(map(lambda x: (x[0] + exo_proc, x[1]), zipped_list)) ================================================ FILE: cadCAD/configuration/utils/__init__.py ================================================ import pandas as pd # type: ignore from datetime import datetime, timedelta from collections import Counter from functools import reduce from funcy import curry # type: ignore from cadCAD.types import * from typing import Union, Dict, List from cadCAD.configuration.utils.depreciationHandler import sanitize_partial_state_updates from cadCAD.utils import dict_filter, contains_type, flatten_tabulated_dict, tabulate_dict class TensorFieldReport: def __init__(self, config_proc): self.config_proc = config_proc def create_tensor_field(self, partial_state_updates, exo_proc, keys=['policies', 'variables']): partial_state_updates = sanitize_partial_state_updates(partial_state_updates) # Temporary dfs = [self.config_proc.create_matrix_field(partial_state_updates, k) for k in keys] df = pd.concat(dfs, axis=1) for es, i in zip(exo_proc, range(len(exo_proc))): df['es' + str(i + 1)] = es df['m'] = df.index + 1 return df def configs_as_spec(configs): sim_ids = list(map(lambda x: x.simulation_id, configs)) # sim_ids = [config.simulation_id for config in configs] sim_id_counts = list(Counter(sim_ids).values()) IDed_configs = list(zip(sim_ids, configs)) del sim_ids selected_IDed_configs = dict(IDed_configs) del IDed_configs counted_IDs_configs = list(zip(sim_id_counts, selected_IDed_configs.values())) del sim_id_counts, selected_IDed_configs for runs, config in counted_IDs_configs: config.sim_config['N'] = runs return counted_IDs_configs def configs_as_objs(configs): counted_IDs_configs = configs_as_spec(configs) new_configs = list(map(lambda x: x[1], counted_IDs_configs)) del counted_IDs_configs return new_configs def configs_as_dicts(configs): counted_IDs_configs = configs_as_spec(configs) new_configs = list(map(lambda x: x[1].__dict__, counted_IDs_configs)) del counted_IDs_configs return new_configs def configs_as_dataframe(configs): new_configs = configs_as_dicts(configs) configs_df = pd.DataFrame(new_configs) del new_configs configs_df_columns = list(configs_df.columns) header_cols = ['session_id', 'user_id', 'simulation_id', 'run_id'] for col in header_cols: configs_df_columns.remove(col) return configs_df[header_cols + configs_df_columns] ## System Model def state_update(y, x): return lambda var_dict, sub_step, sL, s, _input, **kwargs: (y, x) def policy(y, x): return lambda _g, step, sL, s, **kwargs: {y: x} def bound_norm_random(rng, low, high): res = rng.normal((high+low)/2, (high-low)/6) if res < low or res > high: res = bound_norm_random(rng, low, high) # return Decimal(res) return float(res) tstep_delta = timedelta(days=0, minutes=0, seconds=30) def time_step(dt_str, dt_format='%Y-%m-%d %H:%M:%S', _timedelta = tstep_delta): dt = datetime.strptime(dt_str, dt_format) t = dt + _timedelta return t.strftime(dt_format) ep_t_delta = timedelta(days=0, minutes=0, seconds=1) def ep_time_step(s_condition, dt_str, fromat_str='%Y-%m-%d %H:%M:%S', _timedelta = ep_t_delta): if s_condition: return time_step(dt_str, fromat_str, _timedelta) else: return dt_str def exo_update_per_ts(ep): # @curried def ep_decorator(f, y, var_dict, sub_step, sL, s, _input, **kwargs): if s['substep'] + 1 == 1: return f(var_dict, sub_step, sL, s, _input, **kwargs) else: return y, s[y] return {es: ep_decorator(f, es) for es, f in ep.items()} # type: ignore def trigger_condition(s, pre_conditions, cond_opp): condition_bools = [s[field] in precondition_values for field, precondition_values in pre_conditions.items()] return reduce(cond_opp, condition_bools) def apply_state_condition(pre_conditions, cond_opp, y, f, _g, step, sL, s, _input, **kwargs): def state_scope_tuner(f): lenf = f.__code__.co_argcount if lenf == 5: return f(_g, step, sL, s, _input) elif lenf == 6: return f(_g, step, sL, s, _input, **kwargs) if trigger_condition(s, pre_conditions, cond_opp): return state_scope_tuner(f) else: return y, s[y] def var_trigger(y, f, pre_conditions, cond_op): return lambda _g, step, sL, s, _input, **kwargs: \ apply_state_condition(pre_conditions, cond_op, y, f, _g, step, sL, s, _input, **kwargs) def var_substep_trigger(substeps): def trigger(end_substep, y, f): pre_conditions = {'substep': substeps} cond_opp = lambda a, b: a and b return var_trigger(y, f, pre_conditions, cond_opp) return lambda y, f: curry(trigger)(substeps)(y)(f) def env_trigger(end_substep): def trigger(end_substep, trigger_field, trigger_vals, funct_list): def env_update(state_dict, sweep_dict, target_value): state_dict_copy = state_dict.copy() # Use supstep to simulate current sysMetrics if state_dict_copy['substep'] == end_substep: state_dict_copy['timestep'] = state_dict_copy['timestep'] + 1 if state_dict_copy[trigger_field] in trigger_vals: for g in funct_list: target_value = g(sweep_dict, target_value) del state_dict_copy return target_value return env_update return lambda trigger_field, trigger_vals, funct_list: \ curry(trigger)(end_substep)(trigger_field)(trigger_vals)(funct_list) def config_sim(config_dict: ConfigurationDict): if "N" in config_dict: if config_dict["N"] <= 0: raise ValueError("'N' must be > 0") else: pass else: raise KeyError("The 'sim_configs' dictionary must contain the key 'N' (# of Monte Carlo Runs)") if "T" not in config_dict: raise KeyError("The 'sim_configs' dictionary must contain the key 'T' (Timestep Iterator)") else: if "M" in config_dict: params = config_dict['M'] param_values_length = {key: len(value) if type(value) == list else 0 for key, value in params.items()} param_values_length_set = set(param_values_length.values()) distinct_param_value_lengths = len(param_values_length_set) if distinct_param_value_lengths > 2: raise Exception('When sweeping, `M` list lengths should either be 1 and/or equal. More than two distinct lengths are not allowed') elif (distinct_param_value_lengths == 1) and (0 in param_values_length_set): return config_dict elif (distinct_param_value_lengths == 1) or (1 in param_values_length_set): return [{**config_dict, "M": M} for M in flatten_tabulated_dict(tabulate_dict(params))] else: raise Exception('When sweeping, `M` list lengths should either be 1 and/or equal. ') else: config_dict["M"] = [{}] return config_dict def psub_list(psu_block, psu_steps): return [psu_block[psu] for psu in psu_steps] def psub(policies, state_updates): return { 'policies': policies, 'states': state_updates } def genereate_psubs(policy_grid, states_grid, policies, state_updates): PSUBS = [] for policy_ids, state_list in zip(policy_grid, states_grid): filtered_policies = {k: v for (k, v) in policies.items() if k in policy_ids} filtered_state_updates = {k: v for (k, v) in state_updates.items() if k in state_list} PSUBS.append(psub(filtered_policies, filtered_state_updates)) return PSUBS def access_block(state_history, target_field, psu_block_offset, exculsion_list=[]): exculsion_list += [target_field] def filter_history(key_list, block): filter = lambda key_list: \ lambda d: {k: v for k, v in d.items() if k not in key_list} return list(map(filter(key_list), block)) if psu_block_offset < -1: if len(state_history) >= abs(psu_block_offset): return filter_history(exculsion_list, state_history[psu_block_offset]) else: return [] elif psu_block_offset == -1: return filter_history(exculsion_list, state_history[psu_block_offset]) else: return [] ## Parameter Sweep def partial_state_sweep_filter(state_field, partial_state_updates): partial_state_dict = dict([(k, v[state_field]) for k, v in partial_state_updates.items()]) return dict([ (k, dict_filter(v, lambda v: isinstance(v, list))) for k, v in partial_state_dict.items() if contains_type(list(v.values()), list) ]) def state_sweep_filter(raw_exogenous_states): return dict([(k, v) for k, v in raw_exogenous_states.items() if isinstance(v, list)]) # @curried def sweep_partial_states(_type, in_config): configs = [] # filtered_mech_states filtered_partial_states = partial_state_sweep_filter(_type, in_config.partial_state_update_blocks) if len(filtered_partial_states) > 0: for partial_state, state_dict in filtered_partial_states.items(): for state, state_funcs in state_dict.items(): for f in state_funcs: config = in_config.copy() config.partial_state_updates[partial_state][_type][state] = f configs.append(config) del config else: configs = [in_config] return configs # @curried def sweep_states(state_type, states, in_config): configs = [] filtered_states = state_sweep_filter(states) if len(filtered_states) > 0: for state, state_funcs in filtered_states.items(): for f in state_funcs: config = in_config.copy() exploded_states = states.copy() exploded_states[state] = f if state_type == 'exogenous': config.exogenous_states = exploded_states elif state_type == 'environmental': config.env_processes = exploded_states configs.append(config) del config, exploded_states else: configs = [in_config] return configs ================================================ FILE: cadCAD/configuration/utils/depreciationHandler.py ================================================ from copy import deepcopy def sanitize_config(config): for key, value in config.kwargs.items(): if key == 'state_dict': config.initial_state = value elif key == 'seed': config.seeds = value elif key == 'mechanisms': config.partial_state_update_blocks = value if config.initial_state == {}: raise Exception('The initial conditions of the system have not been set') def sanitize_partial_state_updates(partial_state_updates): new_partial_state_updates = partial_state_updates.copy() def rename_keys(d): if 'behaviors' in d: d['policies'] = d.pop('behaviors') if 'states' in d: d['variables'] = d.pop('states') if isinstance(new_partial_state_updates, list): for v in new_partial_state_updates: rename_keys(v) elif isinstance(new_partial_state_updates, dict): for k, v in new_partial_state_updates.items(): rename_keys(v) del partial_state_updates return new_partial_state_updates ================================================ FILE: cadCAD/configuration/utils/policyAggregation.py ================================================ def get_base_value(x): if isinstance(x, str): return '' elif isinstance(x, int): return 0 elif isinstance(x, list): return [] else: return 0 def policy_to_dict(v): return dict(list(zip(map(lambda n: 'p' + str(n + 1), list(range(len(v)))), v))) add = lambda a, b: a + b # @curried # def foldr_dict_vals(f, d): # return foldr(f)(list(d.values())) # # # def sum_dict_values(): # return foldr_dict_vals(add) # @curried # def dict_op(f, d1, d2): # def set_base_value(target_dict, source_dict, key): # if key not in target_dict: # return get_base_value(source_dict[key]) # else: # return target_dict[key] # # key_set = set(list(d1.keys()) + list(d2.keys())) # # return {k: f(set_base_value(d1, d2, k), set_base_value(d2, d1, k)) for k in key_set} # # def dict_elemwise_sum(): # return dict_op(add) ================================================ FILE: cadCAD/configuration/utils/userDefinedObject.py ================================================ from collections import namedtuple from inspect import getmembers, ismethod from pandas.core.frame import DataFrame from cadCAD.utils import SilentDF def val_switch(v): if isinstance(v, DataFrame) is True: return SilentDF(v) else: return v class udcView(object): def __init__(self, d, masked_members): self.__dict__ = d self.masked_members = masked_members def __repr__(self): members = {} variables = { k: val_switch(v) for k, v in self.__dict__.items() if str(type(v)) != "" and k not in self.masked_members # and isinstance(v, DataFrame) is not True } members['methods'] = [k for k, v in self.__dict__.items() if str(type(v)) == ""] members.update(variables) return f"{members}" class udcBroker(object): def __init__(self, obj, function_filter=['__init__']): d = {} funcs = dict(getmembers(obj, ismethod)) filtered_functions = {k: v for k, v in funcs.items() if k not in function_filter} d['obj'] = obj d.update(vars(obj)) # somehow is enough d.update(filtered_functions) self.members_dict = d def get_members(self): return self.members_dict def get_view(self, masked_members): return udcView(self.members_dict, masked_members) def get_namedtuple(self): return namedtuple("Hydra", self.members_dict.keys())(*self.members_dict.values()) def UDO(udo, masked_members=['obj']): return udcBroker(udo).get_view(masked_members) def udoPipe(obj_view): return UDO(obj_view.obj, obj_view.masked_members) ================================================ FILE: cadCAD/diagram/__init__.py ================================================ from cadCAD.diagram.config_diagram import diagram, diagram_from_config ================================================ FILE: cadCAD/diagram/config_diagram.py ================================================ from graphviz import Digraph import inspect import re ### Inspect functions def extract_var_key(raw_line: str, var_id: str) -> str: """ Extract the key from an line in the form "dict['key']" or "dict.get('key', *args)". """ line = raw_line.strip()[len(var_id) :] state_var = "" if line[0] == "[": state_var = line[2:-2] elif line[0:4] == ".get": call = line.split("(")[1] call = call.split(")")[0] call = call.strip() sep = "'" if call[0] == '"': sep = '"' state_var = [el for el in call.split(sep) if len(el) > 0][0] return state_var def extract_vars_from_source(source: str, var_id: str) -> set: """ Extract keys from an source code that consumes an dict with var_id name. """ regex = ( r"((" + var_id + r"\[(\'|\")\w+(\'|\")\])|(" + var_id + r".get\((\'|\")\w+(\'|\")[A-z,\s\"\']*\)))" ) matches = re.findall(regex, source) lines = [match[0] for match in matches] state_vars = set([extract_var_key(line, var_id) for line in lines]) return state_vars def extract_keys(f: callable) -> dict: """ """ src = inspect.getsource(f) params = inspect.signature(f) params_key = list(params.parameters)[0] state_key = list(params.parameters)[3] output = { "state": extract_vars_from_source(src, state_key), "params": extract_vars_from_source(src, params_key), } return output def relate_psub(psub: dict) -> dict: """ Given an dict describing an Partial State Update block, this functions generates an dict with three keys: 'params' and 'state' which are sets containing all unique parameters and state variables for the PSUB, and 'map' for doing an more detailed map. """ psub_relation = {"map": {}, "params": set(), "state": set()} unique_params = set() unique_vars = set() keys = ["policies", "variables"] for key in keys: type_functions = psub.get(key, {}) type_keys = {k: extract_keys(v) for k, v in type_functions.items()} params_list = [v.get("params", set()) for v in type_keys.values()] vars_list = [v.get("state", set()) for v in type_keys.values()] if len(params_list) > 0: params = set.union(*params_list) else: params = set() if len(vars_list) > 0: vars = set.union(*vars_list) else: vars = set() psub_relation["params"] = psub_relation["params"].union(params) psub_relation["state"] = psub_relation["state"].union(vars) psub_relation["map"][key] = type_keys return psub_relation def generate_relations(psubs) -> list: """ Generates an list of dicts, """ psub_relations = [relate_psub(psub) for psub in psubs] return psub_relations ### Diagram functions def generate_time_graph() -> Digraph: time_graph = Digraph("cluster_timestep", engine="dot") time_graph.attr(style="filled", bgcolor="pink", dpi="50", rankdir="LR") return time_graph def generate_variables_cluster(variables: dict, i: int, suffix="") -> Digraph: state_graph = Digraph("cluster_variables_{}{}".format(i, suffix)) state_graph.attr(style="filled, dashed", label="State", fillcolor="skyblue") for key, value in variables.items(): name = "variable_{}_{}{}".format(key, i, suffix) description = "{} ({})".format(key, type(value).__name__) state_graph.node( name, description, shape="cylinder", style="filled, solid", fillcolor="honeydew", ), return state_graph def generate_params_cluster(params: dict, i: int) -> Digraph: params_graph = Digraph("cluster_params_{}".format(i)) params_graph.attr(style="filled, dashed", label="Parameters", fillcolor="skyblue") for key, value in params.items(): name = "param_{}_{}".format(key, i) description = "{} ({})".format(key, type(value).__name__) params_graph.node( name, description, shape="cylinder", style="filled, solid", fillcolor="honeydew", ), return params_graph def generate_psub_graph(i: int): psub_graph = Digraph("cluster_psub_{}".format(i)) psub_graph.attr( style="filled, dashed", label=f"Partial State Update Block #{i}", fillcolor="thistle", center="true", ) return psub_graph def relate_params(graph: Digraph, params, i, origin=-1) -> Digraph: for param in params: dst = "param_{}_{}".format(param, i) src = "param_{}_{}".format(param, origin) graph.edge(src, dst) return graph def generate_policies_cluster(policies: dict, i: int, psub_graph) -> Digraph: policy_graph = Digraph("cluster_policy_{}".format(i)) policy_graph.attr(label="Policies") policy_graph.node( "agg_{}".format(i), "Aggregation", shape="circle", style="filled,bold", fillcolor="greenyellow", width="1", ) for key, value in policies.items(): name = "policy_{}_{}".format(key, i) description = "{} ({})".format(key, value.__name__) policy_graph.node( name, description, style="filled, bold", fillcolor="palegreen", shape="cds", height="1", width="1", ) psub_graph.edge(name, "agg_{}".format(i)) return psub_graph.subgraph(policy_graph) def relate( graph, relations, i, src_prefix, dst_prefix, suffix="", reverse=False ) -> Digraph: for key, value in relations.items(): dst = "{}_{}_{}".format(dst_prefix, key, i) for param in value: src = "{}_{}_{}{}".format(src_prefix, param, i, suffix) if reverse: graph.edge(dst, src) else: graph.edge(src, dst) return graph def generate_sufs_cluster(sufs: dict, i: int, psub_graph, agg=False) -> Digraph: suf_graph = Digraph("cluster_suf_{}".format(i)) suf_graph.attr(label="State Update Functions") for key, value in sufs.items(): name = "suf_{}_{}".format(key, i) description = "{} ({})".format(key, value.__name__) suf_graph.node( name, description, style="filled, bold", fillcolor="red", shape="cds", height="1", width="1", ) if agg: psub_graph.edge("agg_{}".format(i), name) return psub_graph.subgraph(suf_graph) def relate_params_to_sufs(graph, sufs, i) -> Digraph: for key, value in sufs.items(): dst = "suf_{}_{}".format(key, i) for param in value: src = "param_{}_{}".format(param, i) graph.edge(src, dst) return graph def diagram(initial_state, params, psubs): """ Generates an diagram for an cadCAD configuration object. """ relations = generate_relations(psubs) time_graph = generate_time_graph() for i_psub, psub in enumerate(psubs): psub_graph = generate_psub_graph(i_psub) # Parameters psub_params = relations[i_psub].get("params", set()) psub_params = {k: params.get(k, None) for k in psub_params} psub_vars = relations[i_psub].get("state", set()) psub_vars = {k: initial_state.get(k, None) for k in psub_vars} psub_graph.subgraph(generate_params_cluster(psub_params, i_psub)) psub_graph.subgraph(generate_variables_cluster(psub_vars, i_psub)) # psub_graph = relate_params(psub_graph, psub_params, i) # Policies policies = psub.get("policies", {}) psub_map = relations[i_psub].get("map", {}) policy_map = psub_map.get("policies", {}) policy_inputs = { policy: relation["state"] for policy, relation in policy_map.items() } policy_params = { policy: relation["params"] for policy, relation in policy_map.items() } list_of_inputs = list(policy_inputs.values()) if len(list_of_inputs) > 0: agg = True inputs = set.union(*list_of_inputs) inputs = {k: initial_state.get(k, None) for k in inputs} psub_graph.subgraph(generate_policies_cluster(policies, i_psub, psub_graph)) psub_graph = relate(psub_graph, policy_params, i_psub, "param", "policy") psub_graph = relate(psub_graph, policy_inputs, i_psub, "variable", "policy") else: agg = False # SUFs sufs = psub.get("variables", {}) suf_map = psub_map.get("variables", {}) sufs_inputs = { policy: relation["state"] for policy, relation in suf_map.items() } sufs_params = { policy: relation["params"] for policy, relation in suf_map.items() } list_of_inputs = list(sufs_inputs.values()) if len(list_of_inputs) > 0: inputs = set.union(*list_of_inputs) inputs = {k: initial_state.get(k, None) for k in inputs} generate_sufs_cluster(sufs, i_psub, psub_graph, agg=agg) psub_graph = relate(psub_graph, sufs_params, i_psub, "param", "suf") psub_graph = relate(psub_graph, sufs_inputs, i_psub, "variable", "suf") time_graph.subgraph(psub_graph) return time_graph def diagram_from_config(config): initial_state = config.initial_state params = config.sim_config["M"] psubs = config.partial_state_update_blocks return diagram(initial_state, params, psubs) ================================================ FILE: cadCAD/engine/__init__.py ================================================ from time import time from typing import Callable, Dict, List, Any, Tuple, Union, Sequence, Mapping from tqdm.auto import tqdm from cadCAD.utils import flatten from cadCAD.utils.execution import print_exec_info from cadCAD.configuration import Configuration, Processor from cadCAD.configuration.utils import TensorFieldReport, configs_as_objs, configs_as_dicts from cadCAD.engine.simulation import Executor as SimExecutor from cadCAD.engine.execution import single_proc_exec, parallelize_simulations, local_simulations from cadCAD.types import * VarDictType = Dict[str, List[object]] StatesListsType = List[dict[str, object]] ConfigsType = List[tuple[list[callable], List[callable]]] EnvProcessesType = Dict[str, callable] class ExecutionMode: local_mode = 'local_proc' multi_mode = 'multi_proc' distributed = 'dist_proc' single_mode = 'single_proc' # Backwards compatible modes below single_proc = 'single_proc' multi_proc = 'multi_proc' def auto_mode_switcher(config_amt: int): try: if config_amt == 1: return ExecutionMode.single_mode, single_proc_exec elif (config_amt > 1): return ExecutionMode.multi_mode, parallelize_simulations except AttributeError: if config_amt < 1: raise ValueError('N must be >= 1!') class ExecutionContext: def __init__(self, context=ExecutionMode.local_mode, method=None, additional_objs=None) -> None: self.name = context self.additional_objs = additional_objs if context == 'local_proc': self.method = local_simulations elif context == 'single_proc': self.method = single_proc_exec elif context == 'multi_proc': self.method = parallelize_simulations elif context == 'dist_proc': def distroduce_proc( simulation_execs, var_dict_list, states_lists, configs_structs, env_processes_list, Ts, SimIDs, RunIDs, ExpIDs, SubsetIDs, SubsetWindows, configured_n, # exec_method, sc, additional_objs=additional_objs ): return method( simulation_execs, var_dict_list, states_lists, configs_structs, env_processes_list, Ts, SimIDs, RunIDs, ExpIDs, SubsetIDs, SubsetWindows, configured_n, # exec_method, sc, additional_objs ) self.method = distroduce_proc class Executor: def __init__(self, exec_context: ExecutionContext, configs: List[Configuration], sc=None, empty_return=False, supress_print=False ) -> None: self.sc = sc self.SimExecutor = SimExecutor self.exec_method = exec_context.method self.exec_context = exec_context.name self.additional_objs = exec_context.additional_objs self.configs = configs self.empty_return = empty_return self.supress_print = supress_print def execute(self) -> Tuple[object, object, Dict[str, object]]: if self.empty_return is True: return [], [], [] config_proc = Processor() create_tensor_field = TensorFieldReport( config_proc).create_tensor_field sessions = [] var_dict_list, states_lists = [], [] Ts, Ns, SimIDs, RunIDs = [], [], [], [] ExpIDs, ExpWindows, SubsetIDs, SubsetWindows = [], [], [], [] eps, configs_structs, env_processes_list = [], [], [] partial_state_updates, sim_executors = [], [] config_idx = 0 # Execution Info if self.supress_print is False: print_exec_info(self.exec_context, configs_as_objs(self.configs)) t1 = time() for x in tqdm(self.configs, total=len(self.configs), desc="Initializing configurations", disable=self.supress_print): sessions.append( { 'user_id': x.user_id, 'experiment_id': x.experiment_id, 'session_id': x.session_id, 'simulation_id': x.simulation_id, 'run_id': x.run_id, 'subset_id': x.subset_id, 'subset_window': x.subset_window } ) Ts.append(x.sim_config['T']) Ns.append(x.sim_config['N']) ExpIDs.append(x.experiment_id) ExpWindows.append(x.exp_window) SimIDs.append(x.simulation_id) SubsetIDs.append(x.subset_id) RunIDs.append(x.run_id) SubsetWindows.append(x.subset_window) var_dict_list.append(x.sim_config['M']) states_lists.append([x.initial_state]) eps.append(list(x.exogenous_states.values())) configs_structs.append(config_proc.generate_config( x.initial_state, x.partial_state_update_blocks, eps[config_idx])) env_processes_list.append(x.env_processes) partial_state_updates.append(x.partial_state_update_blocks) sim_executors.append(SimExecutor(x.policy_ops).simulation) config_idx += 1 remote_threshold = 100 config_amt = len(self.configs) def get_final_dist_results(simulations: List[StateHistory], psus: List[StateUpdateBlocks], eps, sessions: List[SessionDict]): tensor_fields = [create_tensor_field( psu, ep) for psu, ep in list(zip(psus, eps))] return simulations, tensor_fields, sessions def get_final_results(simulations: List[StateHistory], psus: List[StateUpdateBlocks], eps, sessions: List[SessionDict], remote_threshold: int): # if list of lists of lists of dicts: do flatten # if list of dicts: do not flatetn # else raise error init: bool = isinstance(simulations, Sequence) failed_1 = False failed_2 = False try: init: bool = isinstance(simulations, Sequence) dont_flatten = init & isinstance(simulations[0], Mapping) do_flatten = not dont_flatten except: failed_1 = True do_flatten = True try: do_flatten = init & isinstance(simulations[0], Sequence) do_flatten &= isinstance(simulations[0][0], Sequence) do_flatten &= isinstance(simulations[0][0][0], Mapping) except: failed_2 = True do_flatten = False if failed_1 and failed_2: raise ValueError('Invalid simulation results (Executor output is not list[dict] or list[list[list[dict]]])') flat_timesteps, tensor_fields = [], [] for sim_result, psu, ep in tqdm(list(zip(simulations, psus, eps)), total=len(simulations), desc='Flattening results', disable=self.supress_print): if do_flatten: flat_timesteps.append(flatten(sim_result)) tensor_fields.append(create_tensor_field(psu, ep)) if do_flatten: flat_simulations = flatten(flat_timesteps) else: flat_simulations = simulations return flat_simulations, tensor_fields, sessions final_result = None original_N = len(configs_as_dicts(self.configs)) if self.exec_context != ExecutionMode.distributed: # Consider Legacy Support if self.exec_context == ExecutionMode.local_mode: self.exec_context, self.exec_method = auto_mode_switcher( config_amt) elif self.exec_context == ExecutionMode.single_mode or self.exec_context == ExecutionMode.single_proc: self.exec_context, self.exec_method = ExecutionMode.single_mode, single_proc_exec elif self.exec_context == ExecutionMode.multi_mode or self.exec_context == ExecutionMode.multi_proc: if config_amt == 1: raise ValueError("Multi mode must have at least 2 configs") else: self.exec_context, self.exec_method = ExecutionMode.multi_mode, parallelize_simulations else: raise ValueError("Invalid execution mode specified") if self.supress_print is False: print("Execution Method: " + self.exec_method.__name__) simulations_results = self.exec_method( sim_executors, var_dict_list, states_lists, configs_structs, env_processes_list, Ts, SimIDs, RunIDs, ExpIDs, SubsetIDs, SubsetWindows, original_N, self.additional_objs ) final_result = get_final_results( simulations_results, partial_state_updates, eps, sessions, remote_threshold) elif self.exec_context == ExecutionMode.distributed: if self.supress_print is False: print("Execution Method: " + self.exec_method.__name__) simulations_results = self.exec_method( sim_executors, var_dict_list, states_lists, configs_structs, env_processes_list, Ts, SimIDs, RunIDs, ExpIDs, SubsetIDs, SubsetWindows, original_N, self.sc ) final_result = get_final_dist_results( simulations_results, partial_state_updates, eps, sessions) t2 = time() if self.supress_print is False: print(f"Total execution time: {t2 - t1 :.2f}s") return final_result ================================================ FILE: cadCAD/engine/execution.py ================================================ from typing import Callable, Dict, List, Any, Tuple, Sequence from pathos.multiprocessing import ProcessPool # type: ignore from collections import Counter from cadCAD.types import * from cadCAD.utils import flatten VarDictType = Dict[str, List[object]] StatesListsType = List[dict[str, object]] ConfigsType = List[tuple[list[callable], List[callable]]] EnvProcessesType = Dict[str, callable] def single_proc_exec( simulation_execs: Sequence[ExecutorFunction], var_dict_list: Union[Sequence[Parameters], Parameters], states_lists: Sequence[StateHistory], configs_structs: Sequence[StateUpdateBlocks], env_processes_list: Sequence[EnvProcesses], Ts: Sequence[TimeSeq], SimIDs: Sequence[SimulationID], Ns: Sequence[Run], ExpIDs: Sequence[int], SubsetIDs: Sequence[SubsetID], SubsetWindows: Sequence[SubsetWindow], configured_n: Sequence[N_Runs], additional_objs=None ) -> List: if not isinstance(var_dict_list, Sequence): var_dict_list = list([var_dict_list]) raw_params = ( simulation_execs, states_lists, configs_structs, env_processes_list, Ts, SimIDs, Ns, SubsetIDs, SubsetWindows, var_dict_list) results: List = [] for raw_param in zip(*raw_params): simulation_exec, states_list, config, env_processes, T, sim_id, N, subset_id, subset_window, var_dict = raw_param result = simulation_exec( var_dict, states_list, config, env_processes, T, sim_id, N, subset_id, subset_window, configured_n, additional_objs ) results.append(flatten(result)) return flatten(results) def parallelize_simulations( simulation_execs: List[ExecutorFunction], var_dict_list: List[Parameters], states_lists: List[StateHistory], configs_structs: List[StateUpdateBlocks], env_processes_list: List[EnvProcesses], Ts: List[TimeSeq], SimIDs: List[SimulationID], Ns: List[Run], ExpIDs: List[int], SubsetIDs: List[SubsetID], SubsetWindows: List[SubsetWindow], configured_n: List[N_Runs], additional_objs=None ): params = list( zip( simulation_execs, var_dict_list, states_lists, configs_structs, env_processes_list, Ts, SimIDs, Ns, SubsetIDs, SubsetWindows ) ) len_configs_structs = len(configs_structs) unique_runs = Counter(SimIDs) sim_count = max(unique_runs.values()) highest_divisor = int(len_configs_structs / sim_count) new_configs_structs, new_params = [], [] for count in range(len(params)): if count == 0: new_params.append( params[count: highest_divisor] ) new_configs_structs.append( configs_structs[count: highest_divisor] ) elif count > 0: new_params.append( params[count * highest_divisor: (count + 1) * highest_divisor] ) new_configs_structs.append( configs_structs[count * highest_divisor: (count + 1) * highest_divisor] ) def process_executor(params): if len_configs_structs > 1: with ProcessPool(processes=len_configs_structs) as pp: results = pp.map( lambda t: t[0](t[1], t[2], t[3], t[4], t[5], t[6], t[7], t[8], t[9], configured_n), params ) else: t = params[0] results = t[0](t[1], t[2], t[3], t[4], t[5], t[6], t[7], t[8], t[9], configured_n) return results results = flatten(list(map(lambda params: process_executor(params), new_params))) return results def local_simulations( simulation_execs: List[ExecutorFunction], var_dict_list: List[Parameters], states_lists: List[StateHistory], configs_structs: List[StateUpdateBlocks], env_processes_list: List[EnvProcesses], Ts: List[TimeSeq], SimIDs: List[SimulationID], Ns: List[Run], ExpIDs: List[int], SubsetIDs: List[SubsetID], SubsetWindows: List[SubsetWindow], configured_n: List[N_Runs], additional_objs=None ): config_amt = len(configs_structs) if config_amt == 1: # and configured_n != 1 return single_proc_exec( simulation_execs, var_dict_list, states_lists, configs_structs, env_processes_list, Ts, SimIDs, Ns, ExpIDs, SubsetIDs, SubsetWindows, configured_n, additional_objs ) elif config_amt > 1: # and configured_n != 1 return parallelize_simulations( simulation_execs, var_dict_list, states_lists, configs_structs, env_processes_list, Ts, SimIDs, Ns, ExpIDs, SubsetIDs, SubsetWindows, configured_n, additional_objs ) # elif config_amt > 1 and configured_n == 1: ================================================ FILE: cadCAD/engine/simulation.py ================================================ from typing import Any, Callable, Dict, List, Tuple from copy import deepcopy, copy from functools import reduce from funcy import curry # type: ignore from cadCAD.utils import flatten from cadCAD.engine.utils import engine_exception from cadCAD.types import * id_exception: callable = curry(engine_exception)(KeyError)(KeyError)(None) Aggregator = Callable[[object, object], object] def policy_scope_tuner(args: tuple, additional_objs: object, f: PolicyFunction) -> dict: """ Execute cadCAD policy function. """ (sweep_dict, sub_step, sL, s) = args if additional_objs is None: return f(sweep_dict, sub_step, sL, s) else: return f(sweep_dict, sub_step, sL, s, additional_objs) def compose(init_reduction_funct: Aggregator, funct_list: List[Aggregator], val_list: dict) -> object: """ Reduce the nested policy input dict into a simple one. """ result, i = None, 0 def composition(x): return [reduce( init_reduction_funct, x.values())] + funct_list for g in composition(val_list): if i == 0: result = g i = 1 else: result = g(result) return result class Executor: def __init__( self, policy_ops, policy_update_exception: callable = id_exception, state_update_exception: callable = id_exception ) -> None: self.policy_ops = policy_ops self.state_update_exception = state_update_exception self.policy_update_exception = policy_update_exception def get_policy_input( self, sweep_dict: Dict[str, List[object]], sub_step: int, sL: List[dict[str, object]], s: Dict[str, object], funcs: List[callable], additional_objs ) -> Dict[str, object]: """ Retrieves the Policy Input for usage on State Update Functions Arguments: sweep_dict - System Parameters sub_step - Execution order in regards to PSUBs sL - History of the variables state s - Current variables state funcs - list of cadCAD Policies to be executed """ ops = self.policy_ops args = (sweep_dict, sub_step, sL, s) def execute_policy(f: PolicyFunction) -> dict: return policy_scope_tuner(args, additional_objs, f) col_results: List[PolicyOutput] = map(execute_policy, funcs) # Create a nested dict containing all results combination # new_dict[policy_input][policy_ordinal] = policy_input_value new_dict: dict = {} for i, col_result in enumerate(col_results): for label, value in col_result.items(): if label not in new_dict.keys(): new_dict[label] = {} else: pass new_dict[label][i] = value # Aggregator functions ops_head, *ops_tail = ops # Function for aggregating a combination of policy inputs # for the same signal def f(val_list): return compose(init_reduction_funct=ops_head, funct_list=ops_tail, val_list=val_list) # Generate dict to be consumed by SUFs policy_input = { label: f(val_list) for label, val_list in new_dict.items()} return policy_input def apply_env_proc( self, sweep_dict, env_processes: Dict[str, callable], state_dict: Dict[str, object] ) -> Dict[str, object]: def env_composition(target_field, state_dict, target_value): function_type = type(lambda x: x) env_update = env_processes[target_field] if isinstance(env_update, list): for f in env_update: target_value = f(sweep_dict, target_value) elif isinstance(env_update, function_type): target_value = env_update(state_dict, sweep_dict, target_value) else: target_value = env_update return target_value filtered_state_dict = { k: v for k, v in state_dict.items() if k in env_processes.keys()} env_proc_dict = { target_field: env_composition( target_field, state_dict, target_value) for target_field, target_value in filtered_state_dict.items() } for k, v in env_proc_dict.items(): state_dict[k] = v return state_dict # mech_step def partial_state_update( self, sweep_dict: Parameters, sub_step: Substep, sL: List[State], sH: StateHistory, state_funcs: List[StateUpdateFunction], policy_funcs: List[PolicyFunction], env_processes: EnvProcesses, time_step: int, run: int, additional_objs ) -> List[dict[str, object]]: if type(additional_objs) == dict: if additional_objs.get('deepcopy_off', False) == True: last_in_obj = copy(sL[-1]) if len(additional_objs) == 1: additional_objs = None # XXX: drop the additional objects if only used for deepcopy # toggling. else: last_in_obj = deepcopy(sL[-1]) else: last_in_obj = deepcopy(sL[-1]) _input: Dict[str, Any] = self.policy_update_exception( self.get_policy_input(sweep_dict, sub_step, sH, last_in_obj, policy_funcs, additional_objs) ) def generate_record(state_funcs): def state_scope_tuner(f): lenf = f.__code__.co_argcount if lenf == 5: return self.state_update_exception(f(sweep_dict, sub_step, sH, last_in_obj, _input)) elif lenf == 6: return self.state_update_exception(f(sweep_dict, sub_step, sH, last_in_obj, _input, additional_objs)) for f in state_funcs: yield state_scope_tuner(f) def transfer_missing_fields(source, destination): for k in source: if k not in destination: destination[k] = source[k] del source return destination try: new_state_vars = dict(generate_record(state_funcs)) except (ValueError, TypeError): raise ValueError("There is a State Update Function which is not returning an proper tuple") last_in_copy: Dict[str, Any] = transfer_missing_fields(last_in_obj, new_state_vars) last_in_copy: Dict[str, Any] = self.apply_env_proc(sweep_dict, env_processes, last_in_copy) last_in_copy['substep'], last_in_copy['timestep'], last_in_copy['run'] = sub_step, time_step, run sL.append(last_in_copy) del last_in_copy return sL # mech_pipeline - state_update_block def state_update_pipeline( self, sweep_dict: Dict[str, List[object]], simulation_list, configs: List[tuple[list[callable], List[callable]]], env_processes: Dict[str, callable], time_step: int, run: int, additional_objs ) -> List[dict[str, object]]: sub_step = 0 states_list_copy: List[dict[str, object]] = tuple(simulation_list[-1]) genesis_states: Dict[str, object] = states_list_copy[-1].copy() # genesis_states: Dict[str, object] = states_list_copy[-1] if len(states_list_copy) == 1: genesis_states['substep'] = sub_step del states_list_copy states_list: List[dict[str, object]] = [genesis_states] sub_step += 1 for [s_conf, p_conf] in configs: states_list: List[dict[str, object]] = self.partial_state_update( sweep_dict, sub_step, states_list, simulation_list, s_conf, p_conf, env_processes, time_step, run, additional_objs ) sub_step += 1 time_step += 1 return states_list # state_update_pipeline def run_pipeline( self, sweep_dict: Dict[str, List[object]], states_list: List[dict[str, object]], configs: List[tuple[list[callable], List[callable]]], env_processes: Dict[str, callable], time_seq: range, run: int, additional_objs ) -> List[list[dict[str, object]]]: time_seq: List[int] = [x + 1 for x in time_seq] simulation_list: List[list[dict[str, object]]] = [states_list] for time_step in time_seq: pipe_run: List[dict[str, object]] = self.state_update_pipeline( sweep_dict, simulation_list, configs, env_processes, time_step, run, additional_objs ) _, *pipe_run = pipe_run simulation_list.append(pipe_run) return simulation_list def simulation( self, sweep_dict: SweepableParameters, states_list: StateHistory, configs, env_processes: EnvProcesses, time_seq: TimeSeq, simulation_id: SimulationID, run: int, subset_id: SubsetID, subset_window: SubsetWindow, configured_N: int, # remote_ind additional_objs: Union[None, Dict]=None ): run += 1 subset_window.appendleft(subset_id) def execute_run(sweep_dict, states_list, configs, env_processes, time_seq, _run) -> List[dict[str, object]]: def generate_init_sys_metrics(genesis_states_list, sim_id, _subset_id, _run, _subset_window): for D in genesis_states_list: d = D.copy() d['simulation'], d['subset'], d['run'], d['substep'], d['timestep'] = \ sim_id, _subset_id, _run, 0, 0 yield d states_list_copy: List[dict[str, object]] = list( generate_init_sys_metrics( tuple(states_list), simulation_id, subset_id, run, subset_window) ) first_timestep_per_run: List[dict[str, object]] = self.run_pipeline( sweep_dict, states_list_copy, configs, env_processes, time_seq, run, additional_objs ) del states_list_copy return first_timestep_per_run pipe_run = flatten( [execute_run(sweep_dict, states_list, configs, env_processes, time_seq, run)] ) return pipe_run ================================================ FILE: cadCAD/engine/utils.py ================================================ from datetime import datetime def datetime_range(start, end, delta, dt_format='%Y-%m-%d %H:%M:%S'): reverse_head = end [start, end] = [datetime.strptime(x, dt_format) for x in [start, end]] def _datetime_range(start, end, delta): current = start while current < end: yield current current += delta reverse_tail = [dt.strftime(dt_format) for dt in _datetime_range(start, end, delta)] return reverse_tail + [reverse_head] def last_index(l): return len(l)-1 def retrieve_state(l, offset): return l[last_index(l) + offset + 1] # @curried def engine_exception(ErrorType, error_message, exception_function, try_function): try: return try_function except ErrorType: print(error_message) return exception_function ================================================ FILE: cadCAD/tools/__init__.py ================================================ from cadCAD.tools.execution import easy_run from cadCAD.tools.profiling import profile_run from cadCAD.tools.utils import generic_suf, add_parameter_labels ================================================ FILE: cadCAD/tools/execution/__init__.py ================================================ from cadCAD.tools.execution.easy_run import easy_run ================================================ FILE: cadCAD/tools/execution/easy_run.py ================================================ import inspect import types from typing import Dict, Union import pandas as pd # type: ignore from cadCAD.configuration import Experiment from cadCAD.configuration.utils import config_sim from cadCAD.engine import ExecutionContext, ExecutionMode, Executor def describe_or_return(v: object) -> object: """ Thanks @LinuxIsCool! """ if isinstance(v, types.FunctionType): return f'function: {v.__name__}' elif isinstance(v, types.LambdaType) and v.__name__ == '': return f'lambda: {inspect.signature(v)}' elif isinstance(v, list): return str(v) else: return v def select_M_dict(M_dict: Dict[str, object], keys: set) -> Dict[str, object]: """ Thanks @LinuxIsCool! """ return {k: describe_or_return(v) for k, v in M_dict.items() if k in keys} def select_config_M_dict(configs: list, i: int, keys: set) -> Dict[str, object]: return select_M_dict(configs[i].sim_config['M'], keys) def easy_run( state_variables, params, psubs, N_timesteps, N_samples, use_label=False, assign_params: Union[bool, set] = True, drop_substeps=True, exec_mode='local', deepcopy_off=False, supress_print=False ) -> pd.DataFrame: """ Run cadCAD simulations without headaches. """ # Set-up sim_config simulation_parameters = {'N': N_samples, 'T': range(N_timesteps), 'M': params} sim_config = config_sim(simulation_parameters) # type: ignore # Create a new experiment exp = Experiment() exp.append_configs( sim_configs=sim_config, initial_state=state_variables, partial_state_update_blocks=psubs, ) configs = exp.configs # Set-up cadCAD executor if exec_mode == 'local': _exec_mode = ExecutionMode().local_mode elif exec_mode == 'single': _exec_mode = ExecutionMode().single_mode exec_context = ExecutionContext(_exec_mode, additional_objs={'deepcopy_off': deepcopy_off}) executor = Executor(exec_context=exec_context, configs=configs, supress_print=supress_print) # Execute the cadCAD experiment (records, tensor_field, _) = executor.execute() # Parse the output as a pandas DataFrame df = pd.DataFrame(records) if drop_substeps == True: # Drop all intermediate substeps first_ind = (df.substep == 0) & (df.timestep == 0) last_ind = df.substep == max(df.substep) inds_to_drop = first_ind | last_ind df = df.loc[inds_to_drop].drop(columns=['substep']) else: pass if assign_params == False: pass else: M_dict = configs[0].sim_config['M'] params_set = set(M_dict.keys()) if assign_params == True: pass else: params_set &= assign_params # type: ignore # Logic for getting the assign params criteria if type(assign_params) is list: selected_params = set(assign_params) & params_set # type: ignore elif type(assign_params) is set: selected_params = assign_params & params_set else: selected_params = params_set # Attribute parameters to each row* params_dict = select_config_M_dict(configs, 0, selected_params) # Handles all cases of parameter types including list for key, value in params_dict.items(): df[key] = df.apply(lambda _: value, axis=1) for i, (_, n_df) in enumerate(df.groupby(['simulation', 'subset', 'run'])): params_dict = select_config_M_dict(configs, i, selected_params) for key, value in params_dict.items(): df.loc[n_df.index, key] = df.loc[n_df.index].apply( lambda _: value, axis=1) # Based on Vitor Marthendal (@marthendalnunes) snippet if use_label == True: psub_map = { order + 1: psub.get('label', '') for (order, psub) in enumerate(psubs) } psub_map[0] = 'Initial State' df['substep_label'] = df.substep.map(psub_map) return df ================================================ FILE: cadCAD/tools/preparation.py ================================================ from typing import Mapping from cadCAD.tools.execution import easy_run from pandas import DataFrame # type: ignore from cadCAD.types import * from cadCAD.tools.types import * from itertools import product from dataclasses import dataclass def sweep_cartesian_product(sweep_params: SweepableParameters) -> SweepableParameters: """ Makes a cartesian product from dictionary values. This is useful for plugging inside the sys_params dict, like: ```python sweep_params = {'a': [0.1, 0.2], 'b': [1, 2]} product_sweep sys_params = {**cartesian_product_sweep(sweep_params), 'c': [0.1]} ``` Usage: >>> sweep_params = {'a': [0.1, 0.2], 'b': [1, 2]} >>> cartesian_product_sweep(sweep_params) {'a': [0.1, 0.1, 0.2, 0.2], 'b': [1, 2, 1, 2]} """ cartesian_product = product(*sweep_params.values()) transpose_cartesian_product = zip(*cartesian_product) zipped_sweep_params = zip(sweep_params.keys(), transpose_cartesian_product) sweep_dict = dict(zipped_sweep_params) sweep_dict = {k: list(v) for k, v in sweep_dict.items()} return sweep_dict def prepare_params(params: SystemParameters, cartesian_sweep: bool = False) -> Mapping[str, List[object]]: simple_params = {k: [v.value] for k, v in params.items() if type(v) is Param} sweep_params: SweepableParameters = {k: v.value for k, v in params.items() if type(v) is ParamSweep} if cartesian_sweep is True: sweep_params = sweep_cartesian_product(sweep_params) else: pass cleaned_params = {**simple_params, **sweep_params} return cleaned_params def prepare_state(state: InitialState) -> Mapping[str, object]: cleaned_state = {k: v.value for k, v in state.items()} return cleaned_state @dataclass class ConfigurationWrapper(): initial_state: InitialState params: SystemParameters timestep_block: StateUpdateBlocks timesteps: int samples: int def run(self, *args, **kwargs) -> DataFrame: output = easy_run(prepare_state(self.initial_state), prepare_params(self.params), self.timestep_block, self.timesteps, self.samples, *args, **kwargs) return output ================================================ FILE: cadCAD/tools/profiling/__init__.py ================================================ from cadCAD.tools.profiling.profile_run import profile_run ================================================ FILE: cadCAD/tools/profiling/profile_run.py ================================================ from typing import Dict from cadCAD.tools import easy_run from cadCAD.types import StateUpdateBlocks, Parameters, State, StateUpdateBlock from time import time import pandas as pd # type: ignore def MEASURE_TIME_SUF(p, s, h, v, p_i): return ('run_time', time()) MEASURING_BLOCK: StateUpdateBlock = { 'label': 'Time Measure', 'policies': {}, 'variables': { 'run_time': MEASURE_TIME_SUF } } # type: ignore def profile_psubs(psubs: StateUpdateBlocks, profile_substeps=True) -> StateUpdateBlocks: """ Updates a TimestepBlock so that a time measuring function is added. """ new_timestep_block: StateUpdateBlocks = [] new_timestep_block.append(MEASURING_BLOCK) if profile_substeps is True: for psub in psubs: new_timestep_block.append(psub) new_timestep_block.append(MEASURING_BLOCK) else: pass return new_timestep_block def profile_run(state_variables: State, params: Parameters, psubs: StateUpdateBlocks, *args, profile_substeps=True, **kwargs) -> pd.DataFrame: if profile_substeps is True: kwargs.update(drop_substeps=False) new_psubs = profile_psubs(psubs, profile_substeps) state_variables.update({'run_time': None}) return easy_run(state_variables, params, new_psubs, *args, **kwargs) ================================================ FILE: cadCAD/tools/profiling/visualizations.py ================================================ from tqdm.auto import tqdm import pandas as pd import plotly.express as px import numpy as np def visualize_elapsed_time_per_ts(df: pd.DataFrame, relative=False) -> None: indexes = ['simulation', 'run', 'timestep', 'substep'] z_df = df.set_index(indexes) first_time = z_df.query( 'timestep == 1 & substep == 1').reset_index([-1, -2]).run_time s = (z_df.run_time - first_time) s.name = 'time_since_start' z_df = z_df.join(s) s = z_df.groupby(indexes[:-1]).time_since_start.max() fig_df = s.reset_index() if relative is True: s = fig_df.groupby(indexes[:-2]).time_since_start.diff() s.name = 'psub_duration' fig_df = fig_df.join(s) y_col = 'psub_duration' else: y_col = 'time_since_start' fig = px.box(fig_df, x='timestep', y=y_col) return fig def visualize_substep_impact(df: pd.DataFrame, relative=True, **kwargs) -> None: indexes = ['simulation', 'run', 'timestep', 'substep'] new_df = df.copy() new_df = new_df.assign(psub_time=np.nan).set_index(indexes) # Calculate the run time associated with PSUBs for ind, gg_df in tqdm(df.query('substep > 0').groupby(indexes[:-1])): g_df = gg_df.reset_index() N_rows = len(g_df) substep_rows = list(range(N_rows))[1:-1:2] for substep_row in substep_rows: t1 = g_df.run_time[substep_row - 1] t2 = g_df.run_time[substep_row + 1] dt = t2 - t1 g_df.loc[substep_row, 'psub_time'] = dt g_df = g_df.set_index(indexes) new_df.loc[g_df.index, 'psub_time'] = g_df.psub_time fig_df = new_df.reset_index().dropna(subset=['psub_time']) if 'substep_label' in fig_df.columns: x_col = 'substep_label' else: x_col = 'substep' fig_df[x_col] = fig_df[x_col] / 2 if relative is True: fig_df = fig_df.assign(relative_psub_time=fig_df.groupby(indexes[:-1]).psub_time.apply(lambda x: x / x.sum())) y_col = 'relative_psub_time' else: y_col = 'psub_time' inds = fig_df[y_col] < fig_df[y_col].quantile(0.95) inds &= fig_df[y_col] > fig_df[y_col].quantile(0.05) fig = px.box(fig_df[inds], x=x_col, y=y_col, **kwargs) return fig ================================================ FILE: cadCAD/tools/types.py ================================================ from typing import NamedTuple, Tuple, Dict, Union, List class InitialValue(NamedTuple): value: object type: type class Param(NamedTuple): value: object type: type class ParamSweep(NamedTuple): value: List[object] type: type InitialState = Dict[str, InitialValue] SystemParameters = Dict[str, Union[Param, ParamSweep]] ================================================ FILE: cadCAD/tools/utils.py ================================================ from cadCAD.types import * import pandas as pd def generic_suf(variable: str, signal: str = "") -> StateUpdateFunction: """ Generate a State Update Function that assigns the signal value to the given variable. By default, the signal has the same identifier as the variable. """ if signal is "": signal = variable else: pass def suf(_1, _2, _3, _4, signals: PolicyOutput) -> StateUpdateTuple: return (variable, signals[signal]) return suf def add_parameter_labels(configs: list, df: pd.DataFrame) -> pd.DataFrame: """Utility function to add the parameters to a dataframe after processing Args: configs (list): The configurations of the simulations df (pd.DataFrame): Simulation dataframe Returns: pd.DataFrame: Simulation dataframe with labels """ # Find the relevant parameters sim_params = pd.DataFrame([x.sim_config["M"] for x in configs]) sim_params[["subset", "simulation", "run"]] = [ [x.subset_id, x.simulation_id, x.run_id] for x in configs ] # Fix because run_id is 0 indexed, but cadCAD dataframe is 1 indexed for runs sim_params["run"] += 1 # Join sim_params = sim_params.set_index(["subset", "simulation", "run"]) df = df.join(sim_params, on=["subset", "simulation", "run"]) return df ================================================ FILE: cadCAD/types.py ================================================ from typing import TypedDict, Callable, Union, Dict, List, Tuple, Iterable from collections import deque State = Dict[str, object] Parameters = Dict[str, object] SweepableParameters = Dict[str, List[object]] Substep = int StateHistory = List[List[State]] PolicyOutput = Dict[str, object] StateVariable = object PolicyFunction = Callable[[Parameters, Substep, StateHistory, State], PolicyOutput] StateUpdateFunction = Callable[[Parameters, Substep, StateHistory, State, PolicyOutput], Tuple[str, StateVariable]] class StateUpdateBlock(TypedDict): policies: Dict[str, PolicyFunction] variables: Dict[str, StateUpdateFunction] StateUpdateBlocks = List[StateUpdateBlock] class ConfigurationDict(TypedDict): T: Iterable # Generator for the timestep variable N: int # Number of MC Runs M: Union[Parameters, SweepableParameters] # Parameters / List of Parameter to Sweep TargetValue = object EnvProcess: Callable[[State, SweepableParameters, TargetValue], TargetValue] EnvProcesses = Dict[str, Callable] TimeSeq = Iterable SimulationID = int Run = int SubsetID = int SubsetWindow = Iterable N_Runs = int ExecutorFunction = Callable[[Parameters, StateHistory, StateUpdateBlocks, EnvProcesses, TimeSeq, SimulationID, Run, SubsetID, SubsetWindow, N_Runs], object] ExecutionParameter = Tuple[ExecutorFunction, Parameters, StateHistory, StateUpdateBlocks, EnvProcesses, TimeSeq, SimulationID, Run, SubsetID, SubsetWindow, N_Runs] class SessionDict(TypedDict): user_id: str experiment_id: int session_id: str simulation_id: int run_id: int subset_id: int subset_window: deque ================================================ FILE: cadCAD/utils/__init__.py ================================================ from functools import reduce from collections import defaultdict from itertools import product import warnings from typing import Union from cadCAD.types import * from typing import List, Dict, Union import functools import operator from pandas import DataFrame # type: ignore class SilentDF(DataFrame): def __repr__(self): return str(hex(id(DataFrame))) def append_dict(dict: dict, new_dict: dict) -> dict: """ >>> append_dict({1: 2, 3: 4}, {3: 5}) {1: 2, 3: 5} """ dict.update(new_dict) return dict def arrange_cols(df: DataFrame, reverse=False) -> DataFrame: """ Reorders `df` columns so that the variable order is `session_metrics` followed by `sys_metrics` and `results_cols` """ session_metrics = ['session_id', 'user_id', 'simulation_id', 'run_id'] sys_metrics = ['run', 'timestep', 'substep'] result_cols = list(set(df.columns) - set(session_metrics) - set(sys_metrics)) result_cols.sort(reverse=reverse) return df[session_metrics + sys_metrics + result_cols] class IndexCounter: def __init__(self): self.i = 0 def __call__(self): self.i += 1 return self.i def compose(*functions: Tuple[callable]) -> object: return reduce(lambda f, g: lambda x: f(g(x)), functions, lambda x: x) def pipe(x: object) -> object: return x def print_pipe(x: object) -> object: print(x) return x def tupalize(k: object, vs: Union[list, dict]): """ >>> tupalize(1, 1) [(1, 1)] >>> tupalize(1, [2, 3]) [(1, 2), (1, 3)] """ l = [] if isinstance(vs, list): for v in vs: l.append((k, v)) else: l.append((k, vs)) return l def flattenDict(l: dict) -> list: """ >>> flattenDict({1: [1, 2, 3], 4: 5}) [{1: 1, 4: 5}, {1: 2, 4: 5}, {1: 3, 4: 5}] """ flat_list = [tupalize(k, vs) for k, vs in l.items()] flat_dict = [dict(items) for items in product(*flat_list)] return flat_dict def flatten(l: Union[list, dict]): if isinstance(l, list): return functools.reduce(operator.iconcat, l, []) elif isinstance(l, dict): return flattenDict(l) def flatMap(f, collection): return flatten(list(map(f, collection))) def dict_filter(dictionary, condition): return dict([(k, v) for k, v in dictionary.items() if condition(v)]) def get_max_dict_val_len(g: Dict[str, List[int]]) -> int: return len(max(g.values(), key=len)) def tabulate_dict(d: Dict[str, List[int]]) -> Dict[str, List[int]]: max_len = get_max_dict_val_len(d) _d = {} for k, vl in d.items(): if len(vl) != max_len: _d[k] = vl + list([vl[-1]] * (max_len-1)) else: _d[k] = vl return _d def flatten_tabulated_dict(d: Dict[str, List[int]]) -> List[dict[str, int]]: max_len = get_max_dict_val_len(d) dl: List[dict] = [{} for i in range(max_len)] for k, vl in d.items(): for v, i in zip(vl, list(range(len(vl)))): dl[i][k] = v return dl def contains_type(_collection, type): return any(isinstance(x, type) for x in _collection) def drop_right(l, n): return l[:len(l) - n] def key_filter(l, keyname): if (type(l) == list): return [v[keyname] for v in l] # Keeping support to dictionaries for backwards compatibility # Should be removed in the future warnings.warn( "The use of a dictionary to describe Partial State Update Blocks will be deprecated. Use a list instead.", FutureWarning) return [v[keyname] for k, v in l.items()] def groupByKey(l): d = defaultdict(list) for key, value in l: d[key].append(value) return list(dict(d).items()).pop() # @curried def rename(new_name, f): f.__name__ = new_name return f def curry_pot(f, *argv): sweep_ind = f.__name__[0:5] == 'sweep' arg_len = len(argv) if sweep_ind is True and arg_len == 4: return f(argv[0])(argv[1])(argv[2])(argv[3]) elif sweep_ind is False and arg_len == 4: return f(argv[0], argv[1], argv[2], argv[3]) elif sweep_ind is True and arg_len == 3: return f(argv[0])(argv[1])(argv[2]) elif sweep_ind is False and arg_len == 3: return f(argv[0], argv[1], argv[2]) else: raise TypeError('curry_pot() needs 3 or 4 positional arguments') ================================================ FILE: cadCAD/utils/execution.py ================================================ from pprint import pprint from cadCAD import logo, version from cadCAD.utils import flatten def print_exec_info(exec_context, configs): print(logo) print(f'cadCAD Version: {version}') print(f'Execution Mode: {exec_context}') models = len(configs) sim_strs, run_vals, timestep_vals, params, sub_states = [], [], [], [], set() for i, config in enumerate(configs): sim_config = config.sim_config n_n = sim_config['N'] n_t = len(sim_config['T']) n_m = len(sim_config['M']) n_s = len(config.initial_state) run_vals.append(n_n) for timestep in [*sim_config['T']]: timestep_vals.append(timestep) if type(sim_config['M']) is dict: params.append(n_m) else: n_m = 0 for state_key in list(config.initial_state.keys()): sub_states.add(state_key) sim_strs.append(f' Simulation {i}: (Timesteps, Params, Runs, Sub-States) = ({n_t}, {n_m}, {n_n}, {n_s})') timesteps = len(timestep_vals) if sum(params) != 0: param_count = sum(params) else: param_count = 0 runs = sum(run_vals) init_states = len(sub_states) print("Simulation Dimensions:") print( f'Entire Simulation: (Models, Unique Timesteps, Params, Total Runs, Sub-States) = ({models}, {timesteps}, {param_count}, {runs}, {init_states})' ) for sim_str in sim_strs: print(sim_str) ================================================ FILE: cadCAD/utils/jupyter.py ================================================ def get_home_dir(user): return f"s3://jupyterbackups/jupyter/{user}/" def set_write_path(sc, user, datafolder_path): return get_home_dir(user) + datafolder_path +f'_{sc.applicationId}' ================================================ FILE: cadCAD/utils/sys_config.py ================================================ from funcy import curry from cadCAD.configuration.utils import ep_time_step, time_step def increment(y, incr_by): return lambda _g, step, sL, s, _input, **kwargs: (y, s[y] + incr_by) def track(y): return lambda _g, step, sL, s, _input, **kwargs: (y, s[y].x) def simple_state_update(y, x): return lambda _g, step, sH, s, _input, **kwargs: (y, x) def simple_policy_update(y): return lambda _g, step, sH, s, **kwargs: y def update_timestamp(y, timedelta, format): return lambda _g, step, sL, s, _input, **kwargs: ( y, ep_time_step(s, dt_str=s[y], fromat_str=format, _timedelta=timedelta) ) def apply(f, y: str, incr_by: int): return lambda _g, step, sL, s, _input, **kwargs: (y, curry(f)(s[y])(incr_by)) def add(y: str, incr_by): return apply(lambda a, b: a + b, y, incr_by) def increment_state_by_int(y: str, incr_by: int): return lambda _g, step, sL, s, _input, **kwargs: (y, s[y] + incr_by) def s(y, x): return lambda _g, step, sH, s, _input, **kwargs: (y, x) def time_model(y, substeps, time_delta, ts_format='%Y-%m-%d %H:%M:%S'): def apply_incriment_condition(s): if s['substep'] == 0 or s['substep'] == substeps: return y, time_step(dt_str=s[y], dt_format=ts_format, _timedelta=time_delta) else: return y, s[y] return lambda _g, step, sL, s, _input, **kwargs: apply_incriment_condition(s) ================================================ FILE: documentation/Historically_State_Access.md ================================================ Historical State Access (DEPRECATED) == #### Motivation The current state (values of state variables) is accessed through the `s` list. When the user requires previous state variable values, they may be accessed through the state history list, `sH`. Accessing the state history should be implemented without creating unintended feedback loops on the current state. The 3rd parameter of state and policy update functions (labeled as `sH` of type `list[list[dict]]`) provides access to past Partial State Update Block (PSUB) given a negative offset number. `access_block` is used to access past PSUBs (`list[dict]`) from `sH`. For example, an offset of `-2` denotes the second to last PSUB. #### Exclusion list Create a list of states to exclude from the reported PSU. ```python exclusion_list = [ 'nonexistent', 'last_x', '2nd_to_last_x', '3rd_to_last_x', '4th_to_last_x' ] ``` ##### Example Policy Updates ###### Last partial state update ```python def last_update(_params, substep, sH, s, **kwargs): return {"last_x": access_block( state_history=sH, target_field="last_x", # Add a field to the exclusion list psu_block_offset=-1, exculsion_list=exclusion_list ) } ``` * Note: Although `target_field` adding a field to the exclusion may seem redundant, it is useful in the case of the exclusion list being empty while the `target_field` is assigned to a state or a policy key. ##### Define State Updates ###### 2nd to last partial state update ```python def second2last_update(_params, substep, sH, s, **kwargs): return {"2nd_to_last_x": access_block(sH, "2nd_to_last_x", -2, exclusion_list)} ``` ###### 3rd to last partial state update ```python def third_to_last_x(_params, substep, sH, s, _input, **kwargs): return '3rd_to_last_x', access_block(sH, "3rd_to_last_x", -3, exclusion_list) ``` ###### 4rd to last partial state update ```python def fourth_to_last_x(_params, substep, sH, s, _input, **kwargs): return '4th_to_last_x', access_block(sH, "4th_to_last_x", -4, exclusion_list) ``` ###### Non-exsistent partial state update * `psu_block_offset >= 0` doesn't exist ```python def nonexistent(_params, substep, sH, s, _input, **kwargs): return 'nonexistent', access_block(sH, "nonexistent", 0, exclusion_list) ``` #### [Example Simulation:](examples/historical_state_access.py) #### Example Output: ###### State History ``` +----+-------+-----------+------------+-----+ | | run | substep | timestep | x | |----+-------+-----------+------------+-----| | 0 | 1 | 0 | 0 | 0 | | 1 | 1 | 1 | 1 | 1 | | 2 | 1 | 2 | 1 | 2 | | 3 | 1 | 3 | 1 | 3 | | 4 | 1 | 1 | 2 | 4 | | 5 | 1 | 2 | 2 | 5 | | 6 | 1 | 3 | 2 | 6 | | 7 | 1 | 1 | 3 | 7 | | 8 | 1 | 2 | 3 | 8 | | 9 | 1 | 3 | 3 | 9 | +----+-------+-----------+------------+-----+ ``` ###### Accessed State History: Example: `last_x` ``` +----+-----------------------------------------------------------------------------------------------------------------------------------------------------+ | | last_x | |----+-----------------------------------------------------------------------------------------------------------------------------------------------------| | 0 | [] | | 1 | [{'x': 0, 'run': 1, 'substep': 0, 'timestep': 0}] | | 2 | [{'x': 0, 'run': 1, 'substep': 0, 'timestep': 0}] | | 3 | [{'x': 0, 'run': 1, 'substep': 0, 'timestep': 0}] | | 4 | [{'x': 1, 'run': 1, 'substep': 1, 'timestep': 1}, {'x': 2, 'run': 1, 'substep': 2, 'timestep': 1}, {'x': 3, 'run': 1, 'substep': 3, 'timestep': 1}] | | 5 | [{'x': 1, 'run': 1, 'substep': 1, 'timestep': 1}, {'x': 2, 'run': 1, 'substep': 2, 'timestep': 1}, {'x': 3, 'run': 1, 'substep': 3, 'timestep': 1}] | | 6 | [{'x': 1, 'run': 1, 'substep': 1, 'timestep': 1}, {'x': 2, 'run': 1, 'substep': 2, 'timestep': 1}, {'x': 3, 'run': 1, 'substep': 3, 'timestep': 1}] | | 7 | [{'x': 4, 'run': 1, 'substep': 1, 'timestep': 2}, {'x': 5, 'run': 1, 'substep': 2, 'timestep': 2}, {'x': 6, 'run': 1, 'substep': 3, 'timestep': 2}] | | 8 | [{'x': 4, 'run': 1, 'substep': 1, 'timestep': 2}, {'x': 5, 'run': 1, 'substep': 2, 'timestep': 2}, {'x': 6, 'run': 1, 'substep': 3, 'timestep': 2}] | | 9 | [{'x': 4, 'run': 1, 'substep': 1, 'timestep': 2}, {'x': 5, 'run': 1, 'substep': 2, 'timestep': 2}, {'x': 6, 'run': 1, 'substep': 3, 'timestep': 2}] | +----+-----------------------------------------------------------------------------------------------------------------------------------------------------+ ``` ================================================ FILE: documentation/Policy_Aggregation.md ================================================ Policy Aggregation == For each Partial State Update, multiple policy dictionaries are aggregated into a single dictionary to be inputted into all state functions using an initial reduction function and optional subsequent map functions. #### Aggregate Function Composition: ```python # Reduce Function add = lambda a, b: a + b # Used to add policy values of the same key # Map Function mult_by_2 = lambda y: y * 2 # Used to multiply all policy values by 2 policy_ops=[add, mult_by_2] ``` ##### Example Policy Updates per Partial State Update (PSU) ```python def p1_psu1(_params, step, sH, s, **kwargs): return {'policy1': 1} def p2_psu1(_params, step, sH, s, **kwargs): return {'policy2': 2} ``` * `add` not applicable due to lack of redundant policies * `mult_by_2` applied to all policies * Result: `{'policy1': 2, 'policy2': 4}` ```python def p1_psu2(_params, step, sH, s, **kwargs): return {'policy1': 2, 'policy2': 2} def p2_psu2(_params, step, sH, s, **kwargs): return {'policy1': 2, 'policy2': 2} ``` * `add` applicable due to redundant policies * `mult_by_2` applied to all policies * Result: `{'policy1': 8, 'policy2': 8}` ```python def p1_psu3(_params, step, sH, s, **kwargs): return {'policy1': 1, 'policy2': 2, 'policy3': 3} def p2_psu3(_params, step, sH, s, **kwargs): return {'policy1': 1, 'policy2': 2, 'policy3': 3} ``` * `add` applicable due to redundant policies * `mult_by_2` applied to all policies * Result: `{'policy1': 4, 'policy2': 8, 'policy3': 12}` #### Aggregate Policies using functions ```python from cadCAD.configuration import Experiment exp = Experiment() exp.append_model( sim_configs=???, initial_state=???, partial_state_update_blocks=???, policy_ops=[add, mult_by_2] # Default: [lambda a, b: a + b] ) ``` #### Example ##### * [System Model Configuration](examples/policy_aggregation.py) ##### * Simulation Results: ``` +----+---------------------------------------------+-------+------+-----------+------------+ | | policies | run | s1 | substep | timestep | |----+---------------------------------------------+-------+------+-----------+------------| | 0 | {} | 1 | 0 | 0 | 0 | | 1 | {'policy1': 2, 'policy2': 4} | 1 | 1 | 1 | 1 | | 2 | {'policy1': 8, 'policy2': 8} | 1 | 2 | 2 | 1 | | 3 | {'policy3': 12, 'policy1': 4, 'policy2': 8} | 1 | 3 | 3 | 1 | | 4 | {'policy1': 2, 'policy2': 4} | 1 | 4 | 1 | 2 | | 5 | {'policy1': 8, 'policy2': 8} | 1 | 5 | 2 | 2 | | 6 | {'policy3': 12, 'policy1': 4, 'policy2': 8} | 1 | 6 | 3 | 2 | | 7 | {'policy1': 2, 'policy2': 4} | 1 | 7 | 1 | 3 | | 8 | {'policy1': 8, 'policy2': 8} | 1 | 8 | 2 | 3 | | 9 | {'policy3': 12, 'policy1': 4, 'policy2': 8} | 1 | 9 | 3 | 3 | +----+---------------------------------------------+-------+------+-----------+------------+ ``` ================================================ FILE: documentation/README.md ================================================ Simulation Configuration == ## Introduction Given a **Simulation Configuration**, cadCAD produces datasets that represent the evolution of the state of a system over [discrete time](https://en.wikipedia.org/wiki/Discrete_time_and_continuous_time#Discrete_time). The state of the system is described by a set of [State Variables](#State-Variables). The dynamic of the system is described by [Policy Functions](#Policy-Functions) and [State Update Functions](#State-Update-Functions), which are evaluated by cadCAD according to the definitions set by the user in [Partial State Update Blocks](#Partial-State-Update-Blocks). A Simulation Configuration is comprised of a [System Model](#System-Model) and a set of [Simulation Properties](#Simulation-Properties). ### Experiments `cadCAD.configuration.Experiment` is a unique representation of an experiment of one or more configured System Models. The `append_model` method of `Experiment` appends a System Model configurations, each representing a single `run`. ```python from cadCAD.configuration import Experiment exp = Experiment() exp.append_model( model_id = ..., # OPTIONAL: System Model label initial_state = ..., # System Model partial_state_update_blocks = ..., # System Model policy_ops = ..., # System Model sim_configs = ..., # Simulation Properties user_id = ..., # OPTIONAL: Configuration User ID ) ``` Parameters: `append_model` * **model_id** : str - OPTIONAL: System Model label * **initial_state** : _dict_ - [State Variables](#State-Variables) and their initial values * **partial_state_update_blocks** : List[dict[dict]] - list of [Partial State Update Blocks](#Partial-State-Update-Blocks) * **policy_ops** : List[functions] - See [Policy Aggregation](Policy_Aggregation.md) * **sim_configs** - See [System Model Parameter Sweep](System_Model_Parameter_Sweep.md) * **user_id** : str - OPTIONAL: Configuration User ID ## Simulation Properties Simulation properties are passed to `append_model` in the `sim_configs` parameter. To construct this parameter, we use the `config_sim` function in `cadCAD.configuration.utils` ```python from cadCAD.configuration.utils import config_sim from cadCAD.configuration import Experiment sim_config_dict = { "N": ..., "T": range(...), "M": ... } c = config_sim(sim_config_dict) exp = Experiment() exp.append_model( ... sim_configs = c # Simulation Properties ) ``` ### T - Simulation Length Computer simulations run in discrete time: >Discrete time views values of variables as occurring at distinct, separate "points in time", or equivalently as being unchanged throughout each non-zero region of time ("time period")—that is, time is viewed as a discrete variable. (...) This view of time corresponds to a digital clock that gives a fixed reading of 10:37 for a while, and then jumps to a new fixed reading of 10:38, etc. ([source: Wikipedia](https://en.wikipedia.org/wiki/Discrete_time_and_continuous_time#Discrete_time)) As is common in many simulation tools, in cadCAD too we refer to each discrete unit of time as a **timestep**. cadCAD increments a "time counter", and at each step it updates the state variables according to the equations that describe the system. The main simulation property that the user must set when creating a Simulation Configuration is the number of timesteps in the simulation. In other words, for how long do they want to simulate the system that has been modeled. ### N - Number of Runs cadCAD facilitates running multiple simulations of the same system sequentially, reporting the results of all those runs in a single dataset. This is especially helpful for running [Monte Carlo Simulations](https://github.com/cadCAD-org/demos/blob/master/tutorials/robots_and_marbles/robot-marbles-part-4/robot-marbles-part-4.ipynb). ### M - Parameters of the System Parameters of the system, passed to the state update functions and the policy functions in the `params` parameter are defined here. See [System Model Parameter Sweep](System_Model_Parameter_Sweep.md) for more information. ## System Model The System Model describes the system that will be simulated in cadCAD. It is comprised of a set of [State Variables](##State-Variables) and the [State Update Functions](#State-Update-Functions) that determine the evolution of the state of the system over time. [Policy Functions](#Policy-Functions) (representations of user policies or internal system control policies) may also be part of a System Model. ### State Variables >A state variable is one of the set of variables that are used to describe the mathematical "state" of a dynamical system. Intuitively, the state of a system describes enough about the system to determine its future behaviour in the absence of any external forces affecting the system. ([source: Wikipedia](https://en.wikipedia.org/wiki/State_variable)) cadCAD can handle state variables of any Python data type, including custom classes. It is up to the user of cadCAD to determine the state variables needed to **sufficiently and accurately** describe the system they are interested in. State Variables are passed to `append_model` along with its initial values, as a Python `dict` where the `dict_keys` are the names of the variables and the `dict_values` are their initial values. ```python from cadCAD.configuration import Experiment genesis_states = { 'state_variable_1': 0, 'state_variable_2': 0, 'state_variable_3': 1.5, 'timestamp': '2019-01-01 00:00:00' } exp = Experiment() exp.append_model( initial_state = genesis_states, ... ) ``` ### State Update Functions State Update Functions represent equations according to which the state variables change over time. Each state update function must return a tuple containing a string with the name of the state variable being updated and its new value. Each state update function can only modify a single state variable. The general structure of a state update function is: ```python def state_update_function_A(_params, substep, sH, s, _input, **kwargs): ... return 'state_variable_name', new_value ``` Parameters: * **_params** : _dict_ - [System parameters](System_Model_Parameter_Sweep.md) * **substep** : _int_ - Current [substep](#Substep) * **sH** : _list[list[dict_]] - Historical values of all state variables for the simulation. See [Historical State Access (DEPRECATED)](Historically_State_Access.md) for details * **s** : _dict_ - Current state of the system, where the `dict_keys` are the names of the state variables and the `dict_values` are their current values. * **_input** : _dict_ - Aggregation of the signals of all policy functions in the current [Partial State Update Block](#Partial-State-Update-Block) * **\*\*kwargs** - State Update feature extensions Return: * _tuple_ containing a string with the name of the state variable being updated and its new value. State update functions should not modify any of the parameters passed to it, as those are mutable Python objects that cadCAD relies on in order to run the simulation according to the specifications. ### Policy Functions A Policy Function computes one or more signals to be passed to [State Update Functions](#State-Update-Functions) (via the _\_input_ parameter). Read [this article](https://github.com/cadCAD-org/demos/blob/master/tutorials/robots_and_marbles/robot-marbles-part-2/robot-marbles-part-2.ipynb) for details on why and when to use policy functions. The general structure of a policy function is: ```python def policy_function_1(_params, substep, sH, s, **kwargs): ... return {'signal_1': value_1, ..., 'signal_N': value_N} ``` Parameters: * **_params** : _dict_ - [System parameters](System_Model_Parameter_Sweep.md) * **substep** : _int_ - Current [substep](#Substep) * **sH** : _list[list[dict_]] - Historical values of all state variables for the simulation. See [Historical State Access (DEPRECATED)](Historically_State_Access.md) for details * **s** : _dict_ - Current state of the system, where the `dict_keys` are the names of the state variables and the `dict_values` are their current values. * **\*\*kwargs** - Policy Update feature extensions Return: * _dict_ of signals to be passed to the state update functions in the same [Partial State Update Block](#Partial-State-Update-Blocks) Policy functions should not modify any of the parameters passed to it, as those are mutable Python objects that cadCAD relies on in order to run the simulation according to the specifications. At each [Partial State Update Block](#Partial-State-Update-Blocks) (PSUB), the `dicts` returned by all policy functions within that PSUB dictionaries are aggregated into a single `dict` using an initial reduction function (a key-wise operation, default: `dic1['keyA'] + dic2['keyA']`) and optional subsequent map functions. The resulting aggregated `dict` is then passed as the `_input` parameter to the state update functions in that PSUB. For more information on how to modify the aggregation method, see [Policy Aggregation](Policy_Aggregation.md). ### Partial State Update Blocks A **Partial State Update Block** (PSUB) is a set of State Update Functions and Policy Functions such that State Update Functions in the set are independent from each other and Policies in the set are independent from each other and from the State Update Functions in the set. In other words, if a state variable is updated in a PSUB, its new value cannot impact the State Update Functions and Policy Functions in that PSUB - only those in the next PSUB. ![](https://i.imgur.com/9rlX9TG.png) Partial State Update Blocks are passed to `append_model` as a list of Python `dicts` where the `dict_keys` are named `"policies"` and `"variables"` and the values are also Python `dicts` where the keys are the names of the policy and state update functions and the values are the functions. ```python from cadCAD.configuration import Experiment PSUBs = [ { "policies": { "b_1": policy_function_1, ... "b_J": policy_function_J }, "variables": { "s_1": state_update_function_1, ... "s_K": state_update_function_K } }, #PSUB_1, {...}, #PSUB_2, ... {...} #PSUB_M ] exp = Experiment() exp.append_model( ... partial_state_update_blocks = PSUBs, ... ) ``` #### Substep At each timestep, cadCAD iterates over the `partial_state_update_blocks` list. For each Partial State Update Block, cadCAD returns a record containing the state of the system at the end of that PSUB. We refer to that subdivision of a timestep as a `substep`. ## Result Dataset cadCAD returns a dataset containing the evolution of the state variables defined by the user over time, with three `int` indexes: * `subset` - identifies the subset per sweepable parameter produced by a parameter sweep (ver. `0.3.1`'s result was multiple datasets; A single dataset per sweepable parameter). * `run` - identifies the [run](#N-Number-of-Runs) * `timestep` - discrete unit of time (the total number of timesteps is defined by the user in the [T Simulation Parameter](#T-Simulation-Length)) * `substep` - subdivision of timestep (the number of [substeps](#Substeps) is the same as the number of Partial State Update Blocks) * `simulation` - **Alpha: Ignore** Therefore, the total number of records in the resulting dataset is `N` x `T` x `len(partial_state_update_blocks)` #### [System Simulation Execution](Simulation_Execution.md) ================================================ FILE: documentation/Simulation_Execution.md ================================================ # Simulation Execution System Simulations are executed with the execution engine executor (`cadCAD.engine.Executor`) given System Model Configurations. There are multiple simulation Execution Modes and Execution Contexts. ## Steps ### 1. *Choose Execution Mode* #### Simulation Execution Modes: `cadCAD` executes a process per System Model Configuration and a thread per System Simulation. #### Class: `cadCAD.engine.ExecutionMode` #### Attributes: * **Local Mode (Default):** Automatically selects Single Threaded or Multi-Process Modes (Example: `cadCAD.engine.ExecutionMode().local_mode`). * **Single Threaded Mode:** A single threaded Execution Mode for a single System Model Configuration (Example: `cadCAD.engine.ExecutionMode().single_mode`). * **Multi-Process Mode:** Execution Mode for System Model Simulations which executes Multiple processes within multiple processes per given System Model Configuration (Example: `cadCAD.engine.ExecutionMode().multi_mode`). ### 2. *Create Execution Context using Execution Mode* ```python from cadCAD.engine import ExecutionMode, ExecutionContext exec_mode = ExecutionMode() local_mode_ctx = ExecutionContext(context=exec_mode.local_mode) ``` ### 3. *Create Simulation Executor* ```python from cadCAD.engine import Executor from ... import exp # import of an instantiated of an `cadCAD.configuration.Experiment` object simulation = Executor(exec_context=local_mode_ctx, configs=exp.configs) ``` ### 4. *Execute Simulation & Produce System Event Dataset* A Simulation execution produces a System Event Dataset and the Tensor Field applied to initial states used to create it. ```python import pandas as pd raw_system_events, tensor_field, sessions = simulation.execute() # Simulation Result Types: # raw_system_events: List[dict] # tensor_field: pd.DataFrame # Result System Events DataFrame simulation_result = pd.DataFrame(raw_system_events) ``` #### Example Tensor Field ``` +----+-----+--------------------------------+--------------------------------+ | | m | b1 | s1 | |----+-----+--------------------------------+--------------------------------| | 0 | 1 | | | | 1 | 2 | | | | 2 | 3 | | | +----+-----+--------------------------------+--------------------------------+ ``` #### Example Result: System Events DataFrame ``` +----+------+-----------+------------+--------+-----+---------+----------+ | | s1 | s2 | simulation | subset | run | substep | timestep | |----+------+-----------|------------+--------+-----+---------+----------| | 0 | 0 | 0.0 | 0 | 0 | 1 | 0 | 0 | | 1 | 1 | 4 | 0 | 0 | 1 | 1 | 1 | | 2 | 2 | 6 | 0 | 0 | 1 | 2 | 1 | | 3 | 3 | [ 30 300] | 0 | 0 | 1 | 3 | 1 | | 4 | 0 | 0.0 | 1 | 0 | 1 | 0 | 0 | | 5 | 1 | 4 | 1 | 0 | 1 | 1 | 1 | | 6 | 2 | 6 | 1 | 0 | 1 | 2 | 1 | | 7 | 3 | [ 30 300] | 1 | 0 | 1 | 3 | 1 | +----+------+-----------+------------+--------+-----+---------+----------+ ``` ## Execution Examples: ### Single Simulation Execution (Single Threaded Execution) Example System Model Configurations: * [System Model A](examples/sys_model_A.py) * [System Model B](examples/sys_model_B.py) Example Simulation Executions: * [System Model A](examples/sys_model_A_exec.py) * [System Model B](examples/sys_model_B_exec.py) ```python import pandas as pd from tabulate import tabulate from cadCAD.engine import ExecutionMode, ExecutionContext, Executor from documentation.examples import sys_model_A from documentation.examples.sys_model_A import exp exec_mode = ExecutionMode() # Single Process Execution using a Single System Model Configuration: # sys_model_A local_mode_ctx = ExecutionContext(context=exec_mode.local_mode) sys_model_A_simulation = Executor(exec_context=local_mode_ctx, configs=exp.configs) sys_model_A_raw_result, sys_model_A_tensor_field, sessions = sys_model_A_simulation.execute() sys_model_A_result = pd.DataFrame(sys_model_A_raw_result) print() print("Tensor Field: sys_model_A") print(tabulate(sys_model_A_tensor_field, headers='keys', tablefmt='psql')) print("Result: System Events DataFrame") print(tabulate(sys_model_A_result, headers='keys', tablefmt='psql')) print() ``` #### Multiple Simulation Execution ##### Multi-Process / Threaded Execution Example System Model Configurations: * [System Model A](examples/sys_model_A.py) * [System Model B](examples/sys_model_B.py) Example Simulation Executions: * [System Model AB](examples/sys_model_AB_exec.py) ```python import pandas as pd from tabulate import tabulate from cadCAD.engine import ExecutionMode, ExecutionContext, Executor from documentation.examples import sys_model_A, sys_model_B, system_model_AB_exp exec_mode = ExecutionMode() # # Multiple Processes Execution using Multiple System Model Configurations: # # sys_model_A & sys_model_B local_mode_ctx = ExecutionContext(context=exec_mode.local_mode) sys_model_AB_simulation = Executor(exec_context=local_mode_ctx, configs=system_model_AB_exp.configs) sys_model_AB_raw_result, sys_model_AB_tensor_field, sessions = sys_model_AB_simulation.execute() sys_model_AB_result = pd.DataFrame(sys_model_AB_raw_result) print() print("Tensor Field:") print(tabulate(sys_model_AB_tensor_field, headers='keys', tablefmt='psql')) print("Result: System Events DataFrame:") print(tabulate(sys_model_AB_result, headers='keys', tablefmt='psql')) print() ``` ##### System Model Parameter Sweep [Info](System_Model_Parameter_Sweep.md) Example: [Param Sweep](examples/param_sweep.py) ```python import pandas as pd from tabulate import tabulate from cadCAD.engine import ExecutionMode, ExecutionContext, Executor from documentation.examples import param_sweep from documentation.examples.param_sweep import exp exec_mode = ExecutionMode() local_mode_ctx = ExecutionContext(context=exec_mode.local_mode) run = Executor(exec_context=local_mode_ctx, configs=exp.configs) raw_result, tensor_field, sessions = run.execute() result = pd.DataFrame(raw_result) print() print("Tensor Field:") print(tabulate(tensor_field, headers='keys', tablefmt='psql')) print("Output:") print(tabulate(result, headers='keys', tablefmt='psql')) print() ``` ================================================ FILE: documentation/System_Configuration.md ================================================ # Display System Model Configurations: ## Announcement: See [CHANGELOG](CHANGELOG.md) The `cadCAD.configuration.Experiment().configs` (System Model Configurations) `list` has been flattened to contain single run `Configuration` objects. This functionality will be restored in a subsequent release by a class that returns the original representation in ver. `0.3.1`. * The conversion utilities have been provided to restore its original representation of configurations with runs >= 1 * System Configuration Conversions: * Configuration as list of Configuration Objects (as in ver. `0.3.1`) * New: System Configuration as a Pandas DataFrame * New: System Configuration as list of Dictionaries ## Conversions ##### Note: The following applies as a result of simulation execution #### Imports: ```python from cadCAD.configuration.utils import configs_as_objs, configs_as_dataframe, configs_as_dicts ``` #### System Configurations as list of Configuration Objects Example: * `configs` is temporarily returned in a flattened format and reformatted into its intended format. * `Configuration` objects at `0x10790e470` and `0x1143dd630` are reconstituted into objects at `0x10790e7b8` and `0x116268908` respectively. ```python from ... import exp # import of an instantiated `cadCAD.configuration.Experiment` object flattened_configs = exp.configs print('Flattened Format: Temporary') pprint(flattened_configs) print() print('Intended Format:') intended_configs = configs_as_objs(flattened_configs) pprint(intended_configs) print() print("Object: cadCAD.configuration.Configuration(...).sim_config") pprint(intended_configs[0].sim_config) print() ``` Return: ``` Flattened Format: Temporary [, , , ] Intended Format: [, ] Object: cadCAD.configuration.Configuration(...).sim_config {'M': [{}], 'N': 2, 'T': range(0, 1), 'run_id': 1, 'simulation_id': 0, 'subset_id': 0, 'subset_window': deque([0, None], maxlen=2)} ``` #### System Configurations as a Pandas DataFrame ```python flattened_configs = configs configs_df = configs_as_dataframe(configs) configs_df ``` #### System Configurations as list of Dictionaries ```python configs_dicts: list = configs_as_dicts(configs) pprint(configs_dicts[0]['sim_config']) ``` Return: ``` {'env_processes': {'s3': [ at 0x7f8f9c99bd90>, at 0x7f8f9c9a11e0>], 's4': .trigger..env_update at 0x7f8f9c9a12f0>}, 'exogenous_states': {}, 'initial_state': {'s1': 0.0, 's2': 0.0, 's3': 1.0, 's4': 1.0, 'timestamp': '2018-10-01 15:16:24'}, 'kwargs': {}, 'partial_state_updates': [{'policies': {'p1': , 'p2': }, 'variables': {'s1': , 's2': , 's3': . at 0x7f8f9c99bae8>, 's4': . at 0x7f8f9c99bea0>, 'timestamp': . at 0x7f8f9c99b730>}}, {'policies': {'p1': , 'p2': }, 'variables': {'s1': , 's2': , 's3': . at 0x7f8f9c99bbf8>, 's4': . at 0x7f8f9c9a1048>, 'timestamp': . at 0x7f8f9c99b840>}}, {'policies': {'p1': , 'p2': }, 'variables': {'s1': , 's2': , 's3': . at 0x7f8f9c99bd08>, 's4': . at 0x7f8f9c9a1158>, 'timestamp': . at 0x7f8f9c99b950>}}], 'policy_ops': [ at 0x7f8f9cb39158>], 'run_id': 249, 'seeds': {'a': , 'b': , 'c': , 'z': }, 'session_id': 'cadCAD_user=0_249', 'sim_config': {'M': {'alpha': 1, 'beta': 2, 'gamma': 3, 'omega': 7}, 'N': 250, 'T': range(0, 5000), 'run_id': 249, 'simulation_id': 0}, 'simulation_id': 0, 'user_id': 'cadCAD_user'} ``` ================================================ FILE: documentation/System_Model_Parameter_Sweep.md ================================================ System Model Parameter Sweep == Parametrization of a System Model configuration that produces multiple configurations. ##### Set Parameters *Note:* `params` values require up to a maximum of 2 distinct lengths ```python params = { 'alpha': [1], 'beta': [2, 5], 'gamma': [3, 4], 'omega': [7] } ``` The parameters above produce 2 Runs per Simulation. * Run 1: * `alpha = 1` * `beta = 2` * `gamma = 3` * `omega = 7` * Run 2: * `alpha = 1` * `beta = 5` * `gamma = 4` * `omega = 7` All parameters can also be set to include a single parameter each, which will result in a single simulation. ##### Example State Updates Previous State: `y = 0` ```python def state_update(_params, step, sH, s, _input, **kwargs): y = 'state' x = s['state'] + _params['alpha'] + _params['gamma'] return y, x ``` * Updated State: * Simulation 1: `y = 4 = 0 + 1 + 3` * Simulation 2: `y = 5 = 0 + 1 + 4` ##### Example Policy Updates ```python # Internal States per Mechanism def policies(_params, step, sH, s, **kwargs): return {'beta': _params['beta'], 'gamma': _params['gamma']} ``` * Simulation 1: `{'beta': 2, 'gamma': 3]}` * Simulation 2: `{'beta': 5, 'gamma': 4}` ##### Configure Simulation ```python from cadCAD.configuration.utils import config_sim g = { 'alpha': [1], 'beta': [2, 5], 'gamma': [3, 4], 'omega': [7] } sim_config = config_sim( { "N": 2, "T": range(5), "M": g, } ) ``` #### Example ##### * [System Model Configuration](examples/param_sweep.py) ================================================ FILE: documentation/__init__.py ================================================ ================================================ FILE: documentation/cadCAD-v0.4.23-Model-Upgrade-Guide.md ================================================
Feature ver. 0.4.23 ver. 0.3.1 (Deprecated)
Experiments
from cadCAD.configuration import Experiment
exp = Experiment()
exp.append_configs(...) 
from cadCAD.configuration import append_configs
append_configs(…)         
Local Execution Mode
          
from cadCAD.engine import ExecutionMode, ExecutionContext
exec_mode = ExecutionMode()
local_ctx = ExecutionContext(context=exec_mode.local_mode)         

Multi-Threaded

from cadCAD.engine import ExecutionMode, ExecutionContext
exec_mode = ExecutionMode()
single_ctx = ExecutionContext(context=exec_mode.multi_proc)

Single-Threaded

from cadCAD.engine import ExecutionMode, ExecutionContext
exec_mode = ExecutionMode()
multi_ctx = ExecutionContext(context=exec_mode.single_proc)
            
cadCAD Post-Processing Enhancements / Modifications
import pandas as pd
from tabulate import tabulate
from cadCAD.engine import ExecutionMode, ExecutionContext, Executor
import system_model_A, system_model_B

from cadCAD import configs
exec_mode = ExecutionMode()

local_ctx = ExecutionContext(context=exec_mode.local_mode)
simulation = Executor(exec_context=local_ctx, configs=configs)
raw_result, sys_model, _ = simulation.execute()
result = pd.DataFrame(raw_result)
print(tabulate(result, headers='keys', tablefmt='psql'))
        
import pandas as pd
from tabulate import tabulate
from cadCAD.engine import ExecutionMode, ExecutionContext, Executor
import system_model_A, system_model_B
from cadCAD import configs

exec_mode = ExecutionMode()
multi_ctx = ExecutionContext(context=exec_mode.multi_proc)
simulation = Executor(exec_context=multi_ctx, configs=configs)
i = 0
config_names = ['sys_model_A', 'sys_model_B']
for raw_result, _ in simulation.execute():
result = pd.DataFrame(raw_result)
print()
print(f"{config_names[i]} Result: System Events DataFrame:")
print(tabulate(result, headers='keys', tablefmt='psql'))
print()
i += 1
           
   
Expandable state and policy update parameter
def state_update(_params, substep, sH, s, _input, **kwargs):
…
return 'state_variable_name', new_value
def policy(_params, substep, sH, s, **kwargs):
…
return {'signal_1': value_1, …, 'signal_N': value_N}
   
     
def state_update(_params, substep, sH, s, _input):
…
return 'state_variable_name', new_value
def policy(_params, substep, sH, s):
…
return {'signal_1': value_1, …, 'signal_N': value_N}  
   
================================================ FILE: documentation/cadCAD-v0.4.27-Model-Upgrade-Guide.md ================================================
Feature ver. 0.4.27 ver. 0.4.23
Experiments & System Model Configurations
from cadCAD.configuration import Experiment

exp = Experiment()
exp.append_model(
    model_id = 'sys_model_1', # System Model
    initial_state = ..., # System Model
    partial_state_update_blocks = ..., # System Model
    policy_ops = ..., # System Model
    sim_configs = ..., # Simulation Properties
)
exp.append_model(
    model_id = 'sys_model_2', # System Model
    ...
)

configs = exp.configs
from cadCAD import configs
from cadCAD.configuration import Experiment
exp = Experiment()
exp.append_configs(...)       
cadCAD Post-Processing Modifications
import pandas as pd
from tabulate import tabulate
from cadCAD.engine import ExecutionMode, ExecutionContext, Executor
from simulations.regression_tests.experiments import multi_exp
from simulations.regression_tests.models import config_multi_1, config_multi_2

exec_mode = ExecutionMode()

local_proc_ctx = ExecutionContext(context=exec_mode.local_mode)
run = Executor(exec_context=local_proc_ctx, configs=multi_exp.configs)

raw_result, tensor_fields, _ = run.execute()
result = pd.DataFrame(raw_result)
print(tabulate(tensor_fields[0], headers='keys', tablefmt='psql'))
print(tabulate(result, headers='keys', tablefmt='psql'))
import pandas as pd
from tabulate import tabulate
from cadCAD.engine import ExecutionMode, ExecutionContext, Executor
import system_model_A, system_model_B

from cadCAD import configs
exec_mode = ExecutionMode()

local_ctx = ExecutionContext(context=exec_mode.local_mode)
simulation = Executor(exec_context=local_ctx, configs=configs)
raw_result, sys_model, _ = simulation.execute()
result = pd.DataFrame(raw_result)
print(tabulate(result, headers='keys', tablefmt='psql'))           
   
================================================ FILE: documentation/cadCAD-v0.4.28-Model-Upgrade-Guide.md ================================================
Feature ver. 0.4.28 ver. 0.4.23
Experiments & System Model Configurations
from cadCAD.configuration import Experiment

exp = Experiment()
exp.append_model(
    model_id = 'sys_model_1', # System Model - OPTIONAL
    initial_state = ..., # System Model
    partial_state_update_blocks = ..., # System Model
    policy_ops = ..., # System Model
    sim_configs = ..., # Simulation Properties
)
exp.append_model(...)

configs = exp.configs
from cadCAD import configs
from cadCAD.configuration import Experiment
exp = Experiment()
exp.append_configs(...)       
cadCAD Post-Processing Modifications
import pandas as pd
from tabulate import tabulate
from cadCAD.engine import ExecutionMode, ExecutionContext, Executor
from simulations.regression_tests.experiments import multi_exp
from simulations.regression_tests.models import config_multi_1, config_multi_2

exec_mode = ExecutionMode()

local_proc_ctx = ExecutionContext(context=exec_mode.local_mode)
run = Executor(exec_context=local_proc_ctx, configs=multi_exp.configs)

raw_result, tensor_fields, _ = run.execute()
result = pd.DataFrame(raw_result)
print(tabulate(tensor_fields[0], headers='keys', tablefmt='psql'))
print(tabulate(result, headers='keys', tablefmt='psql'))
import pandas as pd
from tabulate import tabulate
from cadCAD.engine import ExecutionMode, ExecutionContext, Executor
import system_model_A, system_model_B

from cadCAD import configs
exec_mode = ExecutionMode()

local_ctx = ExecutionContext(context=exec_mode.local_mode)
simulation = Executor(exec_context=local_ctx, configs=configs)
raw_result, sys_model, _ = simulation.execute()
result = pd.DataFrame(raw_result)
print(tabulate(result, headers='keys', tablefmt='psql'))           
   
================================================ FILE: documentation/examples/__init__.py ================================================ from cadCAD.configuration import Experiment system_model_AB_exp = Experiment() ================================================ FILE: documentation/examples/cadCAD_diagram.ipynb ================================================ { "cells": [ { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "def policy_1(p, s, h, v):\n", " return {\"pi_1\": v[\"var_1\"]}\n", "\n", "\n", "def policy_2(p, s, h, v):\n", " return {\"pi_1\": v[\"var_1\"], \"pi_2\": v[\"var_1\"] * v[\"var_2\"]}\n", "\n", "\n", "def suf_1(p, s, h, v, pi):\n", " return (\"var_1\", pi[\"pi_1\"])\n", "\n", "\n", "def suf_2(p, s, h, v, pi):\n", " return (\"var_2\", pi[\"pi_2\"])\n", "\n", "\n", "psubs = [\n", " {\n", " \"label\": \"Test\",\n", " \"policies\": {\"policy_1\": policy_1, \"policy_2\": policy_2},\n", " \"variables\": {\"var_1\": suf_1, \"var_2\": suf_2},\n", " }\n", "]\n", "\n", "initial_state = {\"var_1\": 0, \"var_2\": 1}\n", "\n", "params = {\"param_1\": 0, \"param_2\": 1}" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "import sys\n", "sys.path.append('..')" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": [ "\n", "\n", "\n", "\n", "\n", "\n", "cluster_timestep\n", "\n", "\n", "cluster_psub_0\n", "\n", "Partial State Update Block\n", "\n", "\n", "cluster_variables_0\n", "\n", "State\n", "\n", "\n", "cluster_policy_0\n", "\n", "Policies\n", "\n", "\n", "cluster_suf_0\n", "\n", "State Update Functions\n", "\n", "\n", "\n", "state_0\n", "\n", "\n", "State 1\n", "\n", "\n", "\n", "policy_policy_1_0\n", "\n", "policy_1 (policy_1)\n", "\n", "\n", "\n", "state_0->policy_policy_1_0\n", "\n", "\n", "\n", "\n", "\n", "policy_policy_2_0\n", "\n", "policy_2 (policy_2)\n", "\n", "\n", "\n", "state_0->policy_policy_2_0\n", "\n", "\n", "\n", "\n", "\n", "variable_var_2_0\n", "\n", "\n", "var_2 (int)\n", "\n", "\n", "\n", "variable_var_2_0->policy_policy_2_0\n", "\n", "\n", "\n", "\n", "\n", "variable_var_1_0\n", "\n", "\n", "var_1 (int)\n", "\n", "\n", "\n", "variable_var_1_0->policy_policy_1_0\n", "\n", "\n", "\n", "\n", "\n", "variable_var_1_0->policy_policy_2_0\n", "\n", "\n", "\n", "\n", "\n", "agg_0\n", "\n", "Aggregation\n", "\n", "\n", "\n", "suf_var_1_0\n", "\n", "var_1 (suf_1)\n", "\n", "\n", "\n", "agg_0->suf_var_1_0\n", "\n", "\n", "\n", "\n", "\n", "suf_var_2_0\n", "\n", "var_2 (suf_2)\n", "\n", "\n", "\n", "agg_0->suf_var_2_0\n", "\n", "\n", "\n", "\n", "\n", "policy_policy_1_0->agg_0\n", "\n", "\n", "\n", "\n", "\n", "policy_policy_2_0->agg_0\n", "\n", "\n", "\n", "\n", "\n", "state_1\n", "\n", "state_1\n", "\n", "\n", "\n", "suf_var_1_0->state_1\n", "\n", "\n", "\n", "\n", "\n", "suf_var_2_0->state_1\n", "\n", "\n", "\n", "\n", "\n" ], "text/plain": [ "" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from cadCAD_diagram.config_diagram import diagram\n", "\n", "diagram(initial_state, params, psubs)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.6" } }, "nbformat": 4, "nbformat_minor": 4 } ================================================ FILE: documentation/examples/cadCAD_tools_example.ipynb ================================================ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ " # cadCAD Easy Run for the Minimal Prey & Predator model" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/opt/homebrew/Caskroom/miniconda/base/lib/python3.11/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", " from .autonotebook import tqdm as notebook_tqdm\n" ] } ], "source": [ "import plotly.express as px\n", "import numpy as np\n", "import sys\n", "import seaborn as sns\n", "from tqdm.auto import tqdm\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " ## Minimal Prey and Predator Model" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "TIMESTEPS = 100\n", "SAMPLES = 10\n", "\n", "initial_conditions = {\n", " 'prey_population': 100,\n", " 'predator_population': 15\n", "}\n", "\n", "params = {\n", " \"prey_birth_rate\": [1.0],\n", " \"predator_birth_rate\": [0.01],\n", " \"predator_death_const\": [1.0],\n", " \"prey_death_const\": [0.03],\n", " # Precision of the simulation. Lower is more accurate / slower\n", " \"dt\": [0.01, 0.1, 0.05]\n", "}\n", "\n", "\n", "def p_predator_births(params, step, sL, s):\n", " dt = params['dt']\n", " predator_population = s['predator_population']\n", " prey_population = s['prey_population']\n", " birth_fraction = params['predator_birth_rate'] + \\\n", " np.random.random() * 0.0002\n", " births = birth_fraction * prey_population * predator_population * dt\n", " return {'add_to_predator_population': births}\n", "\n", "\n", "def p_prey_births(params, step, sL, s):\n", " dt = params['dt']\n", " population = s['prey_population']\n", " birth_fraction = params['prey_birth_rate'] + np.random.random() * 0.1\n", " births = birth_fraction * population * dt\n", " return {'add_to_prey_population': births}\n", "\n", "\n", "def p_predator_deaths(params, step, sL, s):\n", " dt = params['dt']\n", " population = s['predator_population']\n", " death_rate = params['predator_death_const'] + np.random.random() * 0.005\n", " deaths = death_rate * population * dt\n", " return {'add_to_predator_population': -1.0 * deaths}\n", "\n", "\n", "def p_prey_deaths(params, step, sL, s):\n", " dt = params['dt']\n", " death_rate = params['prey_death_const'] + np.random.random() * 0.1\n", " prey_population = s['prey_population']\n", " predator_population = s['predator_population']\n", " deaths = death_rate * prey_population * predator_population * dt\n", " return {'add_to_prey_population': -1.0 * deaths}\n", "\n", "\n", "def s_prey_population(params, step, sL, s, _input):\n", " y = 'prey_population'\n", " x = s['prey_population'] + _input['add_to_prey_population']\n", " return (y, x)\n", "\n", "\n", "def s_predator_population(params, step, sL, s, _input):\n", " y = 'predator_population'\n", " x = s['predator_population'] + _input['add_to_predator_population']\n", " return (y, x)\n", "\n", "\n", "partial_state_update_blocks = [\n", " {\n", " 'label': 'Lotka-Volterra Equations',\n", " 'policies': {\n", " 'predator_births': p_predator_births,\n", " 'prey_births': p_prey_births,\n", " 'predator_deaths': p_predator_deaths,\n", " 'prey_deaths': p_prey_deaths,\n", " },\n", " 'variables': {\n", " 'prey_population': s_prey_population,\n", " 'predator_population': s_predator_population\n", " }\n", " },\n", " {\n", " 'label': 'Do Nothing',\n", " 'policies': {\n", " \n", " },\n", " 'variables': {\n", " \n", " }\n", " }\n", "]\n" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "import sys\n", "sys.path.append(\"../..\")" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", " ___________ ____\n", " ________ __ ___/ / ____/ | / __ \\\n", " / ___/ __` / __ / / / /| | / / / /\n", "/ /__/ /_/ / /_/ / /___/ ___ |/ /_/ /\n", "\\___/\\__,_/\\__,_/\\____/_/ |_/_____/\n", "by cadCAD\n", "\n", "cadCAD Version: 0.4.28\n", "Execution Mode: local_proc\n", "Simulation Dimensions:\n", "Entire Simulation: (Models, Unique Timesteps, Params, Total Runs, Sub-States) = (1, 100, 5, 30, 2)\n", " Simulation 0: (Timesteps, Params, Runs, Sub-States) = (100, 5, 30, 2)\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "Initializing configurations: 100%|██████████| 30/30 [00:00<00:00, 669.03it/s]" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Execution Method: parallelize_simulations\n", "Execution Mode: parallelized\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\n", "Flattening results: 100%|██████████| 30/30 [00:00<00:00, 324.56it/s]" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Total execution time: 0.86s\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\n" ] } ], "source": [ "from cadCAD.tools import easy_run\n", "\n", "df = easy_run(initial_conditions,\n", " params,\n", " partial_state_update_blocks,\n", " TIMESTEPS,\n", " SAMPLES,\n", " assign_params=True,\n", " drop_substeps=False)" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "application/vnd.plotly.v1+json": { "config": { "plotlyServerURL": "https://plot.ly" }, "data": [ { "hovertemplate": "color=1
x=%{x}
y=%{y}", "legendgroup": "1", "line": { "color": "#636efa", "dash": "solid" }, "marker": { "symbol": "circle" }, "mode": "lines", "name": "1", "showlegend": true, "type": "scattergl", "x": [ 100, 99.29993160631898, 99.29993160631898, 99.38148169571427, 99.38148169571427, 99.33344287701127, 99.33344287701127, 99.78052429956195, 99.78052429956195, 99.54958970085868, 99.54958970085868, 99.5415288602601, 99.5415288602601, 99.20043010937233, 99.20043010937233, 98.38175972088112, 98.38175972088112, 98.08171337358606, 98.08171337358606, 98.3146135545321, 98.3146135545321, 98.15163483592876, 98.15163483592876, 98.2617316271704, 98.2617316271704, 98.4307104729456, 98.4307104729456, 98.78953357215462, 98.78953357215462, 98.79985727776051, 98.79985727776051, 99.23692266333096, 99.23692266333096, 98.39279376646044, 98.39279376646044, 98.38874784974972, 98.38874784974972, 98.47174801810372, 98.47174801810372, 98.2916973612909, 98.2916973612909, 98.77808827688989, 98.77808827688989, 98.74409721517681, 98.74409721517681, 99.24190042277999, 99.24190042277999, 98.84599456847697, 98.84599456847697, 99.09135177709153, 99.09135177709153, 99.10434894166539, 99.10434894166539, 99.57328874254877, 99.57328874254877, 99.21501237298247, 99.21501237298247, 99.25020700392601, 99.25020700392601, 99.63288351336783, 99.63288351336783, 99.40473856709445, 99.40473856709445, 98.7710291940686, 98.7710291940686, 98.5407493936721, 98.5407493936721, 97.7508566239193, 97.7508566239193, 97.71072647387824, 97.71072647387824, 97.06612114764668, 97.06612114764668, 96.60023270185529, 96.60023270185529, 96.97950519720334, 96.97950519720334, 97.13875284807816, 97.13875284807816, 97.28197178315625, 97.28197178315625, 96.58033571299049, 96.58033571299049, 96.25643172904921, 96.25643172904921, 96.6261400000404, 96.6261400000404, 96.52079469759674, 96.52079469759674, 96.14265950886788, 96.14265950886788, 96.29506225210642, 96.29506225210642, 95.82910831575578, 95.82910831575578, 96.35112441973347, 96.35112441973347, 96.16329269178928, 96.16329269178928, 95.87027246972195, 95.87027246972195, 95.7307727305111, 95.7307727305111, 95.52782525481386, 95.52782525481386, 95.3266966060663, 95.3266966060663, 94.73244989096955, 94.73244989096955, 94.85863986535756, 94.85863986535756, 94.5348526851931, 94.5348526851931, 94.27697635190073, 94.27697635190073, 93.47026915554588, 93.47026915554588, 93.23682795968988, 93.23682795968988, 93.37231139151324, 93.37231139151324, 93.15534439539415, 93.15534439539415, 93.24217287585641, 93.24217287585641, 93.78860723896459, 93.78860723896459, 93.77560714675685, 93.77560714675685, 93.0999726791823, 93.0999726791823, 92.90606801326578, 92.90606801326578, 93.2831221906634, 93.2831221906634, 93.01583352672039, 93.01583352672039, 92.70359835023112, 92.70359835023112, 92.00530036542673, 92.00530036542673, 92.42100834060409, 92.42100834060409, 92.7895835919253, 92.7895835919253, 92.73717490018763, 92.73717490018763, 92.76883196952322, 92.76883196952322, 93.08317487684629, 93.08317487684629, 92.33451766496589, 92.33451766496589, 92.13498897315472, 92.13498897315472, 92.09928886790658, 92.09928886790658, 92.22680948420437, 92.22680948420437, 91.62546599412939, 91.62546599412939, 91.12033628158707, 91.12033628158707, 90.91703470428618, 90.91703470428618, 90.51203613658468, 90.51203613658468, 90.76461607129751, 90.76461607129751, 91.12216656725413, 91.12216656725413, 91.25249379875453, 91.25249379875453, 91.58012004487541, 91.58012004487541, 91.06486472813755, 91.06486472813755, 91.18797649222013, 91.18797649222013, 90.69671638734081, 90.69671638734081, 91.26790712942591, 91.26790712942591, 90.79702047570592, 90.79702047570592, 90.23186056687439, 90.23186056687439, 89.67634735880623, 89.67634735880623, 90.06987166421722, 90.06987166421722, 89.65940405481305, 89.65940405481305, 89.14786912937605, 89.14786912937605, 88.68086196244481, 88.68086196244481, 88.08424380115036, 88.08424380115036, 87.92914636627808, 87.92914636627808, 100, 92.99931606318984, 92.99931606318984, 93.74968330870446, 93.74968330870446, 93.35200242595599, 93.35200242595599, 97.61217815984494, 97.61217815984494, 95.54997817570786, 95.54997817570786, 95.635092884268, 95.635092884268, 92.61880754039443, 92.61880754039443, 85.39231796273906, 85.39231796273906, 83.12912862094319, 83.12912862094319, 85.40561642328275, 85.40561642328275, 84.62039860344953, 84.62039860344953, 86.16474388636449, 86.16474388636449, 88.32785188924211, 88.32785188924211, 92.10765900299248, 92.10765900299248, 93.26077770768009, 93.26077770768009, 97.9845294627281, 97.9845294627281, 91.85128228934461, 91.85128228934461, 92.94825282196534, 92.94825282196534, 94.908060967487, 94.908060967487, 94.71326538271349, 94.71326538271349, 100.13862169564187, 100.13862169564187, 101.27435286478284, 101.27435286478284, 107.18723419784558, 107.18723419784558, 105.11150551338793, 105.11150551338793, 108.89332418604562, 108.89332418604562, 110.45800926706632, 110.45800926706632, 116.48523146511381, 116.48523146511381, 114.1292438507272, 114.1292438507272, 115.6710564645791, 115.6710564645791, 120.72623435030194, 120.72623435030194, 118.93046533906094, 118.93046533906094, 112.25835075871757, 112.25835075871757, 110.00527663324144, 110.00527663324144, 101.43663074912372, 101.43663074912372, 101.02867217786005, 101.02867217786005, 94.33053060847377, 94.33053060847377, 89.75476827975842, 89.75476827975842, 93.29245542951959, 93.29245542951959, 94.9186805787271, 94.9186805787271, 96.46551527277536, 96.46551527277536, 89.87389035969865, 89.87389035969865, 87.16376777592785, 87.16376777592785, 90.71447055509934, 90.71447055509934, 90.19536558085994, 90.19536558085994, 87.37997504032674, 87.37997504032674, 89.23463194487961, 89.23463194487961, 85.88495474723042, 85.88495474723042, 90.91229934650016, 90.91229934650016, 90.15196996137051, 90.15196996137051, 88.67602042222708, 88.67602042222708, 88.50743002514825, 88.50743002514825, 87.96325417167918, 87.96325417167918, 87.47813607760847, 87.47813607760847, 84.01053269460503, 84.01053269460503, 86.21927941269837, 86.21927941269837, 85.20026287932083, 85.20026287932083, 84.74514940369397, 84.74514940369397, 80.44680552355874, 80.44680552355874, 80.41520185078912, 80.41520185078912, 83.13776682112793, 83.13776682112793, 83.62311825579216, 83.62311825579216, 86.27091768763398, 86.27091768763398, 92.29068344923925, 92.29068344923925, 94.59113655600862, 94.59113655600862, 92.23253576603186, 92.23253576603186, 93.36203549432568, 93.36203549432568, 98.80311561440442, 98.80311561440442, 99.52383859763862, 99.52383859763862, 100.02610961464065, 100.02610961464065, 97.48148429129367, 97.48148429129367, 103.34545533154333, 103.34545533154333, 109.43020057074936, 109.43020057074936, 112.12304973808557, 112.12304973808557, 115.52003033279902, 115.52003033279902, 121.55801868602819, 121.55801868602819, 117.08958909341867, 117.08958909341867, 117.75922193520242, 117.75922193520242, 119.85458925018938, 119.85458925018938, 123.66274001251523, 123.66274001251523, 119.15604184133105, 119.15604184133105, 115.53291901293304, 115.53291901293304, 114.89363074478746, 114.89363074478746, 111.82198288405428, 111.82198288405428, 115.87910014654939, 115.87910014654939, 121.11836567425608, 121.11836567425608, 123.6936575690804, 123.6936575690804, 128.58085298226052, 128.58085298226052, 121.95792293344105, 121.95792293344105, 123.60374048079915, 123.60374048079915, 116.48935752258258, 116.48935752258258, 123.55808091733965, 123.55808091733965, 115.82597098962636, 115.82597098962636, 106.77349871746914, 106.77349871746914, 98.16867422379417, 98.16867422379417, 101.74594768140646, 101.74594768140646, 95.1243047124417, 95.1243047124417, 87.65512294066052, 87.65512294066052, 81.34224880318148, 81.34224880318148, 74.25512295493493, 74.25512295493493, 72.08158085400078, 72.08158085400078, 100, 96.49965803159492, 96.49965803159492, 96.89282234085528, 96.89282234085528, 96.66395700156504, 96.66395700156504, 98.84511851049147, 98.84511851049147, 97.72022468264952, 97.72022468264952, 97.69539195252099, 97.69539195252099, 96.04474200505408, 96.04474200505408, 92.12122707795169, 92.12122707795169, 90.7524578823741, 90.7524578823741, 91.86620599866295, 91.86620599866295, 91.18321550679761, 91.18321550679761, 91.77076300242805, 91.77076300242805, 92.64886983215455, 92.64886983215455, 94.4115531951917, 94.4115531951917, 94.60105803410664, 94.60105803410664, 96.77426923210655, 96.77426923210655, 92.95584004241334, 92.95584004241334, 93.0988602155345, 93.0988602155345, 93.66372732853505, 93.66372732853505, 93.03719912084956, 93.03719912084956, 95.452716939988, 95.452716939988, 95.51738150606599, 95.51738150606599, 98.05425788440175, 98.05425788440175, 96.45618107548292, 96.45618107548292, 97.85694974565604, 97.85694974565604, 98.17927424291095, 98.17927424291095, 100.65800191623217, 100.65800191623217, 99.23013457226213, 99.23013457226213, 99.68075990493776, 99.68075990493776, 101.76892968159176, 101.76892968159176, 100.93152794995164, 100.93152794995164, 98.15507445203599, 98.15507445203599, 97.32448920917646, 97.32448920917646, 93.8712393709979, 93.8712393709979, 93.94055110646606, 93.94055110646606, 91.25561322951836, 91.25561322951836, 89.45152914637421, 89.45152914637421, 91.38648456820863, 91.38648456820863, 92.40702828733023, 92.40702828733023, 93.37466906480901, 93.37466906480901, 90.60421743023397, 90.60421743023397, 89.54727537765943, 89.54727537765943, 91.50562818437629, 91.50562818437629, 91.43629555560625, 91.43629555560625, 90.22387819072098, 90.22387819072098, 91.286734506583, 91.286734506583, 89.70792037849891, 89.70792037849891, 92.36523442648821, 92.36523442648821, 92.01299752297405, 92.01299752297405, 91.26989588133198, 91.26989588133198, 91.16338302394053, 91.16338302394053, 90.8266416539283, 90.8266416539283, 90.48973346931841, 90.48973346931841, 88.53135087902336, 88.53135087902336, 89.58435442398849, 89.58435442398849, 88.8253866031861, 88.8253866031861, 88.3389425664917, 88.3389425664917, 85.6690510129246, 85.6690510129246, 85.33734615018504, 85.33734615018504, 86.51603920143914, 86.51603920143914, 86.33828493348129, 86.33828493348129, 87.36304955582791, 87.36304955582791, 90.23284652388249, 90.23284652388249, 90.91718361444943, 90.91718361444943, 88.99242906220593, 88.99242906220593, 88.99938883525597, 88.99938883525597, 91.30743180141197, 91.30743180141197, 91.05295854841216, 91.05295854841216, 90.67174729743687, 90.67174729743687, 88.7604154487307, 88.7604154487307, 91.21667934978741, 91.21667934978741, 93.6338256538187, 93.6338256538187, 94.37558676757705, 94.37558676757705, 95.47321941160612, 95.47321941160612, 97.77075917390104, 97.77075917390104, 95.59282238220855, 95.59282238220855, 95.72059903293992, 95.72059903293992, 96.52854695498216, 96.52854695498216, 98.09563460829936, 98.09563460829936, 96.51532722863074, 96.51532722863074, 95.4085247939158, 95.4085247939158, 95.52465821995634, 95.52465821995634, 94.8087017899729, 94.8087017899729, 96.88999312951138, 96.88999312951138, 99.41181607140739, 99.41181607140739, 101.0349689701463, 101.0349689701463, 103.52291722549926, 103.52291722549926, 102.29402709966891, 102.29402709966891, 103.89599855840412, 103.89599855840412, 102.66305598951656, 102.66305598951656, 106.35128198458621, 106.35128198458621, 105.2153347445648, 105.2153347445648, 103.54761969318548, 103.54761969318548, 101.9104419064554, 101.9104419064554, 104.68762728033715, 104.68762728033715, 103.74561762296544, 103.74561762296544, 102.29177188240789, 102.29177188240789, 100.99065500957371, 100.99065500957371, 99.08829773238939, 99.08829773238939, 99.25050915772879, 99.25050915772879 ], "xaxis": "x", "y": [ 15, 15.0025881631884, 15.0025881631884, 15.001496702185737, 15.001496702185737, 15.002361804039465, 15.002361804039465, 15.003883708196188, 15.003883708196188, 15.00568393679195, 15.00568393679195, 15.007415489103332, 15.007415489103332, 15.007679903819312, 15.007679903819312, 15.00785846437848, 15.00785846437848, 15.005149988731267, 15.005149988731267, 15.003693218370183, 15.003693218370183, 15.003201208353792, 15.003201208353792, 15.001441720795848, 15.001441720795848, 15.000133583406503, 15.000133583406503, 14.998369352308925, 14.998369352308925, 14.996174666815067, 14.996174666815067, 14.994789169151316, 14.994789169151316, 14.99321394632609, 14.99321394632609, 14.990466967358335, 14.990466967358335, 14.98892812664762, 14.98892812664762, 14.987709914471244, 14.987709914471244, 14.987290241379329, 14.987290241379329, 14.985547623238297, 14.985547623238297, 14.986392330287694, 14.986392330287694, 14.9857180023299, 14.9857180023299, 14.984461841594834, 14.984461841594834, 14.985073680988108, 14.985073680988108, 14.985562867120061, 14.985562867120061, 14.98541282187458, 14.98541282187458, 14.984719710317288, 14.984719710317288, 14.985916999281203, 14.985916999281203, 14.98625696832826, 14.98625696832826, 14.986605681348385, 14.986605681348385, 14.985955421994834, 14.985955421994834, 14.986129886338091, 14.986129886338091, 14.984477177626776, 14.984477177626776, 14.981225059271852, 14.981225059271852, 14.976432391666856, 14.976432391666856, 14.973674166171941, 14.973674166171941, 14.96980019046312, 14.96980019046312, 14.966768040636888, 14.966768040636888, 14.962334392385861, 14.962334392385861, 14.957429395595303, 14.957429395595303, 14.953568887352041, 14.953568887352041, 14.948548302693771, 14.948548302693771, 14.945167884771239, 14.945167884771239, 14.940572465174537, 14.940572465174537, 14.936861141832518, 14.936861141832518, 14.931906107640428, 14.931906107640428, 14.927219898398723, 14.927219898398723, 14.921427580941707, 14.921427580941707, 14.91592475619714, 14.91592475619714, 14.910827079437475, 14.910827079437475, 14.90399212146379, 14.90399212146379, 14.897887136036417, 14.897887136036417, 14.891130476962763, 14.891130476962763, 14.883405497521546, 14.883405497521546, 14.876434503668987, 14.876434503668987, 14.870076791929769, 14.870076791929769, 14.862470074033991, 14.862470074033991, 14.853101924486802, 14.853101924486802, 14.845417890954725, 14.845417890954725, 14.834854591138358, 14.834854591138358, 14.82487867160691, 14.82487867160691, 14.817333893722857, 14.817333893722857, 14.80795542406726, 14.80795542406726, 14.799736508431591, 14.799736508431591, 14.789248058469765, 14.789248058469765, 14.7801175136321, 14.7801175136321, 14.77151478230201, 14.77151478230201, 14.762483431482917, 14.762483431482917, 14.75140910811959, 14.75140910811959, 14.742427769315322, 14.742427769315322, 14.731695495637132, 14.731695495637132, 14.723316727651351, 14.723316727651351, 14.714085420344661, 14.714085420344661, 14.705044067153839, 14.705044067153839, 14.695511757105502, 14.695511757105502, 14.684106161453188, 14.684106161453188, 14.673362900138697, 14.673362900138697, 14.662126777303884, 14.662126777303884, 14.650294122378542, 14.650294122378542, 14.637133503588467, 14.637133503588467, 14.625885500549552, 14.625885500549552, 14.613041318879013, 14.613041318879013, 14.600491228516, 14.600491228516, 14.589826301169238, 14.589826301169238, 14.579097284458562, 14.579097284458562, 14.567445029812177, 14.567445029812177, 14.555065538321779, 14.555065538321779, 14.543083171721651, 14.543083171721651, 14.530543871653219, 14.530543871653219, 14.519732090172331, 14.519732090172331, 14.50728664083606, 14.50728664083606, 14.494761059082773, 14.494761059082773, 14.480759862525757, 14.480759862525757, 14.466954078017151, 14.466954078017151, 14.452655312592428, 14.452655312592428, 14.43861439698937, 14.43861439698937, 14.421950182244203, 14.421950182244203, 14.404714317939641, 14.404714317939641, 15, 15.025881631884008, 15.025881631884008, 14.919856780977506, 14.919856780977506, 14.84340539956636, 14.84340539956636, 14.768172517785956, 14.768172517785956, 14.753355341717914, 14.753355341717914, 14.710325587285196, 14.710325587285196, 14.65501286735965, 14.65501286735965, 14.558960244492898, 14.558960244492898, 14.343261540533113, 14.343261540533113, 14.112473629068363, 14.112473629068363, 13.923048492146386, 13.923048492146386, 13.716505105851384, 13.716505105851384, 13.536396160701718, 13.536396160701718, 13.382627368919778, 13.382627368919778, 13.273403497288376, 13.273403497288376, 13.18737339314849, 13.18737339314849, 13.15696932845709, 13.15696932845709, 13.046690159522171, 13.046690159522171, 12.961691639243096, 12.961691639243096, 12.904545878763365, 12.904545878763365, 12.853989386327374, 12.853989386327374, 12.856562555701977, 12.856562555701977, 12.89695026210208, 12.89695026210208, 12.99401382064389, 12.99401382064389, 13.064986472742175, 13.064986472742175, 13.200100005296521, 13.200100005296521, 13.356245186734787, 13.356245186734787, 13.581858258648817, 13.581858258648817, 13.779446331861786, 13.779446331861786, 14.020887197803892, 14.020887197803892, 14.322226633251981, 14.322226633251981, 14.607966995872808, 14.607966995872808, 14.80045909939326, 14.80045909939326, 14.974742020331096, 14.974742020331096, 15.014139514654353, 15.014139514654353, 15.031590488973418, 15.031590488973418, 14.942284460374912, 14.942284460374912, 14.810526845162071, 14.810526845162071, 14.71725604402707, 14.71725604402707, 14.654423668399897, 14.654423668399897, 14.59904128346401, 14.59904128346401, 14.452865602940358, 14.452865602940358, 14.282261478879674, 14.282261478879674, 14.149772009038367, 14.149772009038367, 14.027052069983485, 14.027052069983485, 13.859992607077059, 13.859992607077059, 13.726038665079807, 13.726038665079807, 13.542762810472052, 13.542762810472052, 13.426206655218582, 13.426206655218582, 13.293233924236567, 13.293233924236567, 13.147791616712704, 13.147791616712704, 13.006610763951292, 13.006610763951292, 12.84823986731333, 12.84823986731333, 12.693804885133208, 12.693804885133208, 12.498890192871052, 12.498890192871052, 12.325809989121367, 12.325809989121367, 12.151607078337484, 12.151607078337484, 11.98176127509246, 11.98176127509246, 11.761719359770526, 11.761719359770526, 11.535738338854555, 11.535738338854555, 11.356031924588308, 11.356031924588308, 11.166858150706151, 11.166858150706151, 11.013537609868145, 11.013537609868145, 10.940785833361874, 10.940785833361874, 10.880470893076224, 10.880470893076224, 10.810492031684296, 10.810492031684296, 10.738828174758915, 10.738828174758915, 10.732227365833888, 10.732227365833888, 10.74063259552893, 10.74063259552893, 10.754970118090359, 10.754970118090359, 10.733785904628672, 10.733785904628672, 10.787976887758164, 10.787976887758164, 10.88944458640169, 10.88944458640169, 11.04254907916619, 11.04254907916619, 11.228202407568958, 11.228202407568958, 11.482818264639777, 11.482818264639777, 11.69687181566044, 11.69687181566044, 11.906283961960796, 11.906283961960796, 12.151929632994989, 12.151929632994989, 12.442078661195602, 12.442078661195602, 12.685614756768384, 12.685614756768384, 12.882246373678006, 12.882246373678006, 13.098033807459965, 13.098033807459965, 13.265644619378074, 13.265644619378074, 13.488205244369283, 13.488205244369283, 13.801786381602861, 13.801786381602861, 14.15661507092392, 14.15661507092392, 14.571319896228996, 14.571319896228996, 14.900498464260913, 14.900498464260913, 15.264447207321453, 15.264447207321453, 15.531123380217505, 15.531123380217505, 15.924513627073946, 15.924513627073946, 16.19019922374802, 16.19019922374802, 16.322098263657374, 16.322098263657374, 16.304174332335062, 16.304174332335062, 16.340241196629936, 16.340241196629936, 16.268904220202955, 16.268904220202955, 16.086253203878236, 16.086253203878236, 15.782468169262778, 15.782468169262778, 15.374958294571538, 15.374958294571538, 15, 15.012940815942004, 15.012940815942004, 14.98636610132836, 14.98636610132836, 14.971810745493599, 14.971810745493599, 14.959082346076983, 14.959082346076983, 14.960947875173133, 14.960947875173133, 14.95565263271521, 14.95565263271521, 14.943059453110807, 14.943059453110807, 14.920042423099233, 14.920042423099233, 14.859798697725925, 14.859798697725925, 14.797521921922066, 14.797521921922066, 14.746699458020705, 14.746699458020705, 14.686175690662845, 14.686175690662845, 14.631471102128723, 14.631471102128723, 14.58023065366825, 14.58023065366825, 14.537568554812667, 14.537568554812667, 14.500231317119468, 14.500231317119468, 14.474722857563513, 14.474722857563513, 14.4220647350196, 14.4220647350196, 14.376180825464203, 14.376180825464203, 14.335464151009303, 14.335464151009303, 14.295170307805137, 14.295170307805137, 14.263049608683579, 14.263049608683579, 14.243626386186193, 14.243626386186193, 14.231930990766053, 14.231930990766053, 14.208866161776603, 14.208866161776603, 14.202879759057403, 14.202879759057403, 14.198542451693676, 14.198542451693676, 14.205568788947831, 14.205568788947831, 14.202391682296767, 14.202391682296767, 14.211179246898407, 14.211179246898407, 14.22809282401728, 14.22809282401728, 14.240716868942075, 14.240716868942075, 14.233201323513999, 14.233201323513999, 14.225227297004473, 14.225227297004473, 14.189429886330164, 14.189429886330164, 14.147165369806896, 14.147165369806896, 14.08333714510193, 14.08333714510193, 14.019069291306938, 14.019069291306938, 13.961481416227368, 13.961481416227368, 13.913958049210835, 13.913958049210835, 13.866151471260338, 13.866151471260338, 13.801817295121142, 13.801817295121142, 13.737042236766802, 13.737042236766802, 13.678767238942457, 13.678767238942457, 13.628052525015123, 13.628052525015123, 13.56643704645608, 13.56643704645608, 13.515035696227566, 13.515035696227566, 13.450876501139497, 13.450876501139497, 13.402818129238593, 13.402818129238593, 13.348944553667687, 13.348944553667687, 13.293373264063145, 13.293373264063145, 13.239891656584982, 13.239891656584982, 13.178310915340727, 13.178310915340727, 13.11914363309317, 13.11914363309317, 13.04834605494057, 13.04834605494057, 12.980008418510142, 12.980008418510142, 12.912100563936535, 12.912100563936535, 12.84548257168026, 12.84548257168026, 12.761653328708682, 12.761653328708682, 12.670680742782599, 12.670680742782599, 12.593746048181327, 12.593746048181327, 12.505966192387636, 12.505966192387636, 12.426975415778585, 12.426975415778585, 12.372987114877688, 12.372987114877688, 12.316124888297376, 12.316124888297376, 12.25624784136798, 12.25624784136798, 12.188780748399955, 12.188780748399955, 12.139029429691613, 12.139029429691613, 12.091613175035052, 12.091613175035052, 12.042152685505714, 12.042152685505714, 11.977247905600317, 11.977247905600317, 11.933433733774168, 11.933433733774168, 11.89504783502318, 11.89504783502318, 11.871147080760428, 11.871147080760428, 11.850217659047976, 11.850217659047976, 11.84192192212905, 11.84192192212905, 11.82311969344896, 11.82311969344896, 11.798468322241224, 11.798468322241224, 11.781618541251447, 11.781618541251447, 11.771189982727265, 11.771189982727265, 11.752590059889691, 11.752590059889691, 11.725074162195554, 11.725074162195554, 11.707552281866988, 11.707552281866988, 11.681614136981478, 11.681614136981478, 11.667586378488018, 11.667586378488018, 11.674231291283325, 11.674231291283325, 11.689501880321215, 11.689501880321215, 11.71312985613572, 11.71312985613572, 11.729541695595978, 11.729541695595978, 11.756346252143663, 11.756346252143663, 11.776821825896544, 11.776821825896544, 11.823144360448932, 11.823144360448932, 11.858480184796978, 11.858480184796978, 11.887381186413212, 11.887381186413212, 11.903274853981108, 11.903274853981108, 11.934053284575308, 11.934053284575308, 11.959946529310686, 11.959946529310686, 11.981458643093886, 11.981458643093886, 11.986109221284174, 11.986109221284174, 11.98062484432249, 11.98062484432249 ], "yaxis": "y" }, { "hovertemplate": "color=2
x=%{x}
y=%{y}", "legendgroup": "2", "line": { "color": "#EF553B", "dash": "solid" }, "marker": { "symbol": "circle" }, "mode": "lines", "name": "2", "showlegend": true, "type": "scattergl", "x": [ 100, 99.29993160631898, 99.29993160631898, 99.38148169571427, 99.38148169571427, 99.33344287701127, 99.33344287701127, 99.78052429956195, 99.78052429956195, 99.54958970085868, 99.54958970085868, 99.5415288602601, 99.5415288602601, 99.20043010937233, 99.20043010937233, 98.38175972088112, 98.38175972088112, 98.08171337358606, 98.08171337358606, 98.3146135545321, 98.3146135545321, 98.15163483592876, 98.15163483592876, 98.2617316271704, 98.2617316271704, 98.4307104729456, 98.4307104729456, 98.78953357215462, 98.78953357215462, 98.79985727776051, 98.79985727776051, 99.23692266333096, 99.23692266333096, 98.39279376646044, 98.39279376646044, 98.38874784974972, 98.38874784974972, 98.47174801810372, 98.47174801810372, 98.2916973612909, 98.2916973612909, 98.77808827688989, 98.77808827688989, 98.74409721517681, 98.74409721517681, 99.24190042277999, 99.24190042277999, 98.84599456847697, 98.84599456847697, 99.09135177709153, 99.09135177709153, 99.10434894166539, 99.10434894166539, 99.57328874254877, 99.57328874254877, 99.21501237298247, 99.21501237298247, 99.25020700392601, 99.25020700392601, 99.63288351336783, 99.63288351336783, 99.40473856709445, 99.40473856709445, 98.7710291940686, 98.7710291940686, 98.5407493936721, 98.5407493936721, 97.7508566239193, 97.7508566239193, 97.71072647387824, 97.71072647387824, 97.06612114764668, 97.06612114764668, 96.60023270185529, 96.60023270185529, 96.97950519720334, 96.97950519720334, 97.13875284807816, 97.13875284807816, 97.28197178315625, 97.28197178315625, 96.58033571299049, 96.58033571299049, 96.25643172904921, 96.25643172904921, 96.6261400000404, 96.6261400000404, 96.52079469759674, 96.52079469759674, 96.14265950886788, 96.14265950886788, 96.29506225210642, 96.29506225210642, 95.82910831575578, 95.82910831575578, 96.35112441973347, 96.35112441973347, 96.16329269178928, 96.16329269178928, 95.87027246972195, 95.87027246972195, 95.7307727305111, 95.7307727305111, 95.52782525481386, 95.52782525481386, 95.3266966060663, 95.3266966060663, 94.73244989096955, 94.73244989096955, 94.85863986535756, 94.85863986535756, 94.5348526851931, 94.5348526851931, 94.27697635190073, 94.27697635190073, 93.47026915554588, 93.47026915554588, 93.23682795968988, 93.23682795968988, 93.37231139151324, 93.37231139151324, 93.15534439539415, 93.15534439539415, 93.24217287585641, 93.24217287585641, 93.78860723896459, 93.78860723896459, 93.77560714675685, 93.77560714675685, 93.0999726791823, 93.0999726791823, 92.90606801326578, 92.90606801326578, 93.2831221906634, 93.2831221906634, 93.01583352672039, 93.01583352672039, 92.70359835023112, 92.70359835023112, 92.00530036542673, 92.00530036542673, 92.42100834060409, 92.42100834060409, 92.7895835919253, 92.7895835919253, 92.73717490018763, 92.73717490018763, 92.76883196952322, 92.76883196952322, 93.08317487684629, 93.08317487684629, 92.33451766496589, 92.33451766496589, 92.13498897315472, 92.13498897315472, 92.09928886790658, 92.09928886790658, 92.22680948420437, 92.22680948420437, 91.62546599412939, 91.62546599412939, 91.12033628158707, 91.12033628158707, 90.91703470428618, 90.91703470428618, 90.51203613658468, 90.51203613658468, 90.76461607129751, 90.76461607129751, 91.12216656725413, 91.12216656725413, 91.25249379875453, 91.25249379875453, 91.58012004487541, 91.58012004487541, 91.06486472813755, 91.06486472813755, 91.18797649222013, 91.18797649222013, 90.69671638734081, 90.69671638734081, 91.26790712942591, 91.26790712942591, 90.79702047570592, 90.79702047570592, 90.23186056687439, 90.23186056687439, 89.67634735880623, 89.67634735880623, 90.06987166421722, 90.06987166421722, 89.65940405481305, 89.65940405481305, 89.14786912937605, 89.14786912937605, 88.68086196244481, 88.68086196244481, 88.08424380115036, 88.08424380115036, 87.92914636627808, 87.92914636627808, 100, 92.99931606318984, 92.99931606318984, 93.74968330870446, 93.74968330870446, 93.35200242595599, 93.35200242595599, 97.61217815984494, 97.61217815984494, 95.54997817570786, 95.54997817570786, 95.635092884268, 95.635092884268, 92.61880754039443, 92.61880754039443, 85.39231796273906, 85.39231796273906, 83.12912862094319, 83.12912862094319, 85.40561642328275, 85.40561642328275, 84.62039860344953, 84.62039860344953, 86.16474388636449, 86.16474388636449, 88.32785188924211, 88.32785188924211, 92.10765900299248, 92.10765900299248, 93.26077770768009, 93.26077770768009, 97.9845294627281, 97.9845294627281, 91.85128228934461, 91.85128228934461, 92.94825282196534, 92.94825282196534, 94.908060967487, 94.908060967487, 94.71326538271349, 94.71326538271349, 100.13862169564187, 100.13862169564187, 101.27435286478284, 101.27435286478284, 107.18723419784558, 107.18723419784558, 105.11150551338793, 105.11150551338793, 108.89332418604562, 108.89332418604562, 110.45800926706632, 110.45800926706632, 116.48523146511381, 116.48523146511381, 114.1292438507272, 114.1292438507272, 115.6710564645791, 115.6710564645791, 120.72623435030194, 120.72623435030194, 118.93046533906094, 118.93046533906094, 112.25835075871757, 112.25835075871757, 110.00527663324144, 110.00527663324144, 101.43663074912372, 101.43663074912372, 101.02867217786005, 101.02867217786005, 94.33053060847377, 94.33053060847377, 89.75476827975842, 89.75476827975842, 93.29245542951959, 93.29245542951959, 94.9186805787271, 94.9186805787271, 96.46551527277536, 96.46551527277536, 89.87389035969865, 89.87389035969865, 87.16376777592785, 87.16376777592785, 90.71447055509934, 90.71447055509934, 90.19536558085994, 90.19536558085994, 87.37997504032674, 87.37997504032674, 89.23463194487961, 89.23463194487961, 85.88495474723042, 85.88495474723042, 90.91229934650016, 90.91229934650016, 90.15196996137051, 90.15196996137051, 88.67602042222708, 88.67602042222708, 88.50743002514825, 88.50743002514825, 87.96325417167918, 87.96325417167918, 87.47813607760847, 87.47813607760847, 84.01053269460503, 84.01053269460503, 86.21927941269837, 86.21927941269837, 85.20026287932083, 85.20026287932083, 84.74514940369397, 84.74514940369397, 80.44680552355874, 80.44680552355874, 80.41520185078912, 80.41520185078912, 83.13776682112793, 83.13776682112793, 83.62311825579216, 83.62311825579216, 86.27091768763398, 86.27091768763398, 92.29068344923925, 92.29068344923925, 94.59113655600862, 94.59113655600862, 92.23253576603186, 92.23253576603186, 93.36203549432568, 93.36203549432568, 98.80311561440442, 98.80311561440442, 99.52383859763862, 99.52383859763862, 100.02610961464065, 100.02610961464065, 97.48148429129367, 97.48148429129367, 103.34545533154333, 103.34545533154333, 109.43020057074936, 109.43020057074936, 112.12304973808557, 112.12304973808557, 115.52003033279902, 115.52003033279902, 121.55801868602819, 121.55801868602819, 117.08958909341867, 117.08958909341867, 117.75922193520242, 117.75922193520242, 119.85458925018938, 119.85458925018938, 123.66274001251523, 123.66274001251523, 119.15604184133105, 119.15604184133105, 115.53291901293304, 115.53291901293304, 114.89363074478746, 114.89363074478746, 111.82198288405428, 111.82198288405428, 115.87910014654939, 115.87910014654939, 121.11836567425608, 121.11836567425608, 123.6936575690804, 123.6936575690804, 128.58085298226052, 128.58085298226052, 121.95792293344105, 121.95792293344105, 123.60374048079915, 123.60374048079915, 116.48935752258258, 116.48935752258258, 123.55808091733965, 123.55808091733965, 115.82597098962636, 115.82597098962636, 106.77349871746914, 106.77349871746914, 98.16867422379417, 98.16867422379417, 101.74594768140646, 101.74594768140646, 95.1243047124417, 95.1243047124417, 87.65512294066052, 87.65512294066052, 81.34224880318148, 81.34224880318148, 74.25512295493493, 74.25512295493493, 72.08158085400078, 72.08158085400078, 100, 96.49965803159492, 96.49965803159492, 96.89282234085528, 96.89282234085528, 96.66395700156504, 96.66395700156504, 98.84511851049147, 98.84511851049147, 97.72022468264952, 97.72022468264952, 97.69539195252099, 97.69539195252099, 96.04474200505408, 96.04474200505408, 92.12122707795169, 92.12122707795169, 90.7524578823741, 90.7524578823741, 91.86620599866295, 91.86620599866295, 91.18321550679761, 91.18321550679761, 91.77076300242805, 91.77076300242805, 92.64886983215455, 92.64886983215455, 94.4115531951917, 94.4115531951917, 94.60105803410664, 94.60105803410664, 96.77426923210655, 96.77426923210655, 92.95584004241334, 92.95584004241334, 93.0988602155345, 93.0988602155345, 93.66372732853505, 93.66372732853505, 93.03719912084956, 93.03719912084956, 95.452716939988, 95.452716939988, 95.51738150606599, 95.51738150606599, 98.05425788440175, 98.05425788440175, 96.45618107548292, 96.45618107548292, 97.85694974565604, 97.85694974565604, 98.17927424291095, 98.17927424291095, 100.65800191623217, 100.65800191623217, 99.23013457226213, 99.23013457226213, 99.68075990493776, 99.68075990493776, 101.76892968159176, 101.76892968159176, 100.93152794995164, 100.93152794995164, 98.15507445203599, 98.15507445203599, 97.32448920917646, 97.32448920917646, 93.8712393709979, 93.8712393709979, 93.94055110646606, 93.94055110646606, 91.25561322951836, 91.25561322951836, 89.45152914637421, 89.45152914637421, 91.38648456820863, 91.38648456820863, 92.40702828733023, 92.40702828733023, 93.37466906480901, 93.37466906480901, 90.60421743023397, 90.60421743023397, 89.54727537765943, 89.54727537765943, 91.50562818437629, 91.50562818437629, 91.43629555560625, 91.43629555560625, 90.22387819072098, 90.22387819072098, 91.286734506583, 91.286734506583, 89.70792037849891, 89.70792037849891, 92.36523442648821, 92.36523442648821, 92.01299752297405, 92.01299752297405, 91.26989588133198, 91.26989588133198, 91.16338302394053, 91.16338302394053, 90.8266416539283, 90.8266416539283, 90.48973346931841, 90.48973346931841, 88.53135087902336, 88.53135087902336, 89.58435442398849, 89.58435442398849, 88.8253866031861, 88.8253866031861, 88.3389425664917, 88.3389425664917, 85.6690510129246, 85.6690510129246, 85.33734615018504, 85.33734615018504, 86.51603920143914, 86.51603920143914, 86.33828493348129, 86.33828493348129, 87.36304955582791, 87.36304955582791, 90.23284652388249, 90.23284652388249, 90.91718361444943, 90.91718361444943, 88.99242906220593, 88.99242906220593, 88.99938883525597, 88.99938883525597, 91.30743180141197, 91.30743180141197, 91.05295854841216, 91.05295854841216, 90.67174729743687, 90.67174729743687, 88.7604154487307, 88.7604154487307, 91.21667934978741, 91.21667934978741, 93.6338256538187, 93.6338256538187, 94.37558676757705, 94.37558676757705, 95.47321941160612, 95.47321941160612, 97.77075917390104, 97.77075917390104, 95.59282238220855, 95.59282238220855, 95.72059903293992, 95.72059903293992, 96.52854695498216, 96.52854695498216, 98.09563460829936, 98.09563460829936, 96.51532722863074, 96.51532722863074, 95.4085247939158, 95.4085247939158, 95.52465821995634, 95.52465821995634, 94.8087017899729, 94.8087017899729, 96.88999312951138, 96.88999312951138, 99.41181607140739, 99.41181607140739, 101.0349689701463, 101.0349689701463, 103.52291722549926, 103.52291722549926, 102.29402709966891, 102.29402709966891, 103.89599855840412, 103.89599855840412, 102.66305598951656, 102.66305598951656, 106.35128198458621, 106.35128198458621, 105.2153347445648, 105.2153347445648, 103.54761969318548, 103.54761969318548, 101.9104419064554, 101.9104419064554, 104.68762728033715, 104.68762728033715, 103.74561762296544, 103.74561762296544, 102.29177188240789, 102.29177188240789, 100.99065500957371, 100.99065500957371, 99.08829773238939, 99.08829773238939, 99.25050915772879, 99.25050915772879 ], "xaxis": "x", "y": [ 15, 15.0025881631884, 15.0025881631884, 15.001496702185737, 15.001496702185737, 15.002361804039465, 15.002361804039465, 15.003883708196188, 15.003883708196188, 15.00568393679195, 15.00568393679195, 15.007415489103332, 15.007415489103332, 15.007679903819312, 15.007679903819312, 15.00785846437848, 15.00785846437848, 15.005149988731267, 15.005149988731267, 15.003693218370183, 15.003693218370183, 15.003201208353792, 15.003201208353792, 15.001441720795848, 15.001441720795848, 15.000133583406503, 15.000133583406503, 14.998369352308925, 14.998369352308925, 14.996174666815067, 14.996174666815067, 14.994789169151316, 14.994789169151316, 14.99321394632609, 14.99321394632609, 14.990466967358335, 14.990466967358335, 14.98892812664762, 14.98892812664762, 14.987709914471244, 14.987709914471244, 14.987290241379329, 14.987290241379329, 14.985547623238297, 14.985547623238297, 14.986392330287694, 14.986392330287694, 14.9857180023299, 14.9857180023299, 14.984461841594834, 14.984461841594834, 14.985073680988108, 14.985073680988108, 14.985562867120061, 14.985562867120061, 14.98541282187458, 14.98541282187458, 14.984719710317288, 14.984719710317288, 14.985916999281203, 14.985916999281203, 14.98625696832826, 14.98625696832826, 14.986605681348385, 14.986605681348385, 14.985955421994834, 14.985955421994834, 14.986129886338091, 14.986129886338091, 14.984477177626776, 14.984477177626776, 14.981225059271852, 14.981225059271852, 14.976432391666856, 14.976432391666856, 14.973674166171941, 14.973674166171941, 14.96980019046312, 14.96980019046312, 14.966768040636888, 14.966768040636888, 14.962334392385861, 14.962334392385861, 14.957429395595303, 14.957429395595303, 14.953568887352041, 14.953568887352041, 14.948548302693771, 14.948548302693771, 14.945167884771239, 14.945167884771239, 14.940572465174537, 14.940572465174537, 14.936861141832518, 14.936861141832518, 14.931906107640428, 14.931906107640428, 14.927219898398723, 14.927219898398723, 14.921427580941707, 14.921427580941707, 14.91592475619714, 14.91592475619714, 14.910827079437475, 14.910827079437475, 14.90399212146379, 14.90399212146379, 14.897887136036417, 14.897887136036417, 14.891130476962763, 14.891130476962763, 14.883405497521546, 14.883405497521546, 14.876434503668987, 14.876434503668987, 14.870076791929769, 14.870076791929769, 14.862470074033991, 14.862470074033991, 14.853101924486802, 14.853101924486802, 14.845417890954725, 14.845417890954725, 14.834854591138358, 14.834854591138358, 14.82487867160691, 14.82487867160691, 14.817333893722857, 14.817333893722857, 14.80795542406726, 14.80795542406726, 14.799736508431591, 14.799736508431591, 14.789248058469765, 14.789248058469765, 14.7801175136321, 14.7801175136321, 14.77151478230201, 14.77151478230201, 14.762483431482917, 14.762483431482917, 14.75140910811959, 14.75140910811959, 14.742427769315322, 14.742427769315322, 14.731695495637132, 14.731695495637132, 14.723316727651351, 14.723316727651351, 14.714085420344661, 14.714085420344661, 14.705044067153839, 14.705044067153839, 14.695511757105502, 14.695511757105502, 14.684106161453188, 14.684106161453188, 14.673362900138697, 14.673362900138697, 14.662126777303884, 14.662126777303884, 14.650294122378542, 14.650294122378542, 14.637133503588467, 14.637133503588467, 14.625885500549552, 14.625885500549552, 14.613041318879013, 14.613041318879013, 14.600491228516, 14.600491228516, 14.589826301169238, 14.589826301169238, 14.579097284458562, 14.579097284458562, 14.567445029812177, 14.567445029812177, 14.555065538321779, 14.555065538321779, 14.543083171721651, 14.543083171721651, 14.530543871653219, 14.530543871653219, 14.519732090172331, 14.519732090172331, 14.50728664083606, 14.50728664083606, 14.494761059082773, 14.494761059082773, 14.480759862525757, 14.480759862525757, 14.466954078017151, 14.466954078017151, 14.452655312592428, 14.452655312592428, 14.43861439698937, 14.43861439698937, 14.421950182244203, 14.421950182244203, 14.404714317939641, 14.404714317939641, 15, 15.025881631884008, 15.025881631884008, 14.919856780977506, 14.919856780977506, 14.84340539956636, 14.84340539956636, 14.768172517785956, 14.768172517785956, 14.753355341717914, 14.753355341717914, 14.710325587285196, 14.710325587285196, 14.65501286735965, 14.65501286735965, 14.558960244492898, 14.558960244492898, 14.343261540533113, 14.343261540533113, 14.112473629068363, 14.112473629068363, 13.923048492146386, 13.923048492146386, 13.716505105851384, 13.716505105851384, 13.536396160701718, 13.536396160701718, 13.382627368919778, 13.382627368919778, 13.273403497288376, 13.273403497288376, 13.18737339314849, 13.18737339314849, 13.15696932845709, 13.15696932845709, 13.046690159522171, 13.046690159522171, 12.961691639243096, 12.961691639243096, 12.904545878763365, 12.904545878763365, 12.853989386327374, 12.853989386327374, 12.856562555701977, 12.856562555701977, 12.89695026210208, 12.89695026210208, 12.99401382064389, 12.99401382064389, 13.064986472742175, 13.064986472742175, 13.200100005296521, 13.200100005296521, 13.356245186734787, 13.356245186734787, 13.581858258648817, 13.581858258648817, 13.779446331861786, 13.779446331861786, 14.020887197803892, 14.020887197803892, 14.322226633251981, 14.322226633251981, 14.607966995872808, 14.607966995872808, 14.80045909939326, 14.80045909939326, 14.974742020331096, 14.974742020331096, 15.014139514654353, 15.014139514654353, 15.031590488973418, 15.031590488973418, 14.942284460374912, 14.942284460374912, 14.810526845162071, 14.810526845162071, 14.71725604402707, 14.71725604402707, 14.654423668399897, 14.654423668399897, 14.59904128346401, 14.59904128346401, 14.452865602940358, 14.452865602940358, 14.282261478879674, 14.282261478879674, 14.149772009038367, 14.149772009038367, 14.027052069983485, 14.027052069983485, 13.859992607077059, 13.859992607077059, 13.726038665079807, 13.726038665079807, 13.542762810472052, 13.542762810472052, 13.426206655218582, 13.426206655218582, 13.293233924236567, 13.293233924236567, 13.147791616712704, 13.147791616712704, 13.006610763951292, 13.006610763951292, 12.84823986731333, 12.84823986731333, 12.693804885133208, 12.693804885133208, 12.498890192871052, 12.498890192871052, 12.325809989121367, 12.325809989121367, 12.151607078337484, 12.151607078337484, 11.98176127509246, 11.98176127509246, 11.761719359770526, 11.761719359770526, 11.535738338854555, 11.535738338854555, 11.356031924588308, 11.356031924588308, 11.166858150706151, 11.166858150706151, 11.013537609868145, 11.013537609868145, 10.940785833361874, 10.940785833361874, 10.880470893076224, 10.880470893076224, 10.810492031684296, 10.810492031684296, 10.738828174758915, 10.738828174758915, 10.732227365833888, 10.732227365833888, 10.74063259552893, 10.74063259552893, 10.754970118090359, 10.754970118090359, 10.733785904628672, 10.733785904628672, 10.787976887758164, 10.787976887758164, 10.88944458640169, 10.88944458640169, 11.04254907916619, 11.04254907916619, 11.228202407568958, 11.228202407568958, 11.482818264639777, 11.482818264639777, 11.69687181566044, 11.69687181566044, 11.906283961960796, 11.906283961960796, 12.151929632994989, 12.151929632994989, 12.442078661195602, 12.442078661195602, 12.685614756768384, 12.685614756768384, 12.882246373678006, 12.882246373678006, 13.098033807459965, 13.098033807459965, 13.265644619378074, 13.265644619378074, 13.488205244369283, 13.488205244369283, 13.801786381602861, 13.801786381602861, 14.15661507092392, 14.15661507092392, 14.571319896228996, 14.571319896228996, 14.900498464260913, 14.900498464260913, 15.264447207321453, 15.264447207321453, 15.531123380217505, 15.531123380217505, 15.924513627073946, 15.924513627073946, 16.19019922374802, 16.19019922374802, 16.322098263657374, 16.322098263657374, 16.304174332335062, 16.304174332335062, 16.340241196629936, 16.340241196629936, 16.268904220202955, 16.268904220202955, 16.086253203878236, 16.086253203878236, 15.782468169262778, 15.782468169262778, 15.374958294571538, 15.374958294571538, 15, 15.012940815942004, 15.012940815942004, 14.98636610132836, 14.98636610132836, 14.971810745493599, 14.971810745493599, 14.959082346076983, 14.959082346076983, 14.960947875173133, 14.960947875173133, 14.95565263271521, 14.95565263271521, 14.943059453110807, 14.943059453110807, 14.920042423099233, 14.920042423099233, 14.859798697725925, 14.859798697725925, 14.797521921922066, 14.797521921922066, 14.746699458020705, 14.746699458020705, 14.686175690662845, 14.686175690662845, 14.631471102128723, 14.631471102128723, 14.58023065366825, 14.58023065366825, 14.537568554812667, 14.537568554812667, 14.500231317119468, 14.500231317119468, 14.474722857563513, 14.474722857563513, 14.4220647350196, 14.4220647350196, 14.376180825464203, 14.376180825464203, 14.335464151009303, 14.335464151009303, 14.295170307805137, 14.295170307805137, 14.263049608683579, 14.263049608683579, 14.243626386186193, 14.243626386186193, 14.231930990766053, 14.231930990766053, 14.208866161776603, 14.208866161776603, 14.202879759057403, 14.202879759057403, 14.198542451693676, 14.198542451693676, 14.205568788947831, 14.205568788947831, 14.202391682296767, 14.202391682296767, 14.211179246898407, 14.211179246898407, 14.22809282401728, 14.22809282401728, 14.240716868942075, 14.240716868942075, 14.233201323513999, 14.233201323513999, 14.225227297004473, 14.225227297004473, 14.189429886330164, 14.189429886330164, 14.147165369806896, 14.147165369806896, 14.08333714510193, 14.08333714510193, 14.019069291306938, 14.019069291306938, 13.961481416227368, 13.961481416227368, 13.913958049210835, 13.913958049210835, 13.866151471260338, 13.866151471260338, 13.801817295121142, 13.801817295121142, 13.737042236766802, 13.737042236766802, 13.678767238942457, 13.678767238942457, 13.628052525015123, 13.628052525015123, 13.56643704645608, 13.56643704645608, 13.515035696227566, 13.515035696227566, 13.450876501139497, 13.450876501139497, 13.402818129238593, 13.402818129238593, 13.348944553667687, 13.348944553667687, 13.293373264063145, 13.293373264063145, 13.239891656584982, 13.239891656584982, 13.178310915340727, 13.178310915340727, 13.11914363309317, 13.11914363309317, 13.04834605494057, 13.04834605494057, 12.980008418510142, 12.980008418510142, 12.912100563936535, 12.912100563936535, 12.84548257168026, 12.84548257168026, 12.761653328708682, 12.761653328708682, 12.670680742782599, 12.670680742782599, 12.593746048181327, 12.593746048181327, 12.505966192387636, 12.505966192387636, 12.426975415778585, 12.426975415778585, 12.372987114877688, 12.372987114877688, 12.316124888297376, 12.316124888297376, 12.25624784136798, 12.25624784136798, 12.188780748399955, 12.188780748399955, 12.139029429691613, 12.139029429691613, 12.091613175035052, 12.091613175035052, 12.042152685505714, 12.042152685505714, 11.977247905600317, 11.977247905600317, 11.933433733774168, 11.933433733774168, 11.89504783502318, 11.89504783502318, 11.871147080760428, 11.871147080760428, 11.850217659047976, 11.850217659047976, 11.84192192212905, 11.84192192212905, 11.82311969344896, 11.82311969344896, 11.798468322241224, 11.798468322241224, 11.781618541251447, 11.781618541251447, 11.771189982727265, 11.771189982727265, 11.752590059889691, 11.752590059889691, 11.725074162195554, 11.725074162195554, 11.707552281866988, 11.707552281866988, 11.681614136981478, 11.681614136981478, 11.667586378488018, 11.667586378488018, 11.674231291283325, 11.674231291283325, 11.689501880321215, 11.689501880321215, 11.71312985613572, 11.71312985613572, 11.729541695595978, 11.729541695595978, 11.756346252143663, 11.756346252143663, 11.776821825896544, 11.776821825896544, 11.823144360448932, 11.823144360448932, 11.858480184796978, 11.858480184796978, 11.887381186413212, 11.887381186413212, 11.903274853981108, 11.903274853981108, 11.934053284575308, 11.934053284575308, 11.959946529310686, 11.959946529310686, 11.981458643093886, 11.981458643093886, 11.986109221284174, 11.986109221284174, 11.98062484432249, 11.98062484432249 ], "yaxis": "y" }, { "hovertemplate": "color=3
x=%{x}
y=%{y}", "legendgroup": "3", "line": { "color": "#00cc96", "dash": "solid" }, "marker": { "symbol": "circle" }, "mode": "lines", "name": "3", "showlegend": true, "type": "scattergl", "x": [ 100, 99.29993160631898, 99.29993160631898, 99.38148169571427, 99.38148169571427, 99.33344287701127, 99.33344287701127, 99.78052429956195, 99.78052429956195, 99.54958970085868, 99.54958970085868, 99.5415288602601, 99.5415288602601, 99.20043010937233, 99.20043010937233, 98.38175972088112, 98.38175972088112, 98.08171337358606, 98.08171337358606, 98.3146135545321, 98.3146135545321, 98.15163483592876, 98.15163483592876, 98.2617316271704, 98.2617316271704, 98.4307104729456, 98.4307104729456, 98.78953357215462, 98.78953357215462, 98.79985727776051, 98.79985727776051, 99.23692266333096, 99.23692266333096, 98.39279376646044, 98.39279376646044, 98.38874784974972, 98.38874784974972, 98.47174801810372, 98.47174801810372, 98.2916973612909, 98.2916973612909, 98.77808827688989, 98.77808827688989, 98.74409721517681, 98.74409721517681, 99.24190042277999, 99.24190042277999, 98.84599456847697, 98.84599456847697, 99.09135177709153, 99.09135177709153, 99.10434894166539, 99.10434894166539, 99.57328874254877, 99.57328874254877, 99.21501237298247, 99.21501237298247, 99.25020700392601, 99.25020700392601, 99.63288351336783, 99.63288351336783, 99.40473856709445, 99.40473856709445, 98.7710291940686, 98.7710291940686, 98.5407493936721, 98.5407493936721, 97.7508566239193, 97.7508566239193, 97.71072647387824, 97.71072647387824, 97.06612114764668, 97.06612114764668, 96.60023270185529, 96.60023270185529, 96.97950519720334, 96.97950519720334, 97.13875284807816, 97.13875284807816, 97.28197178315625, 97.28197178315625, 96.58033571299049, 96.58033571299049, 96.25643172904921, 96.25643172904921, 96.6261400000404, 96.6261400000404, 96.52079469759674, 96.52079469759674, 96.14265950886788, 96.14265950886788, 96.29506225210642, 96.29506225210642, 95.82910831575578, 95.82910831575578, 96.35112441973347, 96.35112441973347, 96.16329269178928, 96.16329269178928, 95.87027246972195, 95.87027246972195, 95.7307727305111, 95.7307727305111, 95.52782525481386, 95.52782525481386, 95.3266966060663, 95.3266966060663, 94.73244989096955, 94.73244989096955, 94.85863986535756, 94.85863986535756, 94.5348526851931, 94.5348526851931, 94.27697635190073, 94.27697635190073, 93.47026915554588, 93.47026915554588, 93.23682795968988, 93.23682795968988, 93.37231139151324, 93.37231139151324, 93.15534439539415, 93.15534439539415, 93.24217287585641, 93.24217287585641, 93.78860723896459, 93.78860723896459, 93.77560714675685, 93.77560714675685, 93.0999726791823, 93.0999726791823, 92.90606801326578, 92.90606801326578, 93.2831221906634, 93.2831221906634, 93.01583352672039, 93.01583352672039, 92.70359835023112, 92.70359835023112, 92.00530036542673, 92.00530036542673, 92.42100834060409, 92.42100834060409, 92.7895835919253, 92.7895835919253, 92.73717490018763, 92.73717490018763, 92.76883196952322, 92.76883196952322, 93.08317487684629, 93.08317487684629, 92.33451766496589, 92.33451766496589, 92.13498897315472, 92.13498897315472, 92.09928886790658, 92.09928886790658, 92.22680948420437, 92.22680948420437, 91.62546599412939, 91.62546599412939, 91.12033628158707, 91.12033628158707, 90.91703470428618, 90.91703470428618, 90.51203613658468, 90.51203613658468, 90.76461607129751, 90.76461607129751, 91.12216656725413, 91.12216656725413, 91.25249379875453, 91.25249379875453, 91.58012004487541, 91.58012004487541, 91.06486472813755, 91.06486472813755, 91.18797649222013, 91.18797649222013, 90.69671638734081, 90.69671638734081, 91.26790712942591, 91.26790712942591, 90.79702047570592, 90.79702047570592, 90.23186056687439, 90.23186056687439, 89.67634735880623, 89.67634735880623, 90.06987166421722, 90.06987166421722, 89.65940405481305, 89.65940405481305, 89.14786912937605, 89.14786912937605, 88.68086196244481, 88.68086196244481, 88.08424380115036, 88.08424380115036, 87.92914636627808, 87.92914636627808, 100, 92.99931606318984, 92.99931606318984, 93.74968330870446, 93.74968330870446, 93.35200242595599, 93.35200242595599, 97.61217815984494, 97.61217815984494, 95.54997817570786, 95.54997817570786, 95.635092884268, 95.635092884268, 92.61880754039443, 92.61880754039443, 85.39231796273906, 85.39231796273906, 83.12912862094319, 83.12912862094319, 85.40561642328275, 85.40561642328275, 84.62039860344953, 84.62039860344953, 86.16474388636449, 86.16474388636449, 88.32785188924211, 88.32785188924211, 92.10765900299248, 92.10765900299248, 93.26077770768009, 93.26077770768009, 97.9845294627281, 97.9845294627281, 91.85128228934461, 91.85128228934461, 92.94825282196534, 92.94825282196534, 94.908060967487, 94.908060967487, 94.71326538271349, 94.71326538271349, 100.13862169564187, 100.13862169564187, 101.27435286478284, 101.27435286478284, 107.18723419784558, 107.18723419784558, 105.11150551338793, 105.11150551338793, 108.89332418604562, 108.89332418604562, 110.45800926706632, 110.45800926706632, 116.48523146511381, 116.48523146511381, 114.1292438507272, 114.1292438507272, 115.6710564645791, 115.6710564645791, 120.72623435030194, 120.72623435030194, 118.93046533906094, 118.93046533906094, 112.25835075871757, 112.25835075871757, 110.00527663324144, 110.00527663324144, 101.43663074912372, 101.43663074912372, 101.02867217786005, 101.02867217786005, 94.33053060847377, 94.33053060847377, 89.75476827975842, 89.75476827975842, 93.29245542951959, 93.29245542951959, 94.9186805787271, 94.9186805787271, 96.46551527277536, 96.46551527277536, 89.87389035969865, 89.87389035969865, 87.16376777592785, 87.16376777592785, 90.71447055509934, 90.71447055509934, 90.19536558085994, 90.19536558085994, 87.37997504032674, 87.37997504032674, 89.23463194487961, 89.23463194487961, 85.88495474723042, 85.88495474723042, 90.91229934650016, 90.91229934650016, 90.15196996137051, 90.15196996137051, 88.67602042222708, 88.67602042222708, 88.50743002514825, 88.50743002514825, 87.96325417167918, 87.96325417167918, 87.47813607760847, 87.47813607760847, 84.01053269460503, 84.01053269460503, 86.21927941269837, 86.21927941269837, 85.20026287932083, 85.20026287932083, 84.74514940369397, 84.74514940369397, 80.44680552355874, 80.44680552355874, 80.41520185078912, 80.41520185078912, 83.13776682112793, 83.13776682112793, 83.62311825579216, 83.62311825579216, 86.27091768763398, 86.27091768763398, 92.29068344923925, 92.29068344923925, 94.59113655600862, 94.59113655600862, 92.23253576603186, 92.23253576603186, 93.36203549432568, 93.36203549432568, 98.80311561440442, 98.80311561440442, 99.52383859763862, 99.52383859763862, 100.02610961464065, 100.02610961464065, 97.48148429129367, 97.48148429129367, 103.34545533154333, 103.34545533154333, 109.43020057074936, 109.43020057074936, 112.12304973808557, 112.12304973808557, 115.52003033279902, 115.52003033279902, 121.55801868602819, 121.55801868602819, 117.08958909341867, 117.08958909341867, 117.75922193520242, 117.75922193520242, 119.85458925018938, 119.85458925018938, 123.66274001251523, 123.66274001251523, 119.15604184133105, 119.15604184133105, 115.53291901293304, 115.53291901293304, 114.89363074478746, 114.89363074478746, 111.82198288405428, 111.82198288405428, 115.87910014654939, 115.87910014654939, 121.11836567425608, 121.11836567425608, 123.6936575690804, 123.6936575690804, 128.58085298226052, 128.58085298226052, 121.95792293344105, 121.95792293344105, 123.60374048079915, 123.60374048079915, 116.48935752258258, 116.48935752258258, 123.55808091733965, 123.55808091733965, 115.82597098962636, 115.82597098962636, 106.77349871746914, 106.77349871746914, 98.16867422379417, 98.16867422379417, 101.74594768140646, 101.74594768140646, 95.1243047124417, 95.1243047124417, 87.65512294066052, 87.65512294066052, 81.34224880318148, 81.34224880318148, 74.25512295493493, 74.25512295493493, 72.08158085400078, 72.08158085400078, 100, 96.49965803159492, 96.49965803159492, 96.89282234085528, 96.89282234085528, 96.66395700156504, 96.66395700156504, 98.84511851049147, 98.84511851049147, 97.72022468264952, 97.72022468264952, 97.69539195252099, 97.69539195252099, 96.04474200505408, 96.04474200505408, 92.12122707795169, 92.12122707795169, 90.7524578823741, 90.7524578823741, 91.86620599866295, 91.86620599866295, 91.18321550679761, 91.18321550679761, 91.77076300242805, 91.77076300242805, 92.64886983215455, 92.64886983215455, 94.4115531951917, 94.4115531951917, 94.60105803410664, 94.60105803410664, 96.77426923210655, 96.77426923210655, 92.95584004241334, 92.95584004241334, 93.0988602155345, 93.0988602155345, 93.66372732853505, 93.66372732853505, 93.03719912084956, 93.03719912084956, 95.452716939988, 95.452716939988, 95.51738150606599, 95.51738150606599, 98.05425788440175, 98.05425788440175, 96.45618107548292, 96.45618107548292, 97.85694974565604, 97.85694974565604, 98.17927424291095, 98.17927424291095, 100.65800191623217, 100.65800191623217, 99.23013457226213, 99.23013457226213, 99.68075990493776, 99.68075990493776, 101.76892968159176, 101.76892968159176, 100.93152794995164, 100.93152794995164, 98.15507445203599, 98.15507445203599, 97.32448920917646, 97.32448920917646, 93.8712393709979, 93.8712393709979, 93.94055110646606, 93.94055110646606, 91.25561322951836, 91.25561322951836, 89.45152914637421, 89.45152914637421, 91.38648456820863, 91.38648456820863, 92.40702828733023, 92.40702828733023, 93.37466906480901, 93.37466906480901, 90.60421743023397, 90.60421743023397, 89.54727537765943, 89.54727537765943, 91.50562818437629, 91.50562818437629, 91.43629555560625, 91.43629555560625, 90.22387819072098, 90.22387819072098, 91.286734506583, 91.286734506583, 89.70792037849891, 89.70792037849891, 92.36523442648821, 92.36523442648821, 92.01299752297405, 92.01299752297405, 91.26989588133198, 91.26989588133198, 91.16338302394053, 91.16338302394053, 90.8266416539283, 90.8266416539283, 90.48973346931841, 90.48973346931841, 88.53135087902336, 88.53135087902336, 89.58435442398849, 89.58435442398849, 88.8253866031861, 88.8253866031861, 88.3389425664917, 88.3389425664917, 85.6690510129246, 85.6690510129246, 85.33734615018504, 85.33734615018504, 86.51603920143914, 86.51603920143914, 86.33828493348129, 86.33828493348129, 87.36304955582791, 87.36304955582791, 90.23284652388249, 90.23284652388249, 90.91718361444943, 90.91718361444943, 88.99242906220593, 88.99242906220593, 88.99938883525597, 88.99938883525597, 91.30743180141197, 91.30743180141197, 91.05295854841216, 91.05295854841216, 90.67174729743687, 90.67174729743687, 88.7604154487307, 88.7604154487307, 91.21667934978741, 91.21667934978741, 93.6338256538187, 93.6338256538187, 94.37558676757705, 94.37558676757705, 95.47321941160612, 95.47321941160612, 97.77075917390104, 97.77075917390104, 95.59282238220855, 95.59282238220855, 95.72059903293992, 95.72059903293992, 96.52854695498216, 96.52854695498216, 98.09563460829936, 98.09563460829936, 96.51532722863074, 96.51532722863074, 95.4085247939158, 95.4085247939158, 95.52465821995634, 95.52465821995634, 94.8087017899729, 94.8087017899729, 96.88999312951138, 96.88999312951138, 99.41181607140739, 99.41181607140739, 101.0349689701463, 101.0349689701463, 103.52291722549926, 103.52291722549926, 102.29402709966891, 102.29402709966891, 103.89599855840412, 103.89599855840412, 102.66305598951656, 102.66305598951656, 106.35128198458621, 106.35128198458621, 105.2153347445648, 105.2153347445648, 103.54761969318548, 103.54761969318548, 101.9104419064554, 101.9104419064554, 104.68762728033715, 104.68762728033715, 103.74561762296544, 103.74561762296544, 102.29177188240789, 102.29177188240789, 100.99065500957371, 100.99065500957371, 99.08829773238939, 99.08829773238939, 99.25050915772879, 99.25050915772879 ], "xaxis": "x", "y": [ 15, 15.0025881631884, 15.0025881631884, 15.001496702185737, 15.001496702185737, 15.002361804039465, 15.002361804039465, 15.003883708196188, 15.003883708196188, 15.00568393679195, 15.00568393679195, 15.007415489103332, 15.007415489103332, 15.007679903819312, 15.007679903819312, 15.00785846437848, 15.00785846437848, 15.005149988731267, 15.005149988731267, 15.003693218370183, 15.003693218370183, 15.003201208353792, 15.003201208353792, 15.001441720795848, 15.001441720795848, 15.000133583406503, 15.000133583406503, 14.998369352308925, 14.998369352308925, 14.996174666815067, 14.996174666815067, 14.994789169151316, 14.994789169151316, 14.99321394632609, 14.99321394632609, 14.990466967358335, 14.990466967358335, 14.98892812664762, 14.98892812664762, 14.987709914471244, 14.987709914471244, 14.987290241379329, 14.987290241379329, 14.985547623238297, 14.985547623238297, 14.986392330287694, 14.986392330287694, 14.9857180023299, 14.9857180023299, 14.984461841594834, 14.984461841594834, 14.985073680988108, 14.985073680988108, 14.985562867120061, 14.985562867120061, 14.98541282187458, 14.98541282187458, 14.984719710317288, 14.984719710317288, 14.985916999281203, 14.985916999281203, 14.98625696832826, 14.98625696832826, 14.986605681348385, 14.986605681348385, 14.985955421994834, 14.985955421994834, 14.986129886338091, 14.986129886338091, 14.984477177626776, 14.984477177626776, 14.981225059271852, 14.981225059271852, 14.976432391666856, 14.976432391666856, 14.973674166171941, 14.973674166171941, 14.96980019046312, 14.96980019046312, 14.966768040636888, 14.966768040636888, 14.962334392385861, 14.962334392385861, 14.957429395595303, 14.957429395595303, 14.953568887352041, 14.953568887352041, 14.948548302693771, 14.948548302693771, 14.945167884771239, 14.945167884771239, 14.940572465174537, 14.940572465174537, 14.936861141832518, 14.936861141832518, 14.931906107640428, 14.931906107640428, 14.927219898398723, 14.927219898398723, 14.921427580941707, 14.921427580941707, 14.91592475619714, 14.91592475619714, 14.910827079437475, 14.910827079437475, 14.90399212146379, 14.90399212146379, 14.897887136036417, 14.897887136036417, 14.891130476962763, 14.891130476962763, 14.883405497521546, 14.883405497521546, 14.876434503668987, 14.876434503668987, 14.870076791929769, 14.870076791929769, 14.862470074033991, 14.862470074033991, 14.853101924486802, 14.853101924486802, 14.845417890954725, 14.845417890954725, 14.834854591138358, 14.834854591138358, 14.82487867160691, 14.82487867160691, 14.817333893722857, 14.817333893722857, 14.80795542406726, 14.80795542406726, 14.799736508431591, 14.799736508431591, 14.789248058469765, 14.789248058469765, 14.7801175136321, 14.7801175136321, 14.77151478230201, 14.77151478230201, 14.762483431482917, 14.762483431482917, 14.75140910811959, 14.75140910811959, 14.742427769315322, 14.742427769315322, 14.731695495637132, 14.731695495637132, 14.723316727651351, 14.723316727651351, 14.714085420344661, 14.714085420344661, 14.705044067153839, 14.705044067153839, 14.695511757105502, 14.695511757105502, 14.684106161453188, 14.684106161453188, 14.673362900138697, 14.673362900138697, 14.662126777303884, 14.662126777303884, 14.650294122378542, 14.650294122378542, 14.637133503588467, 14.637133503588467, 14.625885500549552, 14.625885500549552, 14.613041318879013, 14.613041318879013, 14.600491228516, 14.600491228516, 14.589826301169238, 14.589826301169238, 14.579097284458562, 14.579097284458562, 14.567445029812177, 14.567445029812177, 14.555065538321779, 14.555065538321779, 14.543083171721651, 14.543083171721651, 14.530543871653219, 14.530543871653219, 14.519732090172331, 14.519732090172331, 14.50728664083606, 14.50728664083606, 14.494761059082773, 14.494761059082773, 14.480759862525757, 14.480759862525757, 14.466954078017151, 14.466954078017151, 14.452655312592428, 14.452655312592428, 14.43861439698937, 14.43861439698937, 14.421950182244203, 14.421950182244203, 14.404714317939641, 14.404714317939641, 15, 15.025881631884008, 15.025881631884008, 14.919856780977506, 14.919856780977506, 14.84340539956636, 14.84340539956636, 14.768172517785956, 14.768172517785956, 14.753355341717914, 14.753355341717914, 14.710325587285196, 14.710325587285196, 14.65501286735965, 14.65501286735965, 14.558960244492898, 14.558960244492898, 14.343261540533113, 14.343261540533113, 14.112473629068363, 14.112473629068363, 13.923048492146386, 13.923048492146386, 13.716505105851384, 13.716505105851384, 13.536396160701718, 13.536396160701718, 13.382627368919778, 13.382627368919778, 13.273403497288376, 13.273403497288376, 13.18737339314849, 13.18737339314849, 13.15696932845709, 13.15696932845709, 13.046690159522171, 13.046690159522171, 12.961691639243096, 12.961691639243096, 12.904545878763365, 12.904545878763365, 12.853989386327374, 12.853989386327374, 12.856562555701977, 12.856562555701977, 12.89695026210208, 12.89695026210208, 12.99401382064389, 12.99401382064389, 13.064986472742175, 13.064986472742175, 13.200100005296521, 13.200100005296521, 13.356245186734787, 13.356245186734787, 13.581858258648817, 13.581858258648817, 13.779446331861786, 13.779446331861786, 14.020887197803892, 14.020887197803892, 14.322226633251981, 14.322226633251981, 14.607966995872808, 14.607966995872808, 14.80045909939326, 14.80045909939326, 14.974742020331096, 14.974742020331096, 15.014139514654353, 15.014139514654353, 15.031590488973418, 15.031590488973418, 14.942284460374912, 14.942284460374912, 14.810526845162071, 14.810526845162071, 14.71725604402707, 14.71725604402707, 14.654423668399897, 14.654423668399897, 14.59904128346401, 14.59904128346401, 14.452865602940358, 14.452865602940358, 14.282261478879674, 14.282261478879674, 14.149772009038367, 14.149772009038367, 14.027052069983485, 14.027052069983485, 13.859992607077059, 13.859992607077059, 13.726038665079807, 13.726038665079807, 13.542762810472052, 13.542762810472052, 13.426206655218582, 13.426206655218582, 13.293233924236567, 13.293233924236567, 13.147791616712704, 13.147791616712704, 13.006610763951292, 13.006610763951292, 12.84823986731333, 12.84823986731333, 12.693804885133208, 12.693804885133208, 12.498890192871052, 12.498890192871052, 12.325809989121367, 12.325809989121367, 12.151607078337484, 12.151607078337484, 11.98176127509246, 11.98176127509246, 11.761719359770526, 11.761719359770526, 11.535738338854555, 11.535738338854555, 11.356031924588308, 11.356031924588308, 11.166858150706151, 11.166858150706151, 11.013537609868145, 11.013537609868145, 10.940785833361874, 10.940785833361874, 10.880470893076224, 10.880470893076224, 10.810492031684296, 10.810492031684296, 10.738828174758915, 10.738828174758915, 10.732227365833888, 10.732227365833888, 10.74063259552893, 10.74063259552893, 10.754970118090359, 10.754970118090359, 10.733785904628672, 10.733785904628672, 10.787976887758164, 10.787976887758164, 10.88944458640169, 10.88944458640169, 11.04254907916619, 11.04254907916619, 11.228202407568958, 11.228202407568958, 11.482818264639777, 11.482818264639777, 11.69687181566044, 11.69687181566044, 11.906283961960796, 11.906283961960796, 12.151929632994989, 12.151929632994989, 12.442078661195602, 12.442078661195602, 12.685614756768384, 12.685614756768384, 12.882246373678006, 12.882246373678006, 13.098033807459965, 13.098033807459965, 13.265644619378074, 13.265644619378074, 13.488205244369283, 13.488205244369283, 13.801786381602861, 13.801786381602861, 14.15661507092392, 14.15661507092392, 14.571319896228996, 14.571319896228996, 14.900498464260913, 14.900498464260913, 15.264447207321453, 15.264447207321453, 15.531123380217505, 15.531123380217505, 15.924513627073946, 15.924513627073946, 16.19019922374802, 16.19019922374802, 16.322098263657374, 16.322098263657374, 16.304174332335062, 16.304174332335062, 16.340241196629936, 16.340241196629936, 16.268904220202955, 16.268904220202955, 16.086253203878236, 16.086253203878236, 15.782468169262778, 15.782468169262778, 15.374958294571538, 15.374958294571538, 15, 15.012940815942004, 15.012940815942004, 14.98636610132836, 14.98636610132836, 14.971810745493599, 14.971810745493599, 14.959082346076983, 14.959082346076983, 14.960947875173133, 14.960947875173133, 14.95565263271521, 14.95565263271521, 14.943059453110807, 14.943059453110807, 14.920042423099233, 14.920042423099233, 14.859798697725925, 14.859798697725925, 14.797521921922066, 14.797521921922066, 14.746699458020705, 14.746699458020705, 14.686175690662845, 14.686175690662845, 14.631471102128723, 14.631471102128723, 14.58023065366825, 14.58023065366825, 14.537568554812667, 14.537568554812667, 14.500231317119468, 14.500231317119468, 14.474722857563513, 14.474722857563513, 14.4220647350196, 14.4220647350196, 14.376180825464203, 14.376180825464203, 14.335464151009303, 14.335464151009303, 14.295170307805137, 14.295170307805137, 14.263049608683579, 14.263049608683579, 14.243626386186193, 14.243626386186193, 14.231930990766053, 14.231930990766053, 14.208866161776603, 14.208866161776603, 14.202879759057403, 14.202879759057403, 14.198542451693676, 14.198542451693676, 14.205568788947831, 14.205568788947831, 14.202391682296767, 14.202391682296767, 14.211179246898407, 14.211179246898407, 14.22809282401728, 14.22809282401728, 14.240716868942075, 14.240716868942075, 14.233201323513999, 14.233201323513999, 14.225227297004473, 14.225227297004473, 14.189429886330164, 14.189429886330164, 14.147165369806896, 14.147165369806896, 14.08333714510193, 14.08333714510193, 14.019069291306938, 14.019069291306938, 13.961481416227368, 13.961481416227368, 13.913958049210835, 13.913958049210835, 13.866151471260338, 13.866151471260338, 13.801817295121142, 13.801817295121142, 13.737042236766802, 13.737042236766802, 13.678767238942457, 13.678767238942457, 13.628052525015123, 13.628052525015123, 13.56643704645608, 13.56643704645608, 13.515035696227566, 13.515035696227566, 13.450876501139497, 13.450876501139497, 13.402818129238593, 13.402818129238593, 13.348944553667687, 13.348944553667687, 13.293373264063145, 13.293373264063145, 13.239891656584982, 13.239891656584982, 13.178310915340727, 13.178310915340727, 13.11914363309317, 13.11914363309317, 13.04834605494057, 13.04834605494057, 12.980008418510142, 12.980008418510142, 12.912100563936535, 12.912100563936535, 12.84548257168026, 12.84548257168026, 12.761653328708682, 12.761653328708682, 12.670680742782599, 12.670680742782599, 12.593746048181327, 12.593746048181327, 12.505966192387636, 12.505966192387636, 12.426975415778585, 12.426975415778585, 12.372987114877688, 12.372987114877688, 12.316124888297376, 12.316124888297376, 12.25624784136798, 12.25624784136798, 12.188780748399955, 12.188780748399955, 12.139029429691613, 12.139029429691613, 12.091613175035052, 12.091613175035052, 12.042152685505714, 12.042152685505714, 11.977247905600317, 11.977247905600317, 11.933433733774168, 11.933433733774168, 11.89504783502318, 11.89504783502318, 11.871147080760428, 11.871147080760428, 11.850217659047976, 11.850217659047976, 11.84192192212905, 11.84192192212905, 11.82311969344896, 11.82311969344896, 11.798468322241224, 11.798468322241224, 11.781618541251447, 11.781618541251447, 11.771189982727265, 11.771189982727265, 11.752590059889691, 11.752590059889691, 11.725074162195554, 11.725074162195554, 11.707552281866988, 11.707552281866988, 11.681614136981478, 11.681614136981478, 11.667586378488018, 11.667586378488018, 11.674231291283325, 11.674231291283325, 11.689501880321215, 11.689501880321215, 11.71312985613572, 11.71312985613572, 11.729541695595978, 11.729541695595978, 11.756346252143663, 11.756346252143663, 11.776821825896544, 11.776821825896544, 11.823144360448932, 11.823144360448932, 11.858480184796978, 11.858480184796978, 11.887381186413212, 11.887381186413212, 11.903274853981108, 11.903274853981108, 11.934053284575308, 11.934053284575308, 11.959946529310686, 11.959946529310686, 11.981458643093886, 11.981458643093886, 11.986109221284174, 11.986109221284174, 11.98062484432249, 11.98062484432249 ], "yaxis": "y" }, { "hovertemplate": "color=4
x=%{x}
y=%{y}", "legendgroup": "4", "line": { "color": "#ab63fa", "dash": "solid" }, "marker": { "symbol": "circle" }, "mode": "lines", "name": "4", "showlegend": true, "type": "scattergl", "x": [ 100, 99.29993160631898, 99.29993160631898, 99.38148169571427, 99.38148169571427, 99.33344287701127, 99.33344287701127, 99.78052429956195, 99.78052429956195, 99.54958970085868, 99.54958970085868, 99.5415288602601, 99.5415288602601, 99.20043010937233, 99.20043010937233, 98.38175972088112, 98.38175972088112, 98.08171337358606, 98.08171337358606, 98.3146135545321, 98.3146135545321, 98.15163483592876, 98.15163483592876, 98.2617316271704, 98.2617316271704, 98.4307104729456, 98.4307104729456, 98.78953357215462, 98.78953357215462, 98.79985727776051, 98.79985727776051, 99.23692266333096, 99.23692266333096, 98.39279376646044, 98.39279376646044, 98.38874784974972, 98.38874784974972, 98.47174801810372, 98.47174801810372, 98.2916973612909, 98.2916973612909, 98.77808827688989, 98.77808827688989, 98.74409721517681, 98.74409721517681, 99.24190042277999, 99.24190042277999, 98.84599456847697, 98.84599456847697, 99.09135177709153, 99.09135177709153, 99.10434894166539, 99.10434894166539, 99.57328874254877, 99.57328874254877, 99.21501237298247, 99.21501237298247, 99.25020700392601, 99.25020700392601, 99.63288351336783, 99.63288351336783, 99.40473856709445, 99.40473856709445, 98.7710291940686, 98.7710291940686, 98.5407493936721, 98.5407493936721, 97.7508566239193, 97.7508566239193, 97.71072647387824, 97.71072647387824, 97.06612114764668, 97.06612114764668, 96.60023270185529, 96.60023270185529, 96.97950519720334, 96.97950519720334, 97.13875284807816, 97.13875284807816, 97.28197178315625, 97.28197178315625, 96.58033571299049, 96.58033571299049, 96.25643172904921, 96.25643172904921, 96.6261400000404, 96.6261400000404, 96.52079469759674, 96.52079469759674, 96.14265950886788, 96.14265950886788, 96.29506225210642, 96.29506225210642, 95.82910831575578, 95.82910831575578, 96.35112441973347, 96.35112441973347, 96.16329269178928, 96.16329269178928, 95.87027246972195, 95.87027246972195, 95.7307727305111, 95.7307727305111, 95.52782525481386, 95.52782525481386, 95.3266966060663, 95.3266966060663, 94.73244989096955, 94.73244989096955, 94.85863986535756, 94.85863986535756, 94.5348526851931, 94.5348526851931, 94.27697635190073, 94.27697635190073, 93.47026915554588, 93.47026915554588, 93.23682795968988, 93.23682795968988, 93.37231139151324, 93.37231139151324, 93.15534439539415, 93.15534439539415, 93.24217287585641, 93.24217287585641, 93.78860723896459, 93.78860723896459, 93.77560714675685, 93.77560714675685, 93.0999726791823, 93.0999726791823, 92.90606801326578, 92.90606801326578, 93.2831221906634, 93.2831221906634, 93.01583352672039, 93.01583352672039, 92.70359835023112, 92.70359835023112, 92.00530036542673, 92.00530036542673, 92.42100834060409, 92.42100834060409, 92.7895835919253, 92.7895835919253, 92.73717490018763, 92.73717490018763, 92.76883196952322, 92.76883196952322, 93.08317487684629, 93.08317487684629, 92.33451766496589, 92.33451766496589, 92.13498897315472, 92.13498897315472, 92.09928886790658, 92.09928886790658, 92.22680948420437, 92.22680948420437, 91.62546599412939, 91.62546599412939, 91.12033628158707, 91.12033628158707, 90.91703470428618, 90.91703470428618, 90.51203613658468, 90.51203613658468, 90.76461607129751, 90.76461607129751, 91.12216656725413, 91.12216656725413, 91.25249379875453, 91.25249379875453, 91.58012004487541, 91.58012004487541, 91.06486472813755, 91.06486472813755, 91.18797649222013, 91.18797649222013, 90.69671638734081, 90.69671638734081, 91.26790712942591, 91.26790712942591, 90.79702047570592, 90.79702047570592, 90.23186056687439, 90.23186056687439, 89.67634735880623, 89.67634735880623, 90.06987166421722, 90.06987166421722, 89.65940405481305, 89.65940405481305, 89.14786912937605, 89.14786912937605, 88.68086196244481, 88.68086196244481, 88.08424380115036, 88.08424380115036, 87.92914636627808, 87.92914636627808, 100, 92.99931606318984, 92.99931606318984, 93.74968330870446, 93.74968330870446, 93.35200242595599, 93.35200242595599, 97.61217815984494, 97.61217815984494, 95.54997817570786, 95.54997817570786, 95.635092884268, 95.635092884268, 92.61880754039443, 92.61880754039443, 85.39231796273906, 85.39231796273906, 83.12912862094319, 83.12912862094319, 85.40561642328275, 85.40561642328275, 84.62039860344953, 84.62039860344953, 86.16474388636449, 86.16474388636449, 88.32785188924211, 88.32785188924211, 92.10765900299248, 92.10765900299248, 93.26077770768009, 93.26077770768009, 97.9845294627281, 97.9845294627281, 91.85128228934461, 91.85128228934461, 92.94825282196534, 92.94825282196534, 94.908060967487, 94.908060967487, 94.71326538271349, 94.71326538271349, 100.13862169564187, 100.13862169564187, 101.27435286478284, 101.27435286478284, 107.18723419784558, 107.18723419784558, 105.11150551338793, 105.11150551338793, 108.89332418604562, 108.89332418604562, 110.45800926706632, 110.45800926706632, 116.48523146511381, 116.48523146511381, 114.1292438507272, 114.1292438507272, 115.6710564645791, 115.6710564645791, 120.72623435030194, 120.72623435030194, 118.93046533906094, 118.93046533906094, 112.25835075871757, 112.25835075871757, 110.00527663324144, 110.00527663324144, 101.43663074912372, 101.43663074912372, 101.02867217786005, 101.02867217786005, 94.33053060847377, 94.33053060847377, 89.75476827975842, 89.75476827975842, 93.29245542951959, 93.29245542951959, 94.9186805787271, 94.9186805787271, 96.46551527277536, 96.46551527277536, 89.87389035969865, 89.87389035969865, 87.16376777592785, 87.16376777592785, 90.71447055509934, 90.71447055509934, 90.19536558085994, 90.19536558085994, 87.37997504032674, 87.37997504032674, 89.23463194487961, 89.23463194487961, 85.88495474723042, 85.88495474723042, 90.91229934650016, 90.91229934650016, 90.15196996137051, 90.15196996137051, 88.67602042222708, 88.67602042222708, 88.50743002514825, 88.50743002514825, 87.96325417167918, 87.96325417167918, 87.47813607760847, 87.47813607760847, 84.01053269460503, 84.01053269460503, 86.21927941269837, 86.21927941269837, 85.20026287932083, 85.20026287932083, 84.74514940369397, 84.74514940369397, 80.44680552355874, 80.44680552355874, 80.41520185078912, 80.41520185078912, 83.13776682112793, 83.13776682112793, 83.62311825579216, 83.62311825579216, 86.27091768763398, 86.27091768763398, 92.29068344923925, 92.29068344923925, 94.59113655600862, 94.59113655600862, 92.23253576603186, 92.23253576603186, 93.36203549432568, 93.36203549432568, 98.80311561440442, 98.80311561440442, 99.52383859763862, 99.52383859763862, 100.02610961464065, 100.02610961464065, 97.48148429129367, 97.48148429129367, 103.34545533154333, 103.34545533154333, 109.43020057074936, 109.43020057074936, 112.12304973808557, 112.12304973808557, 115.52003033279902, 115.52003033279902, 121.55801868602819, 121.55801868602819, 117.08958909341867, 117.08958909341867, 117.75922193520242, 117.75922193520242, 119.85458925018938, 119.85458925018938, 123.66274001251523, 123.66274001251523, 119.15604184133105, 119.15604184133105, 115.53291901293304, 115.53291901293304, 114.89363074478746, 114.89363074478746, 111.82198288405428, 111.82198288405428, 115.87910014654939, 115.87910014654939, 121.11836567425608, 121.11836567425608, 123.6936575690804, 123.6936575690804, 128.58085298226052, 128.58085298226052, 121.95792293344105, 121.95792293344105, 123.60374048079915, 123.60374048079915, 116.48935752258258, 116.48935752258258, 123.55808091733965, 123.55808091733965, 115.82597098962636, 115.82597098962636, 106.77349871746914, 106.77349871746914, 98.16867422379417, 98.16867422379417, 101.74594768140646, 101.74594768140646, 95.1243047124417, 95.1243047124417, 87.65512294066052, 87.65512294066052, 81.34224880318148, 81.34224880318148, 74.25512295493493, 74.25512295493493, 72.08158085400078, 72.08158085400078, 100, 96.49965803159492, 96.49965803159492, 96.89282234085528, 96.89282234085528, 96.66395700156504, 96.66395700156504, 98.84511851049147, 98.84511851049147, 97.72022468264952, 97.72022468264952, 97.69539195252099, 97.69539195252099, 96.04474200505408, 96.04474200505408, 92.12122707795169, 92.12122707795169, 90.7524578823741, 90.7524578823741, 91.86620599866295, 91.86620599866295, 91.18321550679761, 91.18321550679761, 91.77076300242805, 91.77076300242805, 92.64886983215455, 92.64886983215455, 94.4115531951917, 94.4115531951917, 94.60105803410664, 94.60105803410664, 96.77426923210655, 96.77426923210655, 92.95584004241334, 92.95584004241334, 93.0988602155345, 93.0988602155345, 93.66372732853505, 93.66372732853505, 93.03719912084956, 93.03719912084956, 95.452716939988, 95.452716939988, 95.51738150606599, 95.51738150606599, 98.05425788440175, 98.05425788440175, 96.45618107548292, 96.45618107548292, 97.85694974565604, 97.85694974565604, 98.17927424291095, 98.17927424291095, 100.65800191623217, 100.65800191623217, 99.23013457226213, 99.23013457226213, 99.68075990493776, 99.68075990493776, 101.76892968159176, 101.76892968159176, 100.93152794995164, 100.93152794995164, 98.15507445203599, 98.15507445203599, 97.32448920917646, 97.32448920917646, 93.8712393709979, 93.8712393709979, 93.94055110646606, 93.94055110646606, 91.25561322951836, 91.25561322951836, 89.45152914637421, 89.45152914637421, 91.38648456820863, 91.38648456820863, 92.40702828733023, 92.40702828733023, 93.37466906480901, 93.37466906480901, 90.60421743023397, 90.60421743023397, 89.54727537765943, 89.54727537765943, 91.50562818437629, 91.50562818437629, 91.43629555560625, 91.43629555560625, 90.22387819072098, 90.22387819072098, 91.286734506583, 91.286734506583, 89.70792037849891, 89.70792037849891, 92.36523442648821, 92.36523442648821, 92.01299752297405, 92.01299752297405, 91.26989588133198, 91.26989588133198, 91.16338302394053, 91.16338302394053, 90.8266416539283, 90.8266416539283, 90.48973346931841, 90.48973346931841, 88.53135087902336, 88.53135087902336, 89.58435442398849, 89.58435442398849, 88.8253866031861, 88.8253866031861, 88.3389425664917, 88.3389425664917, 85.6690510129246, 85.6690510129246, 85.33734615018504, 85.33734615018504, 86.51603920143914, 86.51603920143914, 86.33828493348129, 86.33828493348129, 87.36304955582791, 87.36304955582791, 90.23284652388249, 90.23284652388249, 90.91718361444943, 90.91718361444943, 88.99242906220593, 88.99242906220593, 88.99938883525597, 88.99938883525597, 91.30743180141197, 91.30743180141197, 91.05295854841216, 91.05295854841216, 90.67174729743687, 90.67174729743687, 88.7604154487307, 88.7604154487307, 91.21667934978741, 91.21667934978741, 93.6338256538187, 93.6338256538187, 94.37558676757705, 94.37558676757705, 95.47321941160612, 95.47321941160612, 97.77075917390104, 97.77075917390104, 95.59282238220855, 95.59282238220855, 95.72059903293992, 95.72059903293992, 96.52854695498216, 96.52854695498216, 98.09563460829936, 98.09563460829936, 96.51532722863074, 96.51532722863074, 95.4085247939158, 95.4085247939158, 95.52465821995634, 95.52465821995634, 94.8087017899729, 94.8087017899729, 96.88999312951138, 96.88999312951138, 99.41181607140739, 99.41181607140739, 101.0349689701463, 101.0349689701463, 103.52291722549926, 103.52291722549926, 102.29402709966891, 102.29402709966891, 103.89599855840412, 103.89599855840412, 102.66305598951656, 102.66305598951656, 106.35128198458621, 106.35128198458621, 105.2153347445648, 105.2153347445648, 103.54761969318548, 103.54761969318548, 101.9104419064554, 101.9104419064554, 104.68762728033715, 104.68762728033715, 103.74561762296544, 103.74561762296544, 102.29177188240789, 102.29177188240789, 100.99065500957371, 100.99065500957371, 99.08829773238939, 99.08829773238939, 99.25050915772879, 99.25050915772879 ], "xaxis": "x", "y": [ 15, 15.0025881631884, 15.0025881631884, 15.001496702185737, 15.001496702185737, 15.002361804039465, 15.002361804039465, 15.003883708196188, 15.003883708196188, 15.00568393679195, 15.00568393679195, 15.007415489103332, 15.007415489103332, 15.007679903819312, 15.007679903819312, 15.00785846437848, 15.00785846437848, 15.005149988731267, 15.005149988731267, 15.003693218370183, 15.003693218370183, 15.003201208353792, 15.003201208353792, 15.001441720795848, 15.001441720795848, 15.000133583406503, 15.000133583406503, 14.998369352308925, 14.998369352308925, 14.996174666815067, 14.996174666815067, 14.994789169151316, 14.994789169151316, 14.99321394632609, 14.99321394632609, 14.990466967358335, 14.990466967358335, 14.98892812664762, 14.98892812664762, 14.987709914471244, 14.987709914471244, 14.987290241379329, 14.987290241379329, 14.985547623238297, 14.985547623238297, 14.986392330287694, 14.986392330287694, 14.9857180023299, 14.9857180023299, 14.984461841594834, 14.984461841594834, 14.985073680988108, 14.985073680988108, 14.985562867120061, 14.985562867120061, 14.98541282187458, 14.98541282187458, 14.984719710317288, 14.984719710317288, 14.985916999281203, 14.985916999281203, 14.98625696832826, 14.98625696832826, 14.986605681348385, 14.986605681348385, 14.985955421994834, 14.985955421994834, 14.986129886338091, 14.986129886338091, 14.984477177626776, 14.984477177626776, 14.981225059271852, 14.981225059271852, 14.976432391666856, 14.976432391666856, 14.973674166171941, 14.973674166171941, 14.96980019046312, 14.96980019046312, 14.966768040636888, 14.966768040636888, 14.962334392385861, 14.962334392385861, 14.957429395595303, 14.957429395595303, 14.953568887352041, 14.953568887352041, 14.948548302693771, 14.948548302693771, 14.945167884771239, 14.945167884771239, 14.940572465174537, 14.940572465174537, 14.936861141832518, 14.936861141832518, 14.931906107640428, 14.931906107640428, 14.927219898398723, 14.927219898398723, 14.921427580941707, 14.921427580941707, 14.91592475619714, 14.91592475619714, 14.910827079437475, 14.910827079437475, 14.90399212146379, 14.90399212146379, 14.897887136036417, 14.897887136036417, 14.891130476962763, 14.891130476962763, 14.883405497521546, 14.883405497521546, 14.876434503668987, 14.876434503668987, 14.870076791929769, 14.870076791929769, 14.862470074033991, 14.862470074033991, 14.853101924486802, 14.853101924486802, 14.845417890954725, 14.845417890954725, 14.834854591138358, 14.834854591138358, 14.82487867160691, 14.82487867160691, 14.817333893722857, 14.817333893722857, 14.80795542406726, 14.80795542406726, 14.799736508431591, 14.799736508431591, 14.789248058469765, 14.789248058469765, 14.7801175136321, 14.7801175136321, 14.77151478230201, 14.77151478230201, 14.762483431482917, 14.762483431482917, 14.75140910811959, 14.75140910811959, 14.742427769315322, 14.742427769315322, 14.731695495637132, 14.731695495637132, 14.723316727651351, 14.723316727651351, 14.714085420344661, 14.714085420344661, 14.705044067153839, 14.705044067153839, 14.695511757105502, 14.695511757105502, 14.684106161453188, 14.684106161453188, 14.673362900138697, 14.673362900138697, 14.662126777303884, 14.662126777303884, 14.650294122378542, 14.650294122378542, 14.637133503588467, 14.637133503588467, 14.625885500549552, 14.625885500549552, 14.613041318879013, 14.613041318879013, 14.600491228516, 14.600491228516, 14.589826301169238, 14.589826301169238, 14.579097284458562, 14.579097284458562, 14.567445029812177, 14.567445029812177, 14.555065538321779, 14.555065538321779, 14.543083171721651, 14.543083171721651, 14.530543871653219, 14.530543871653219, 14.519732090172331, 14.519732090172331, 14.50728664083606, 14.50728664083606, 14.494761059082773, 14.494761059082773, 14.480759862525757, 14.480759862525757, 14.466954078017151, 14.466954078017151, 14.452655312592428, 14.452655312592428, 14.43861439698937, 14.43861439698937, 14.421950182244203, 14.421950182244203, 14.404714317939641, 14.404714317939641, 15, 15.025881631884008, 15.025881631884008, 14.919856780977506, 14.919856780977506, 14.84340539956636, 14.84340539956636, 14.768172517785956, 14.768172517785956, 14.753355341717914, 14.753355341717914, 14.710325587285196, 14.710325587285196, 14.65501286735965, 14.65501286735965, 14.558960244492898, 14.558960244492898, 14.343261540533113, 14.343261540533113, 14.112473629068363, 14.112473629068363, 13.923048492146386, 13.923048492146386, 13.716505105851384, 13.716505105851384, 13.536396160701718, 13.536396160701718, 13.382627368919778, 13.382627368919778, 13.273403497288376, 13.273403497288376, 13.18737339314849, 13.18737339314849, 13.15696932845709, 13.15696932845709, 13.046690159522171, 13.046690159522171, 12.961691639243096, 12.961691639243096, 12.904545878763365, 12.904545878763365, 12.853989386327374, 12.853989386327374, 12.856562555701977, 12.856562555701977, 12.89695026210208, 12.89695026210208, 12.99401382064389, 12.99401382064389, 13.064986472742175, 13.064986472742175, 13.200100005296521, 13.200100005296521, 13.356245186734787, 13.356245186734787, 13.581858258648817, 13.581858258648817, 13.779446331861786, 13.779446331861786, 14.020887197803892, 14.020887197803892, 14.322226633251981, 14.322226633251981, 14.607966995872808, 14.607966995872808, 14.80045909939326, 14.80045909939326, 14.974742020331096, 14.974742020331096, 15.014139514654353, 15.014139514654353, 15.031590488973418, 15.031590488973418, 14.942284460374912, 14.942284460374912, 14.810526845162071, 14.810526845162071, 14.71725604402707, 14.71725604402707, 14.654423668399897, 14.654423668399897, 14.59904128346401, 14.59904128346401, 14.452865602940358, 14.452865602940358, 14.282261478879674, 14.282261478879674, 14.149772009038367, 14.149772009038367, 14.027052069983485, 14.027052069983485, 13.859992607077059, 13.859992607077059, 13.726038665079807, 13.726038665079807, 13.542762810472052, 13.542762810472052, 13.426206655218582, 13.426206655218582, 13.293233924236567, 13.293233924236567, 13.147791616712704, 13.147791616712704, 13.006610763951292, 13.006610763951292, 12.84823986731333, 12.84823986731333, 12.693804885133208, 12.693804885133208, 12.498890192871052, 12.498890192871052, 12.325809989121367, 12.325809989121367, 12.151607078337484, 12.151607078337484, 11.98176127509246, 11.98176127509246, 11.761719359770526, 11.761719359770526, 11.535738338854555, 11.535738338854555, 11.356031924588308, 11.356031924588308, 11.166858150706151, 11.166858150706151, 11.013537609868145, 11.013537609868145, 10.940785833361874, 10.940785833361874, 10.880470893076224, 10.880470893076224, 10.810492031684296, 10.810492031684296, 10.738828174758915, 10.738828174758915, 10.732227365833888, 10.732227365833888, 10.74063259552893, 10.74063259552893, 10.754970118090359, 10.754970118090359, 10.733785904628672, 10.733785904628672, 10.787976887758164, 10.787976887758164, 10.88944458640169, 10.88944458640169, 11.04254907916619, 11.04254907916619, 11.228202407568958, 11.228202407568958, 11.482818264639777, 11.482818264639777, 11.69687181566044, 11.69687181566044, 11.906283961960796, 11.906283961960796, 12.151929632994989, 12.151929632994989, 12.442078661195602, 12.442078661195602, 12.685614756768384, 12.685614756768384, 12.882246373678006, 12.882246373678006, 13.098033807459965, 13.098033807459965, 13.265644619378074, 13.265644619378074, 13.488205244369283, 13.488205244369283, 13.801786381602861, 13.801786381602861, 14.15661507092392, 14.15661507092392, 14.571319896228996, 14.571319896228996, 14.900498464260913, 14.900498464260913, 15.264447207321453, 15.264447207321453, 15.531123380217505, 15.531123380217505, 15.924513627073946, 15.924513627073946, 16.19019922374802, 16.19019922374802, 16.322098263657374, 16.322098263657374, 16.304174332335062, 16.304174332335062, 16.340241196629936, 16.340241196629936, 16.268904220202955, 16.268904220202955, 16.086253203878236, 16.086253203878236, 15.782468169262778, 15.782468169262778, 15.374958294571538, 15.374958294571538, 15, 15.012940815942004, 15.012940815942004, 14.98636610132836, 14.98636610132836, 14.971810745493599, 14.971810745493599, 14.959082346076983, 14.959082346076983, 14.960947875173133, 14.960947875173133, 14.95565263271521, 14.95565263271521, 14.943059453110807, 14.943059453110807, 14.920042423099233, 14.920042423099233, 14.859798697725925, 14.859798697725925, 14.797521921922066, 14.797521921922066, 14.746699458020705, 14.746699458020705, 14.686175690662845, 14.686175690662845, 14.631471102128723, 14.631471102128723, 14.58023065366825, 14.58023065366825, 14.537568554812667, 14.537568554812667, 14.500231317119468, 14.500231317119468, 14.474722857563513, 14.474722857563513, 14.4220647350196, 14.4220647350196, 14.376180825464203, 14.376180825464203, 14.335464151009303, 14.335464151009303, 14.295170307805137, 14.295170307805137, 14.263049608683579, 14.263049608683579, 14.243626386186193, 14.243626386186193, 14.231930990766053, 14.231930990766053, 14.208866161776603, 14.208866161776603, 14.202879759057403, 14.202879759057403, 14.198542451693676, 14.198542451693676, 14.205568788947831, 14.205568788947831, 14.202391682296767, 14.202391682296767, 14.211179246898407, 14.211179246898407, 14.22809282401728, 14.22809282401728, 14.240716868942075, 14.240716868942075, 14.233201323513999, 14.233201323513999, 14.225227297004473, 14.225227297004473, 14.189429886330164, 14.189429886330164, 14.147165369806896, 14.147165369806896, 14.08333714510193, 14.08333714510193, 14.019069291306938, 14.019069291306938, 13.961481416227368, 13.961481416227368, 13.913958049210835, 13.913958049210835, 13.866151471260338, 13.866151471260338, 13.801817295121142, 13.801817295121142, 13.737042236766802, 13.737042236766802, 13.678767238942457, 13.678767238942457, 13.628052525015123, 13.628052525015123, 13.56643704645608, 13.56643704645608, 13.515035696227566, 13.515035696227566, 13.450876501139497, 13.450876501139497, 13.402818129238593, 13.402818129238593, 13.348944553667687, 13.348944553667687, 13.293373264063145, 13.293373264063145, 13.239891656584982, 13.239891656584982, 13.178310915340727, 13.178310915340727, 13.11914363309317, 13.11914363309317, 13.04834605494057, 13.04834605494057, 12.980008418510142, 12.980008418510142, 12.912100563936535, 12.912100563936535, 12.84548257168026, 12.84548257168026, 12.761653328708682, 12.761653328708682, 12.670680742782599, 12.670680742782599, 12.593746048181327, 12.593746048181327, 12.505966192387636, 12.505966192387636, 12.426975415778585, 12.426975415778585, 12.372987114877688, 12.372987114877688, 12.316124888297376, 12.316124888297376, 12.25624784136798, 12.25624784136798, 12.188780748399955, 12.188780748399955, 12.139029429691613, 12.139029429691613, 12.091613175035052, 12.091613175035052, 12.042152685505714, 12.042152685505714, 11.977247905600317, 11.977247905600317, 11.933433733774168, 11.933433733774168, 11.89504783502318, 11.89504783502318, 11.871147080760428, 11.871147080760428, 11.850217659047976, 11.850217659047976, 11.84192192212905, 11.84192192212905, 11.82311969344896, 11.82311969344896, 11.798468322241224, 11.798468322241224, 11.781618541251447, 11.781618541251447, 11.771189982727265, 11.771189982727265, 11.752590059889691, 11.752590059889691, 11.725074162195554, 11.725074162195554, 11.707552281866988, 11.707552281866988, 11.681614136981478, 11.681614136981478, 11.667586378488018, 11.667586378488018, 11.674231291283325, 11.674231291283325, 11.689501880321215, 11.689501880321215, 11.71312985613572, 11.71312985613572, 11.729541695595978, 11.729541695595978, 11.756346252143663, 11.756346252143663, 11.776821825896544, 11.776821825896544, 11.823144360448932, 11.823144360448932, 11.858480184796978, 11.858480184796978, 11.887381186413212, 11.887381186413212, 11.903274853981108, 11.903274853981108, 11.934053284575308, 11.934053284575308, 11.959946529310686, 11.959946529310686, 11.981458643093886, 11.981458643093886, 11.986109221284174, 11.986109221284174, 11.98062484432249, 11.98062484432249 ], "yaxis": "y" }, { "hovertemplate": "color=5
x=%{x}
y=%{y}", "legendgroup": "5", "line": { "color": "#FFA15A", "dash": "solid" }, "marker": { "symbol": "circle" }, "mode": "lines", "name": "5", "showlegend": true, "type": "scattergl", "x": [ 100, 99.29993160631898, 99.29993160631898, 99.38148169571427, 99.38148169571427, 99.33344287701127, 99.33344287701127, 99.78052429956195, 99.78052429956195, 99.54958970085868, 99.54958970085868, 99.5415288602601, 99.5415288602601, 99.20043010937233, 99.20043010937233, 98.38175972088112, 98.38175972088112, 98.08171337358606, 98.08171337358606, 98.3146135545321, 98.3146135545321, 98.15163483592876, 98.15163483592876, 98.2617316271704, 98.2617316271704, 98.4307104729456, 98.4307104729456, 98.78953357215462, 98.78953357215462, 98.79985727776051, 98.79985727776051, 99.23692266333096, 99.23692266333096, 98.39279376646044, 98.39279376646044, 98.38874784974972, 98.38874784974972, 98.47174801810372, 98.47174801810372, 98.2916973612909, 98.2916973612909, 98.77808827688989, 98.77808827688989, 98.74409721517681, 98.74409721517681, 99.24190042277999, 99.24190042277999, 98.84599456847697, 98.84599456847697, 99.09135177709153, 99.09135177709153, 99.10434894166539, 99.10434894166539, 99.57328874254877, 99.57328874254877, 99.21501237298247, 99.21501237298247, 99.25020700392601, 99.25020700392601, 99.63288351336783, 99.63288351336783, 99.40473856709445, 99.40473856709445, 98.7710291940686, 98.7710291940686, 98.5407493936721, 98.5407493936721, 97.7508566239193, 97.7508566239193, 97.71072647387824, 97.71072647387824, 97.06612114764668, 97.06612114764668, 96.60023270185529, 96.60023270185529, 96.97950519720334, 96.97950519720334, 97.13875284807816, 97.13875284807816, 97.28197178315625, 97.28197178315625, 96.58033571299049, 96.58033571299049, 96.25643172904921, 96.25643172904921, 96.6261400000404, 96.6261400000404, 96.52079469759674, 96.52079469759674, 96.14265950886788, 96.14265950886788, 96.29506225210642, 96.29506225210642, 95.82910831575578, 95.82910831575578, 96.35112441973347, 96.35112441973347, 96.16329269178928, 96.16329269178928, 95.87027246972195, 95.87027246972195, 95.7307727305111, 95.7307727305111, 95.52782525481386, 95.52782525481386, 95.3266966060663, 95.3266966060663, 94.73244989096955, 94.73244989096955, 94.85863986535756, 94.85863986535756, 94.5348526851931, 94.5348526851931, 94.27697635190073, 94.27697635190073, 93.47026915554588, 93.47026915554588, 93.23682795968988, 93.23682795968988, 93.37231139151324, 93.37231139151324, 93.15534439539415, 93.15534439539415, 93.24217287585641, 93.24217287585641, 93.78860723896459, 93.78860723896459, 93.77560714675685, 93.77560714675685, 93.0999726791823, 93.0999726791823, 92.90606801326578, 92.90606801326578, 93.2831221906634, 93.2831221906634, 93.01583352672039, 93.01583352672039, 92.70359835023112, 92.70359835023112, 92.00530036542673, 92.00530036542673, 92.42100834060409, 92.42100834060409, 92.7895835919253, 92.7895835919253, 92.73717490018763, 92.73717490018763, 92.76883196952322, 92.76883196952322, 93.08317487684629, 93.08317487684629, 92.33451766496589, 92.33451766496589, 92.13498897315472, 92.13498897315472, 92.09928886790658, 92.09928886790658, 92.22680948420437, 92.22680948420437, 91.62546599412939, 91.62546599412939, 91.12033628158707, 91.12033628158707, 90.91703470428618, 90.91703470428618, 90.51203613658468, 90.51203613658468, 90.76461607129751, 90.76461607129751, 91.12216656725413, 91.12216656725413, 91.25249379875453, 91.25249379875453, 91.58012004487541, 91.58012004487541, 91.06486472813755, 91.06486472813755, 91.18797649222013, 91.18797649222013, 90.69671638734081, 90.69671638734081, 91.26790712942591, 91.26790712942591, 90.79702047570592, 90.79702047570592, 90.23186056687439, 90.23186056687439, 89.67634735880623, 89.67634735880623, 90.06987166421722, 90.06987166421722, 89.65940405481305, 89.65940405481305, 89.14786912937605, 89.14786912937605, 88.68086196244481, 88.68086196244481, 88.08424380115036, 88.08424380115036, 87.92914636627808, 87.92914636627808, 100, 92.99931606318984, 92.99931606318984, 93.74968330870446, 93.74968330870446, 93.35200242595599, 93.35200242595599, 97.61217815984494, 97.61217815984494, 95.54997817570786, 95.54997817570786, 95.635092884268, 95.635092884268, 92.61880754039443, 92.61880754039443, 85.39231796273906, 85.39231796273906, 83.12912862094319, 83.12912862094319, 85.40561642328275, 85.40561642328275, 84.62039860344953, 84.62039860344953, 86.16474388636449, 86.16474388636449, 88.32785188924211, 88.32785188924211, 92.10765900299248, 92.10765900299248, 93.26077770768009, 93.26077770768009, 97.9845294627281, 97.9845294627281, 91.85128228934461, 91.85128228934461, 92.94825282196534, 92.94825282196534, 94.908060967487, 94.908060967487, 94.71326538271349, 94.71326538271349, 100.13862169564187, 100.13862169564187, 101.27435286478284, 101.27435286478284, 107.18723419784558, 107.18723419784558, 105.11150551338793, 105.11150551338793, 108.89332418604562, 108.89332418604562, 110.45800926706632, 110.45800926706632, 116.48523146511381, 116.48523146511381, 114.1292438507272, 114.1292438507272, 115.6710564645791, 115.6710564645791, 120.72623435030194, 120.72623435030194, 118.93046533906094, 118.93046533906094, 112.25835075871757, 112.25835075871757, 110.00527663324144, 110.00527663324144, 101.43663074912372, 101.43663074912372, 101.02867217786005, 101.02867217786005, 94.33053060847377, 94.33053060847377, 89.75476827975842, 89.75476827975842, 93.29245542951959, 93.29245542951959, 94.9186805787271, 94.9186805787271, 96.46551527277536, 96.46551527277536, 89.87389035969865, 89.87389035969865, 87.16376777592785, 87.16376777592785, 90.71447055509934, 90.71447055509934, 90.19536558085994, 90.19536558085994, 87.37997504032674, 87.37997504032674, 89.23463194487961, 89.23463194487961, 85.88495474723042, 85.88495474723042, 90.91229934650016, 90.91229934650016, 90.15196996137051, 90.15196996137051, 88.67602042222708, 88.67602042222708, 88.50743002514825, 88.50743002514825, 87.96325417167918, 87.96325417167918, 87.47813607760847, 87.47813607760847, 84.01053269460503, 84.01053269460503, 86.21927941269837, 86.21927941269837, 85.20026287932083, 85.20026287932083, 84.74514940369397, 84.74514940369397, 80.44680552355874, 80.44680552355874, 80.41520185078912, 80.41520185078912, 83.13776682112793, 83.13776682112793, 83.62311825579216, 83.62311825579216, 86.27091768763398, 86.27091768763398, 92.29068344923925, 92.29068344923925, 94.59113655600862, 94.59113655600862, 92.23253576603186, 92.23253576603186, 93.36203549432568, 93.36203549432568, 98.80311561440442, 98.80311561440442, 99.52383859763862, 99.52383859763862, 100.02610961464065, 100.02610961464065, 97.48148429129367, 97.48148429129367, 103.34545533154333, 103.34545533154333, 109.43020057074936, 109.43020057074936, 112.12304973808557, 112.12304973808557, 115.52003033279902, 115.52003033279902, 121.55801868602819, 121.55801868602819, 117.08958909341867, 117.08958909341867, 117.75922193520242, 117.75922193520242, 119.85458925018938, 119.85458925018938, 123.66274001251523, 123.66274001251523, 119.15604184133105, 119.15604184133105, 115.53291901293304, 115.53291901293304, 114.89363074478746, 114.89363074478746, 111.82198288405428, 111.82198288405428, 115.87910014654939, 115.87910014654939, 121.11836567425608, 121.11836567425608, 123.6936575690804, 123.6936575690804, 128.58085298226052, 128.58085298226052, 121.95792293344105, 121.95792293344105, 123.60374048079915, 123.60374048079915, 116.48935752258258, 116.48935752258258, 123.55808091733965, 123.55808091733965, 115.82597098962636, 115.82597098962636, 106.77349871746914, 106.77349871746914, 98.16867422379417, 98.16867422379417, 101.74594768140646, 101.74594768140646, 95.1243047124417, 95.1243047124417, 87.65512294066052, 87.65512294066052, 81.34224880318148, 81.34224880318148, 74.25512295493493, 74.25512295493493, 72.08158085400078, 72.08158085400078, 100, 96.49965803159492, 96.49965803159492, 96.89282234085528, 96.89282234085528, 96.66395700156504, 96.66395700156504, 98.84511851049147, 98.84511851049147, 97.72022468264952, 97.72022468264952, 97.69539195252099, 97.69539195252099, 96.04474200505408, 96.04474200505408, 92.12122707795169, 92.12122707795169, 90.7524578823741, 90.7524578823741, 91.86620599866295, 91.86620599866295, 91.18321550679761, 91.18321550679761, 91.77076300242805, 91.77076300242805, 92.64886983215455, 92.64886983215455, 94.4115531951917, 94.4115531951917, 94.60105803410664, 94.60105803410664, 96.77426923210655, 96.77426923210655, 92.95584004241334, 92.95584004241334, 93.0988602155345, 93.0988602155345, 93.66372732853505, 93.66372732853505, 93.03719912084956, 93.03719912084956, 95.452716939988, 95.452716939988, 95.51738150606599, 95.51738150606599, 98.05425788440175, 98.05425788440175, 96.45618107548292, 96.45618107548292, 97.85694974565604, 97.85694974565604, 98.17927424291095, 98.17927424291095, 100.65800191623217, 100.65800191623217, 99.23013457226213, 99.23013457226213, 99.68075990493776, 99.68075990493776, 101.76892968159176, 101.76892968159176, 100.93152794995164, 100.93152794995164, 98.15507445203599, 98.15507445203599, 97.32448920917646, 97.32448920917646, 93.8712393709979, 93.8712393709979, 93.94055110646606, 93.94055110646606, 91.25561322951836, 91.25561322951836, 89.45152914637421, 89.45152914637421, 91.38648456820863, 91.38648456820863, 92.40702828733023, 92.40702828733023, 93.37466906480901, 93.37466906480901, 90.60421743023397, 90.60421743023397, 89.54727537765943, 89.54727537765943, 91.50562818437629, 91.50562818437629, 91.43629555560625, 91.43629555560625, 90.22387819072098, 90.22387819072098, 91.286734506583, 91.286734506583, 89.70792037849891, 89.70792037849891, 92.36523442648821, 92.36523442648821, 92.01299752297405, 92.01299752297405, 91.26989588133198, 91.26989588133198, 91.16338302394053, 91.16338302394053, 90.8266416539283, 90.8266416539283, 90.48973346931841, 90.48973346931841, 88.53135087902336, 88.53135087902336, 89.58435442398849, 89.58435442398849, 88.8253866031861, 88.8253866031861, 88.3389425664917, 88.3389425664917, 85.6690510129246, 85.6690510129246, 85.33734615018504, 85.33734615018504, 86.51603920143914, 86.51603920143914, 86.33828493348129, 86.33828493348129, 87.36304955582791, 87.36304955582791, 90.23284652388249, 90.23284652388249, 90.91718361444943, 90.91718361444943, 88.99242906220593, 88.99242906220593, 88.99938883525597, 88.99938883525597, 91.30743180141197, 91.30743180141197, 91.05295854841216, 91.05295854841216, 90.67174729743687, 90.67174729743687, 88.7604154487307, 88.7604154487307, 91.21667934978741, 91.21667934978741, 93.6338256538187, 93.6338256538187, 94.37558676757705, 94.37558676757705, 95.47321941160612, 95.47321941160612, 97.77075917390104, 97.77075917390104, 95.59282238220855, 95.59282238220855, 95.72059903293992, 95.72059903293992, 96.52854695498216, 96.52854695498216, 98.09563460829936, 98.09563460829936, 96.51532722863074, 96.51532722863074, 95.4085247939158, 95.4085247939158, 95.52465821995634, 95.52465821995634, 94.8087017899729, 94.8087017899729, 96.88999312951138, 96.88999312951138, 99.41181607140739, 99.41181607140739, 101.0349689701463, 101.0349689701463, 103.52291722549926, 103.52291722549926, 102.29402709966891, 102.29402709966891, 103.89599855840412, 103.89599855840412, 102.66305598951656, 102.66305598951656, 106.35128198458621, 106.35128198458621, 105.2153347445648, 105.2153347445648, 103.54761969318548, 103.54761969318548, 101.9104419064554, 101.9104419064554, 104.68762728033715, 104.68762728033715, 103.74561762296544, 103.74561762296544, 102.29177188240789, 102.29177188240789, 100.99065500957371, 100.99065500957371, 99.08829773238939, 99.08829773238939, 99.25050915772879, 99.25050915772879 ], "xaxis": "x", "y": [ 15, 15.0025881631884, 15.0025881631884, 15.001496702185737, 15.001496702185737, 15.002361804039465, 15.002361804039465, 15.003883708196188, 15.003883708196188, 15.00568393679195, 15.00568393679195, 15.007415489103332, 15.007415489103332, 15.007679903819312, 15.007679903819312, 15.00785846437848, 15.00785846437848, 15.005149988731267, 15.005149988731267, 15.003693218370183, 15.003693218370183, 15.003201208353792, 15.003201208353792, 15.001441720795848, 15.001441720795848, 15.000133583406503, 15.000133583406503, 14.998369352308925, 14.998369352308925, 14.996174666815067, 14.996174666815067, 14.994789169151316, 14.994789169151316, 14.99321394632609, 14.99321394632609, 14.990466967358335, 14.990466967358335, 14.98892812664762, 14.98892812664762, 14.987709914471244, 14.987709914471244, 14.987290241379329, 14.987290241379329, 14.985547623238297, 14.985547623238297, 14.986392330287694, 14.986392330287694, 14.9857180023299, 14.9857180023299, 14.984461841594834, 14.984461841594834, 14.985073680988108, 14.985073680988108, 14.985562867120061, 14.985562867120061, 14.98541282187458, 14.98541282187458, 14.984719710317288, 14.984719710317288, 14.985916999281203, 14.985916999281203, 14.98625696832826, 14.98625696832826, 14.986605681348385, 14.986605681348385, 14.985955421994834, 14.985955421994834, 14.986129886338091, 14.986129886338091, 14.984477177626776, 14.984477177626776, 14.981225059271852, 14.981225059271852, 14.976432391666856, 14.976432391666856, 14.973674166171941, 14.973674166171941, 14.96980019046312, 14.96980019046312, 14.966768040636888, 14.966768040636888, 14.962334392385861, 14.962334392385861, 14.957429395595303, 14.957429395595303, 14.953568887352041, 14.953568887352041, 14.948548302693771, 14.948548302693771, 14.945167884771239, 14.945167884771239, 14.940572465174537, 14.940572465174537, 14.936861141832518, 14.936861141832518, 14.931906107640428, 14.931906107640428, 14.927219898398723, 14.927219898398723, 14.921427580941707, 14.921427580941707, 14.91592475619714, 14.91592475619714, 14.910827079437475, 14.910827079437475, 14.90399212146379, 14.90399212146379, 14.897887136036417, 14.897887136036417, 14.891130476962763, 14.891130476962763, 14.883405497521546, 14.883405497521546, 14.876434503668987, 14.876434503668987, 14.870076791929769, 14.870076791929769, 14.862470074033991, 14.862470074033991, 14.853101924486802, 14.853101924486802, 14.845417890954725, 14.845417890954725, 14.834854591138358, 14.834854591138358, 14.82487867160691, 14.82487867160691, 14.817333893722857, 14.817333893722857, 14.80795542406726, 14.80795542406726, 14.799736508431591, 14.799736508431591, 14.789248058469765, 14.789248058469765, 14.7801175136321, 14.7801175136321, 14.77151478230201, 14.77151478230201, 14.762483431482917, 14.762483431482917, 14.75140910811959, 14.75140910811959, 14.742427769315322, 14.742427769315322, 14.731695495637132, 14.731695495637132, 14.723316727651351, 14.723316727651351, 14.714085420344661, 14.714085420344661, 14.705044067153839, 14.705044067153839, 14.695511757105502, 14.695511757105502, 14.684106161453188, 14.684106161453188, 14.673362900138697, 14.673362900138697, 14.662126777303884, 14.662126777303884, 14.650294122378542, 14.650294122378542, 14.637133503588467, 14.637133503588467, 14.625885500549552, 14.625885500549552, 14.613041318879013, 14.613041318879013, 14.600491228516, 14.600491228516, 14.589826301169238, 14.589826301169238, 14.579097284458562, 14.579097284458562, 14.567445029812177, 14.567445029812177, 14.555065538321779, 14.555065538321779, 14.543083171721651, 14.543083171721651, 14.530543871653219, 14.530543871653219, 14.519732090172331, 14.519732090172331, 14.50728664083606, 14.50728664083606, 14.494761059082773, 14.494761059082773, 14.480759862525757, 14.480759862525757, 14.466954078017151, 14.466954078017151, 14.452655312592428, 14.452655312592428, 14.43861439698937, 14.43861439698937, 14.421950182244203, 14.421950182244203, 14.404714317939641, 14.404714317939641, 15, 15.025881631884008, 15.025881631884008, 14.919856780977506, 14.919856780977506, 14.84340539956636, 14.84340539956636, 14.768172517785956, 14.768172517785956, 14.753355341717914, 14.753355341717914, 14.710325587285196, 14.710325587285196, 14.65501286735965, 14.65501286735965, 14.558960244492898, 14.558960244492898, 14.343261540533113, 14.343261540533113, 14.112473629068363, 14.112473629068363, 13.923048492146386, 13.923048492146386, 13.716505105851384, 13.716505105851384, 13.536396160701718, 13.536396160701718, 13.382627368919778, 13.382627368919778, 13.273403497288376, 13.273403497288376, 13.18737339314849, 13.18737339314849, 13.15696932845709, 13.15696932845709, 13.046690159522171, 13.046690159522171, 12.961691639243096, 12.961691639243096, 12.904545878763365, 12.904545878763365, 12.853989386327374, 12.853989386327374, 12.856562555701977, 12.856562555701977, 12.89695026210208, 12.89695026210208, 12.99401382064389, 12.99401382064389, 13.064986472742175, 13.064986472742175, 13.200100005296521, 13.200100005296521, 13.356245186734787, 13.356245186734787, 13.581858258648817, 13.581858258648817, 13.779446331861786, 13.779446331861786, 14.020887197803892, 14.020887197803892, 14.322226633251981, 14.322226633251981, 14.607966995872808, 14.607966995872808, 14.80045909939326, 14.80045909939326, 14.974742020331096, 14.974742020331096, 15.014139514654353, 15.014139514654353, 15.031590488973418, 15.031590488973418, 14.942284460374912, 14.942284460374912, 14.810526845162071, 14.810526845162071, 14.71725604402707, 14.71725604402707, 14.654423668399897, 14.654423668399897, 14.59904128346401, 14.59904128346401, 14.452865602940358, 14.452865602940358, 14.282261478879674, 14.282261478879674, 14.149772009038367, 14.149772009038367, 14.027052069983485, 14.027052069983485, 13.859992607077059, 13.859992607077059, 13.726038665079807, 13.726038665079807, 13.542762810472052, 13.542762810472052, 13.426206655218582, 13.426206655218582, 13.293233924236567, 13.293233924236567, 13.147791616712704, 13.147791616712704, 13.006610763951292, 13.006610763951292, 12.84823986731333, 12.84823986731333, 12.693804885133208, 12.693804885133208, 12.498890192871052, 12.498890192871052, 12.325809989121367, 12.325809989121367, 12.151607078337484, 12.151607078337484, 11.98176127509246, 11.98176127509246, 11.761719359770526, 11.761719359770526, 11.535738338854555, 11.535738338854555, 11.356031924588308, 11.356031924588308, 11.166858150706151, 11.166858150706151, 11.013537609868145, 11.013537609868145, 10.940785833361874, 10.940785833361874, 10.880470893076224, 10.880470893076224, 10.810492031684296, 10.810492031684296, 10.738828174758915, 10.738828174758915, 10.732227365833888, 10.732227365833888, 10.74063259552893, 10.74063259552893, 10.754970118090359, 10.754970118090359, 10.733785904628672, 10.733785904628672, 10.787976887758164, 10.787976887758164, 10.88944458640169, 10.88944458640169, 11.04254907916619, 11.04254907916619, 11.228202407568958, 11.228202407568958, 11.482818264639777, 11.482818264639777, 11.69687181566044, 11.69687181566044, 11.906283961960796, 11.906283961960796, 12.151929632994989, 12.151929632994989, 12.442078661195602, 12.442078661195602, 12.685614756768384, 12.685614756768384, 12.882246373678006, 12.882246373678006, 13.098033807459965, 13.098033807459965, 13.265644619378074, 13.265644619378074, 13.488205244369283, 13.488205244369283, 13.801786381602861, 13.801786381602861, 14.15661507092392, 14.15661507092392, 14.571319896228996, 14.571319896228996, 14.900498464260913, 14.900498464260913, 15.264447207321453, 15.264447207321453, 15.531123380217505, 15.531123380217505, 15.924513627073946, 15.924513627073946, 16.19019922374802, 16.19019922374802, 16.322098263657374, 16.322098263657374, 16.304174332335062, 16.304174332335062, 16.340241196629936, 16.340241196629936, 16.268904220202955, 16.268904220202955, 16.086253203878236, 16.086253203878236, 15.782468169262778, 15.782468169262778, 15.374958294571538, 15.374958294571538, 15, 15.012940815942004, 15.012940815942004, 14.98636610132836, 14.98636610132836, 14.971810745493599, 14.971810745493599, 14.959082346076983, 14.959082346076983, 14.960947875173133, 14.960947875173133, 14.95565263271521, 14.95565263271521, 14.943059453110807, 14.943059453110807, 14.920042423099233, 14.920042423099233, 14.859798697725925, 14.859798697725925, 14.797521921922066, 14.797521921922066, 14.746699458020705, 14.746699458020705, 14.686175690662845, 14.686175690662845, 14.631471102128723, 14.631471102128723, 14.58023065366825, 14.58023065366825, 14.537568554812667, 14.537568554812667, 14.500231317119468, 14.500231317119468, 14.474722857563513, 14.474722857563513, 14.4220647350196, 14.4220647350196, 14.376180825464203, 14.376180825464203, 14.335464151009303, 14.335464151009303, 14.295170307805137, 14.295170307805137, 14.263049608683579, 14.263049608683579, 14.243626386186193, 14.243626386186193, 14.231930990766053, 14.231930990766053, 14.208866161776603, 14.208866161776603, 14.202879759057403, 14.202879759057403, 14.198542451693676, 14.198542451693676, 14.205568788947831, 14.205568788947831, 14.202391682296767, 14.202391682296767, 14.211179246898407, 14.211179246898407, 14.22809282401728, 14.22809282401728, 14.240716868942075, 14.240716868942075, 14.233201323513999, 14.233201323513999, 14.225227297004473, 14.225227297004473, 14.189429886330164, 14.189429886330164, 14.147165369806896, 14.147165369806896, 14.08333714510193, 14.08333714510193, 14.019069291306938, 14.019069291306938, 13.961481416227368, 13.961481416227368, 13.913958049210835, 13.913958049210835, 13.866151471260338, 13.866151471260338, 13.801817295121142, 13.801817295121142, 13.737042236766802, 13.737042236766802, 13.678767238942457, 13.678767238942457, 13.628052525015123, 13.628052525015123, 13.56643704645608, 13.56643704645608, 13.515035696227566, 13.515035696227566, 13.450876501139497, 13.450876501139497, 13.402818129238593, 13.402818129238593, 13.348944553667687, 13.348944553667687, 13.293373264063145, 13.293373264063145, 13.239891656584982, 13.239891656584982, 13.178310915340727, 13.178310915340727, 13.11914363309317, 13.11914363309317, 13.04834605494057, 13.04834605494057, 12.980008418510142, 12.980008418510142, 12.912100563936535, 12.912100563936535, 12.84548257168026, 12.84548257168026, 12.761653328708682, 12.761653328708682, 12.670680742782599, 12.670680742782599, 12.593746048181327, 12.593746048181327, 12.505966192387636, 12.505966192387636, 12.426975415778585, 12.426975415778585, 12.372987114877688, 12.372987114877688, 12.316124888297376, 12.316124888297376, 12.25624784136798, 12.25624784136798, 12.188780748399955, 12.188780748399955, 12.139029429691613, 12.139029429691613, 12.091613175035052, 12.091613175035052, 12.042152685505714, 12.042152685505714, 11.977247905600317, 11.977247905600317, 11.933433733774168, 11.933433733774168, 11.89504783502318, 11.89504783502318, 11.871147080760428, 11.871147080760428, 11.850217659047976, 11.850217659047976, 11.84192192212905, 11.84192192212905, 11.82311969344896, 11.82311969344896, 11.798468322241224, 11.798468322241224, 11.781618541251447, 11.781618541251447, 11.771189982727265, 11.771189982727265, 11.752590059889691, 11.752590059889691, 11.725074162195554, 11.725074162195554, 11.707552281866988, 11.707552281866988, 11.681614136981478, 11.681614136981478, 11.667586378488018, 11.667586378488018, 11.674231291283325, 11.674231291283325, 11.689501880321215, 11.689501880321215, 11.71312985613572, 11.71312985613572, 11.729541695595978, 11.729541695595978, 11.756346252143663, 11.756346252143663, 11.776821825896544, 11.776821825896544, 11.823144360448932, 11.823144360448932, 11.858480184796978, 11.858480184796978, 11.887381186413212, 11.887381186413212, 11.903274853981108, 11.903274853981108, 11.934053284575308, 11.934053284575308, 11.959946529310686, 11.959946529310686, 11.981458643093886, 11.981458643093886, 11.986109221284174, 11.986109221284174, 11.98062484432249, 11.98062484432249 ], "yaxis": "y" }, { "hovertemplate": "color=6
x=%{x}
y=%{y}", "legendgroup": "6", "line": { "color": "#19d3f3", "dash": "solid" }, "marker": { "symbol": "circle" }, "mode": "lines", "name": "6", "showlegend": true, "type": "scattergl", "x": [ 100, 99.29993160631898, 99.29993160631898, 99.38148169571427, 99.38148169571427, 99.33344287701127, 99.33344287701127, 99.78052429956195, 99.78052429956195, 99.54958970085868, 99.54958970085868, 99.5415288602601, 99.5415288602601, 99.20043010937233, 99.20043010937233, 98.38175972088112, 98.38175972088112, 98.08171337358606, 98.08171337358606, 98.3146135545321, 98.3146135545321, 98.15163483592876, 98.15163483592876, 98.2617316271704, 98.2617316271704, 98.4307104729456, 98.4307104729456, 98.78953357215462, 98.78953357215462, 98.79985727776051, 98.79985727776051, 99.23692266333096, 99.23692266333096, 98.39279376646044, 98.39279376646044, 98.38874784974972, 98.38874784974972, 98.47174801810372, 98.47174801810372, 98.2916973612909, 98.2916973612909, 98.77808827688989, 98.77808827688989, 98.74409721517681, 98.74409721517681, 99.24190042277999, 99.24190042277999, 98.84599456847697, 98.84599456847697, 99.09135177709153, 99.09135177709153, 99.10434894166539, 99.10434894166539, 99.57328874254877, 99.57328874254877, 99.21501237298247, 99.21501237298247, 99.25020700392601, 99.25020700392601, 99.63288351336783, 99.63288351336783, 99.40473856709445, 99.40473856709445, 98.7710291940686, 98.7710291940686, 98.5407493936721, 98.5407493936721, 97.7508566239193, 97.7508566239193, 97.71072647387824, 97.71072647387824, 97.06612114764668, 97.06612114764668, 96.60023270185529, 96.60023270185529, 96.97950519720334, 96.97950519720334, 97.13875284807816, 97.13875284807816, 97.28197178315625, 97.28197178315625, 96.58033571299049, 96.58033571299049, 96.25643172904921, 96.25643172904921, 96.6261400000404, 96.6261400000404, 96.52079469759674, 96.52079469759674, 96.14265950886788, 96.14265950886788, 96.29506225210642, 96.29506225210642, 95.82910831575578, 95.82910831575578, 96.35112441973347, 96.35112441973347, 96.16329269178928, 96.16329269178928, 95.87027246972195, 95.87027246972195, 95.7307727305111, 95.7307727305111, 95.52782525481386, 95.52782525481386, 95.3266966060663, 95.3266966060663, 94.73244989096955, 94.73244989096955, 94.85863986535756, 94.85863986535756, 94.5348526851931, 94.5348526851931, 94.27697635190073, 94.27697635190073, 93.47026915554588, 93.47026915554588, 93.23682795968988, 93.23682795968988, 93.37231139151324, 93.37231139151324, 93.15534439539415, 93.15534439539415, 93.24217287585641, 93.24217287585641, 93.78860723896459, 93.78860723896459, 93.77560714675685, 93.77560714675685, 93.0999726791823, 93.0999726791823, 92.90606801326578, 92.90606801326578, 93.2831221906634, 93.2831221906634, 93.01583352672039, 93.01583352672039, 92.70359835023112, 92.70359835023112, 92.00530036542673, 92.00530036542673, 92.42100834060409, 92.42100834060409, 92.7895835919253, 92.7895835919253, 92.73717490018763, 92.73717490018763, 92.76883196952322, 92.76883196952322, 93.08317487684629, 93.08317487684629, 92.33451766496589, 92.33451766496589, 92.13498897315472, 92.13498897315472, 92.09928886790658, 92.09928886790658, 92.22680948420437, 92.22680948420437, 91.62546599412939, 91.62546599412939, 91.12033628158707, 91.12033628158707, 90.91703470428618, 90.91703470428618, 90.51203613658468, 90.51203613658468, 90.76461607129751, 90.76461607129751, 91.12216656725413, 91.12216656725413, 91.25249379875453, 91.25249379875453, 91.58012004487541, 91.58012004487541, 91.06486472813755, 91.06486472813755, 91.18797649222013, 91.18797649222013, 90.69671638734081, 90.69671638734081, 91.26790712942591, 91.26790712942591, 90.79702047570592, 90.79702047570592, 90.23186056687439, 90.23186056687439, 89.67634735880623, 89.67634735880623, 90.06987166421722, 90.06987166421722, 89.65940405481305, 89.65940405481305, 89.14786912937605, 89.14786912937605, 88.68086196244481, 88.68086196244481, 88.08424380115036, 88.08424380115036, 87.92914636627808, 87.92914636627808, 100, 92.99931606318984, 92.99931606318984, 93.74968330870446, 93.74968330870446, 93.35200242595599, 93.35200242595599, 97.61217815984494, 97.61217815984494, 95.54997817570786, 95.54997817570786, 95.635092884268, 95.635092884268, 92.61880754039443, 92.61880754039443, 85.39231796273906, 85.39231796273906, 83.12912862094319, 83.12912862094319, 85.40561642328275, 85.40561642328275, 84.62039860344953, 84.62039860344953, 86.16474388636449, 86.16474388636449, 88.32785188924211, 88.32785188924211, 92.10765900299248, 92.10765900299248, 93.26077770768009, 93.26077770768009, 97.9845294627281, 97.9845294627281, 91.85128228934461, 91.85128228934461, 92.94825282196534, 92.94825282196534, 94.908060967487, 94.908060967487, 94.71326538271349, 94.71326538271349, 100.13862169564187, 100.13862169564187, 101.27435286478284, 101.27435286478284, 107.18723419784558, 107.18723419784558, 105.11150551338793, 105.11150551338793, 108.89332418604562, 108.89332418604562, 110.45800926706632, 110.45800926706632, 116.48523146511381, 116.48523146511381, 114.1292438507272, 114.1292438507272, 115.6710564645791, 115.6710564645791, 120.72623435030194, 120.72623435030194, 118.93046533906094, 118.93046533906094, 112.25835075871757, 112.25835075871757, 110.00527663324144, 110.00527663324144, 101.43663074912372, 101.43663074912372, 101.02867217786005, 101.02867217786005, 94.33053060847377, 94.33053060847377, 89.75476827975842, 89.75476827975842, 93.29245542951959, 93.29245542951959, 94.9186805787271, 94.9186805787271, 96.46551527277536, 96.46551527277536, 89.87389035969865, 89.87389035969865, 87.16376777592785, 87.16376777592785, 90.71447055509934, 90.71447055509934, 90.19536558085994, 90.19536558085994, 87.37997504032674, 87.37997504032674, 89.23463194487961, 89.23463194487961, 85.88495474723042, 85.88495474723042, 90.91229934650016, 90.91229934650016, 90.15196996137051, 90.15196996137051, 88.67602042222708, 88.67602042222708, 88.50743002514825, 88.50743002514825, 87.96325417167918, 87.96325417167918, 87.47813607760847, 87.47813607760847, 84.01053269460503, 84.01053269460503, 86.21927941269837, 86.21927941269837, 85.20026287932083, 85.20026287932083, 84.74514940369397, 84.74514940369397, 80.44680552355874, 80.44680552355874, 80.41520185078912, 80.41520185078912, 83.13776682112793, 83.13776682112793, 83.62311825579216, 83.62311825579216, 86.27091768763398, 86.27091768763398, 92.29068344923925, 92.29068344923925, 94.59113655600862, 94.59113655600862, 92.23253576603186, 92.23253576603186, 93.36203549432568, 93.36203549432568, 98.80311561440442, 98.80311561440442, 99.52383859763862, 99.52383859763862, 100.02610961464065, 100.02610961464065, 97.48148429129367, 97.48148429129367, 103.34545533154333, 103.34545533154333, 109.43020057074936, 109.43020057074936, 112.12304973808557, 112.12304973808557, 115.52003033279902, 115.52003033279902, 121.55801868602819, 121.55801868602819, 117.08958909341867, 117.08958909341867, 117.75922193520242, 117.75922193520242, 119.85458925018938, 119.85458925018938, 123.66274001251523, 123.66274001251523, 119.15604184133105, 119.15604184133105, 115.53291901293304, 115.53291901293304, 114.89363074478746, 114.89363074478746, 111.82198288405428, 111.82198288405428, 115.87910014654939, 115.87910014654939, 121.11836567425608, 121.11836567425608, 123.6936575690804, 123.6936575690804, 128.58085298226052, 128.58085298226052, 121.95792293344105, 121.95792293344105, 123.60374048079915, 123.60374048079915, 116.48935752258258, 116.48935752258258, 123.55808091733965, 123.55808091733965, 115.82597098962636, 115.82597098962636, 106.77349871746914, 106.77349871746914, 98.16867422379417, 98.16867422379417, 101.74594768140646, 101.74594768140646, 95.1243047124417, 95.1243047124417, 87.65512294066052, 87.65512294066052, 81.34224880318148, 81.34224880318148, 74.25512295493493, 74.25512295493493, 72.08158085400078, 72.08158085400078, 100, 96.49965803159492, 96.49965803159492, 96.89282234085528, 96.89282234085528, 96.66395700156504, 96.66395700156504, 98.84511851049147, 98.84511851049147, 97.72022468264952, 97.72022468264952, 97.69539195252099, 97.69539195252099, 96.04474200505408, 96.04474200505408, 92.12122707795169, 92.12122707795169, 90.7524578823741, 90.7524578823741, 91.86620599866295, 91.86620599866295, 91.18321550679761, 91.18321550679761, 91.77076300242805, 91.77076300242805, 92.64886983215455, 92.64886983215455, 94.4115531951917, 94.4115531951917, 94.60105803410664, 94.60105803410664, 96.77426923210655, 96.77426923210655, 92.95584004241334, 92.95584004241334, 93.0988602155345, 93.0988602155345, 93.66372732853505, 93.66372732853505, 93.03719912084956, 93.03719912084956, 95.452716939988, 95.452716939988, 95.51738150606599, 95.51738150606599, 98.05425788440175, 98.05425788440175, 96.45618107548292, 96.45618107548292, 97.85694974565604, 97.85694974565604, 98.17927424291095, 98.17927424291095, 100.65800191623217, 100.65800191623217, 99.23013457226213, 99.23013457226213, 99.68075990493776, 99.68075990493776, 101.76892968159176, 101.76892968159176, 100.93152794995164, 100.93152794995164, 98.15507445203599, 98.15507445203599, 97.32448920917646, 97.32448920917646, 93.8712393709979, 93.8712393709979, 93.94055110646606, 93.94055110646606, 91.25561322951836, 91.25561322951836, 89.45152914637421, 89.45152914637421, 91.38648456820863, 91.38648456820863, 92.40702828733023, 92.40702828733023, 93.37466906480901, 93.37466906480901, 90.60421743023397, 90.60421743023397, 89.54727537765943, 89.54727537765943, 91.50562818437629, 91.50562818437629, 91.43629555560625, 91.43629555560625, 90.22387819072098, 90.22387819072098, 91.286734506583, 91.286734506583, 89.70792037849891, 89.70792037849891, 92.36523442648821, 92.36523442648821, 92.01299752297405, 92.01299752297405, 91.26989588133198, 91.26989588133198, 91.16338302394053, 91.16338302394053, 90.8266416539283, 90.8266416539283, 90.48973346931841, 90.48973346931841, 88.53135087902336, 88.53135087902336, 89.58435442398849, 89.58435442398849, 88.8253866031861, 88.8253866031861, 88.3389425664917, 88.3389425664917, 85.6690510129246, 85.6690510129246, 85.33734615018504, 85.33734615018504, 86.51603920143914, 86.51603920143914, 86.33828493348129, 86.33828493348129, 87.36304955582791, 87.36304955582791, 90.23284652388249, 90.23284652388249, 90.91718361444943, 90.91718361444943, 88.99242906220593, 88.99242906220593, 88.99938883525597, 88.99938883525597, 91.30743180141197, 91.30743180141197, 91.05295854841216, 91.05295854841216, 90.67174729743687, 90.67174729743687, 88.7604154487307, 88.7604154487307, 91.21667934978741, 91.21667934978741, 93.6338256538187, 93.6338256538187, 94.37558676757705, 94.37558676757705, 95.47321941160612, 95.47321941160612, 97.77075917390104, 97.77075917390104, 95.59282238220855, 95.59282238220855, 95.72059903293992, 95.72059903293992, 96.52854695498216, 96.52854695498216, 98.09563460829936, 98.09563460829936, 96.51532722863074, 96.51532722863074, 95.4085247939158, 95.4085247939158, 95.52465821995634, 95.52465821995634, 94.8087017899729, 94.8087017899729, 96.88999312951138, 96.88999312951138, 99.41181607140739, 99.41181607140739, 101.0349689701463, 101.0349689701463, 103.52291722549926, 103.52291722549926, 102.29402709966891, 102.29402709966891, 103.89599855840412, 103.89599855840412, 102.66305598951656, 102.66305598951656, 106.35128198458621, 106.35128198458621, 105.2153347445648, 105.2153347445648, 103.54761969318548, 103.54761969318548, 101.9104419064554, 101.9104419064554, 104.68762728033715, 104.68762728033715, 103.74561762296544, 103.74561762296544, 102.29177188240789, 102.29177188240789, 100.99065500957371, 100.99065500957371, 99.08829773238939, 99.08829773238939, 99.25050915772879, 99.25050915772879 ], "xaxis": "x", "y": [ 15, 15.0025881631884, 15.0025881631884, 15.001496702185737, 15.001496702185737, 15.002361804039465, 15.002361804039465, 15.003883708196188, 15.003883708196188, 15.00568393679195, 15.00568393679195, 15.007415489103332, 15.007415489103332, 15.007679903819312, 15.007679903819312, 15.00785846437848, 15.00785846437848, 15.005149988731267, 15.005149988731267, 15.003693218370183, 15.003693218370183, 15.003201208353792, 15.003201208353792, 15.001441720795848, 15.001441720795848, 15.000133583406503, 15.000133583406503, 14.998369352308925, 14.998369352308925, 14.996174666815067, 14.996174666815067, 14.994789169151316, 14.994789169151316, 14.99321394632609, 14.99321394632609, 14.990466967358335, 14.990466967358335, 14.98892812664762, 14.98892812664762, 14.987709914471244, 14.987709914471244, 14.987290241379329, 14.987290241379329, 14.985547623238297, 14.985547623238297, 14.986392330287694, 14.986392330287694, 14.9857180023299, 14.9857180023299, 14.984461841594834, 14.984461841594834, 14.985073680988108, 14.985073680988108, 14.985562867120061, 14.985562867120061, 14.98541282187458, 14.98541282187458, 14.984719710317288, 14.984719710317288, 14.985916999281203, 14.985916999281203, 14.98625696832826, 14.98625696832826, 14.986605681348385, 14.986605681348385, 14.985955421994834, 14.985955421994834, 14.986129886338091, 14.986129886338091, 14.984477177626776, 14.984477177626776, 14.981225059271852, 14.981225059271852, 14.976432391666856, 14.976432391666856, 14.973674166171941, 14.973674166171941, 14.96980019046312, 14.96980019046312, 14.966768040636888, 14.966768040636888, 14.962334392385861, 14.962334392385861, 14.957429395595303, 14.957429395595303, 14.953568887352041, 14.953568887352041, 14.948548302693771, 14.948548302693771, 14.945167884771239, 14.945167884771239, 14.940572465174537, 14.940572465174537, 14.936861141832518, 14.936861141832518, 14.931906107640428, 14.931906107640428, 14.927219898398723, 14.927219898398723, 14.921427580941707, 14.921427580941707, 14.91592475619714, 14.91592475619714, 14.910827079437475, 14.910827079437475, 14.90399212146379, 14.90399212146379, 14.897887136036417, 14.897887136036417, 14.891130476962763, 14.891130476962763, 14.883405497521546, 14.883405497521546, 14.876434503668987, 14.876434503668987, 14.870076791929769, 14.870076791929769, 14.862470074033991, 14.862470074033991, 14.853101924486802, 14.853101924486802, 14.845417890954725, 14.845417890954725, 14.834854591138358, 14.834854591138358, 14.82487867160691, 14.82487867160691, 14.817333893722857, 14.817333893722857, 14.80795542406726, 14.80795542406726, 14.799736508431591, 14.799736508431591, 14.789248058469765, 14.789248058469765, 14.7801175136321, 14.7801175136321, 14.77151478230201, 14.77151478230201, 14.762483431482917, 14.762483431482917, 14.75140910811959, 14.75140910811959, 14.742427769315322, 14.742427769315322, 14.731695495637132, 14.731695495637132, 14.723316727651351, 14.723316727651351, 14.714085420344661, 14.714085420344661, 14.705044067153839, 14.705044067153839, 14.695511757105502, 14.695511757105502, 14.684106161453188, 14.684106161453188, 14.673362900138697, 14.673362900138697, 14.662126777303884, 14.662126777303884, 14.650294122378542, 14.650294122378542, 14.637133503588467, 14.637133503588467, 14.625885500549552, 14.625885500549552, 14.613041318879013, 14.613041318879013, 14.600491228516, 14.600491228516, 14.589826301169238, 14.589826301169238, 14.579097284458562, 14.579097284458562, 14.567445029812177, 14.567445029812177, 14.555065538321779, 14.555065538321779, 14.543083171721651, 14.543083171721651, 14.530543871653219, 14.530543871653219, 14.519732090172331, 14.519732090172331, 14.50728664083606, 14.50728664083606, 14.494761059082773, 14.494761059082773, 14.480759862525757, 14.480759862525757, 14.466954078017151, 14.466954078017151, 14.452655312592428, 14.452655312592428, 14.43861439698937, 14.43861439698937, 14.421950182244203, 14.421950182244203, 14.404714317939641, 14.404714317939641, 15, 15.025881631884008, 15.025881631884008, 14.919856780977506, 14.919856780977506, 14.84340539956636, 14.84340539956636, 14.768172517785956, 14.768172517785956, 14.753355341717914, 14.753355341717914, 14.710325587285196, 14.710325587285196, 14.65501286735965, 14.65501286735965, 14.558960244492898, 14.558960244492898, 14.343261540533113, 14.343261540533113, 14.112473629068363, 14.112473629068363, 13.923048492146386, 13.923048492146386, 13.716505105851384, 13.716505105851384, 13.536396160701718, 13.536396160701718, 13.382627368919778, 13.382627368919778, 13.273403497288376, 13.273403497288376, 13.18737339314849, 13.18737339314849, 13.15696932845709, 13.15696932845709, 13.046690159522171, 13.046690159522171, 12.961691639243096, 12.961691639243096, 12.904545878763365, 12.904545878763365, 12.853989386327374, 12.853989386327374, 12.856562555701977, 12.856562555701977, 12.89695026210208, 12.89695026210208, 12.99401382064389, 12.99401382064389, 13.064986472742175, 13.064986472742175, 13.200100005296521, 13.200100005296521, 13.356245186734787, 13.356245186734787, 13.581858258648817, 13.581858258648817, 13.779446331861786, 13.779446331861786, 14.020887197803892, 14.020887197803892, 14.322226633251981, 14.322226633251981, 14.607966995872808, 14.607966995872808, 14.80045909939326, 14.80045909939326, 14.974742020331096, 14.974742020331096, 15.014139514654353, 15.014139514654353, 15.031590488973418, 15.031590488973418, 14.942284460374912, 14.942284460374912, 14.810526845162071, 14.810526845162071, 14.71725604402707, 14.71725604402707, 14.654423668399897, 14.654423668399897, 14.59904128346401, 14.59904128346401, 14.452865602940358, 14.452865602940358, 14.282261478879674, 14.282261478879674, 14.149772009038367, 14.149772009038367, 14.027052069983485, 14.027052069983485, 13.859992607077059, 13.859992607077059, 13.726038665079807, 13.726038665079807, 13.542762810472052, 13.542762810472052, 13.426206655218582, 13.426206655218582, 13.293233924236567, 13.293233924236567, 13.147791616712704, 13.147791616712704, 13.006610763951292, 13.006610763951292, 12.84823986731333, 12.84823986731333, 12.693804885133208, 12.693804885133208, 12.498890192871052, 12.498890192871052, 12.325809989121367, 12.325809989121367, 12.151607078337484, 12.151607078337484, 11.98176127509246, 11.98176127509246, 11.761719359770526, 11.761719359770526, 11.535738338854555, 11.535738338854555, 11.356031924588308, 11.356031924588308, 11.166858150706151, 11.166858150706151, 11.013537609868145, 11.013537609868145, 10.940785833361874, 10.940785833361874, 10.880470893076224, 10.880470893076224, 10.810492031684296, 10.810492031684296, 10.738828174758915, 10.738828174758915, 10.732227365833888, 10.732227365833888, 10.74063259552893, 10.74063259552893, 10.754970118090359, 10.754970118090359, 10.733785904628672, 10.733785904628672, 10.787976887758164, 10.787976887758164, 10.88944458640169, 10.88944458640169, 11.04254907916619, 11.04254907916619, 11.228202407568958, 11.228202407568958, 11.482818264639777, 11.482818264639777, 11.69687181566044, 11.69687181566044, 11.906283961960796, 11.906283961960796, 12.151929632994989, 12.151929632994989, 12.442078661195602, 12.442078661195602, 12.685614756768384, 12.685614756768384, 12.882246373678006, 12.882246373678006, 13.098033807459965, 13.098033807459965, 13.265644619378074, 13.265644619378074, 13.488205244369283, 13.488205244369283, 13.801786381602861, 13.801786381602861, 14.15661507092392, 14.15661507092392, 14.571319896228996, 14.571319896228996, 14.900498464260913, 14.900498464260913, 15.264447207321453, 15.264447207321453, 15.531123380217505, 15.531123380217505, 15.924513627073946, 15.924513627073946, 16.19019922374802, 16.19019922374802, 16.322098263657374, 16.322098263657374, 16.304174332335062, 16.304174332335062, 16.340241196629936, 16.340241196629936, 16.268904220202955, 16.268904220202955, 16.086253203878236, 16.086253203878236, 15.782468169262778, 15.782468169262778, 15.374958294571538, 15.374958294571538, 15, 15.012940815942004, 15.012940815942004, 14.98636610132836, 14.98636610132836, 14.971810745493599, 14.971810745493599, 14.959082346076983, 14.959082346076983, 14.960947875173133, 14.960947875173133, 14.95565263271521, 14.95565263271521, 14.943059453110807, 14.943059453110807, 14.920042423099233, 14.920042423099233, 14.859798697725925, 14.859798697725925, 14.797521921922066, 14.797521921922066, 14.746699458020705, 14.746699458020705, 14.686175690662845, 14.686175690662845, 14.631471102128723, 14.631471102128723, 14.58023065366825, 14.58023065366825, 14.537568554812667, 14.537568554812667, 14.500231317119468, 14.500231317119468, 14.474722857563513, 14.474722857563513, 14.4220647350196, 14.4220647350196, 14.376180825464203, 14.376180825464203, 14.335464151009303, 14.335464151009303, 14.295170307805137, 14.295170307805137, 14.263049608683579, 14.263049608683579, 14.243626386186193, 14.243626386186193, 14.231930990766053, 14.231930990766053, 14.208866161776603, 14.208866161776603, 14.202879759057403, 14.202879759057403, 14.198542451693676, 14.198542451693676, 14.205568788947831, 14.205568788947831, 14.202391682296767, 14.202391682296767, 14.211179246898407, 14.211179246898407, 14.22809282401728, 14.22809282401728, 14.240716868942075, 14.240716868942075, 14.233201323513999, 14.233201323513999, 14.225227297004473, 14.225227297004473, 14.189429886330164, 14.189429886330164, 14.147165369806896, 14.147165369806896, 14.08333714510193, 14.08333714510193, 14.019069291306938, 14.019069291306938, 13.961481416227368, 13.961481416227368, 13.913958049210835, 13.913958049210835, 13.866151471260338, 13.866151471260338, 13.801817295121142, 13.801817295121142, 13.737042236766802, 13.737042236766802, 13.678767238942457, 13.678767238942457, 13.628052525015123, 13.628052525015123, 13.56643704645608, 13.56643704645608, 13.515035696227566, 13.515035696227566, 13.450876501139497, 13.450876501139497, 13.402818129238593, 13.402818129238593, 13.348944553667687, 13.348944553667687, 13.293373264063145, 13.293373264063145, 13.239891656584982, 13.239891656584982, 13.178310915340727, 13.178310915340727, 13.11914363309317, 13.11914363309317, 13.04834605494057, 13.04834605494057, 12.980008418510142, 12.980008418510142, 12.912100563936535, 12.912100563936535, 12.84548257168026, 12.84548257168026, 12.761653328708682, 12.761653328708682, 12.670680742782599, 12.670680742782599, 12.593746048181327, 12.593746048181327, 12.505966192387636, 12.505966192387636, 12.426975415778585, 12.426975415778585, 12.372987114877688, 12.372987114877688, 12.316124888297376, 12.316124888297376, 12.25624784136798, 12.25624784136798, 12.188780748399955, 12.188780748399955, 12.139029429691613, 12.139029429691613, 12.091613175035052, 12.091613175035052, 12.042152685505714, 12.042152685505714, 11.977247905600317, 11.977247905600317, 11.933433733774168, 11.933433733774168, 11.89504783502318, 11.89504783502318, 11.871147080760428, 11.871147080760428, 11.850217659047976, 11.850217659047976, 11.84192192212905, 11.84192192212905, 11.82311969344896, 11.82311969344896, 11.798468322241224, 11.798468322241224, 11.781618541251447, 11.781618541251447, 11.771189982727265, 11.771189982727265, 11.752590059889691, 11.752590059889691, 11.725074162195554, 11.725074162195554, 11.707552281866988, 11.707552281866988, 11.681614136981478, 11.681614136981478, 11.667586378488018, 11.667586378488018, 11.674231291283325, 11.674231291283325, 11.689501880321215, 11.689501880321215, 11.71312985613572, 11.71312985613572, 11.729541695595978, 11.729541695595978, 11.756346252143663, 11.756346252143663, 11.776821825896544, 11.776821825896544, 11.823144360448932, 11.823144360448932, 11.858480184796978, 11.858480184796978, 11.887381186413212, 11.887381186413212, 11.903274853981108, 11.903274853981108, 11.934053284575308, 11.934053284575308, 11.959946529310686, 11.959946529310686, 11.981458643093886, 11.981458643093886, 11.986109221284174, 11.986109221284174, 11.98062484432249, 11.98062484432249 ], "yaxis": "y" }, { "hovertemplate": "color=7
x=%{x}
y=%{y}", "legendgroup": "7", "line": { "color": "#FF6692", "dash": "solid" }, "marker": { "symbol": "circle" }, "mode": "lines", "name": "7", "showlegend": true, "type": "scattergl", "x": [ 100, 99.29993160631898, 99.29993160631898, 99.38148169571427, 99.38148169571427, 99.33344287701127, 99.33344287701127, 99.78052429956195, 99.78052429956195, 99.54958970085868, 99.54958970085868, 99.5415288602601, 99.5415288602601, 99.20043010937233, 99.20043010937233, 98.38175972088112, 98.38175972088112, 98.08171337358606, 98.08171337358606, 98.3146135545321, 98.3146135545321, 98.15163483592876, 98.15163483592876, 98.2617316271704, 98.2617316271704, 98.4307104729456, 98.4307104729456, 98.78953357215462, 98.78953357215462, 98.79985727776051, 98.79985727776051, 99.23692266333096, 99.23692266333096, 98.39279376646044, 98.39279376646044, 98.38874784974972, 98.38874784974972, 98.47174801810372, 98.47174801810372, 98.2916973612909, 98.2916973612909, 98.77808827688989, 98.77808827688989, 98.74409721517681, 98.74409721517681, 99.24190042277999, 99.24190042277999, 98.84599456847697, 98.84599456847697, 99.09135177709153, 99.09135177709153, 99.10434894166539, 99.10434894166539, 99.57328874254877, 99.57328874254877, 99.21501237298247, 99.21501237298247, 99.25020700392601, 99.25020700392601, 99.63288351336783, 99.63288351336783, 99.40473856709445, 99.40473856709445, 98.7710291940686, 98.7710291940686, 98.5407493936721, 98.5407493936721, 97.7508566239193, 97.7508566239193, 97.71072647387824, 97.71072647387824, 97.06612114764668, 97.06612114764668, 96.60023270185529, 96.60023270185529, 96.97950519720334, 96.97950519720334, 97.13875284807816, 97.13875284807816, 97.28197178315625, 97.28197178315625, 96.58033571299049, 96.58033571299049, 96.25643172904921, 96.25643172904921, 96.6261400000404, 96.6261400000404, 96.52079469759674, 96.52079469759674, 96.14265950886788, 96.14265950886788, 96.29506225210642, 96.29506225210642, 95.82910831575578, 95.82910831575578, 96.35112441973347, 96.35112441973347, 96.16329269178928, 96.16329269178928, 95.87027246972195, 95.87027246972195, 95.7307727305111, 95.7307727305111, 95.52782525481386, 95.52782525481386, 95.3266966060663, 95.3266966060663, 94.73244989096955, 94.73244989096955, 94.85863986535756, 94.85863986535756, 94.5348526851931, 94.5348526851931, 94.27697635190073, 94.27697635190073, 93.47026915554588, 93.47026915554588, 93.23682795968988, 93.23682795968988, 93.37231139151324, 93.37231139151324, 93.15534439539415, 93.15534439539415, 93.24217287585641, 93.24217287585641, 93.78860723896459, 93.78860723896459, 93.77560714675685, 93.77560714675685, 93.0999726791823, 93.0999726791823, 92.90606801326578, 92.90606801326578, 93.2831221906634, 93.2831221906634, 93.01583352672039, 93.01583352672039, 92.70359835023112, 92.70359835023112, 92.00530036542673, 92.00530036542673, 92.42100834060409, 92.42100834060409, 92.7895835919253, 92.7895835919253, 92.73717490018763, 92.73717490018763, 92.76883196952322, 92.76883196952322, 93.08317487684629, 93.08317487684629, 92.33451766496589, 92.33451766496589, 92.13498897315472, 92.13498897315472, 92.09928886790658, 92.09928886790658, 92.22680948420437, 92.22680948420437, 91.62546599412939, 91.62546599412939, 91.12033628158707, 91.12033628158707, 90.91703470428618, 90.91703470428618, 90.51203613658468, 90.51203613658468, 90.76461607129751, 90.76461607129751, 91.12216656725413, 91.12216656725413, 91.25249379875453, 91.25249379875453, 91.58012004487541, 91.58012004487541, 91.06486472813755, 91.06486472813755, 91.18797649222013, 91.18797649222013, 90.69671638734081, 90.69671638734081, 91.26790712942591, 91.26790712942591, 90.79702047570592, 90.79702047570592, 90.23186056687439, 90.23186056687439, 89.67634735880623, 89.67634735880623, 90.06987166421722, 90.06987166421722, 89.65940405481305, 89.65940405481305, 89.14786912937605, 89.14786912937605, 88.68086196244481, 88.68086196244481, 88.08424380115036, 88.08424380115036, 87.92914636627808, 87.92914636627808, 100, 92.99931606318984, 92.99931606318984, 93.74968330870446, 93.74968330870446, 93.35200242595599, 93.35200242595599, 97.61217815984494, 97.61217815984494, 95.54997817570786, 95.54997817570786, 95.635092884268, 95.635092884268, 92.61880754039443, 92.61880754039443, 85.39231796273906, 85.39231796273906, 83.12912862094319, 83.12912862094319, 85.40561642328275, 85.40561642328275, 84.62039860344953, 84.62039860344953, 86.16474388636449, 86.16474388636449, 88.32785188924211, 88.32785188924211, 92.10765900299248, 92.10765900299248, 93.26077770768009, 93.26077770768009, 97.9845294627281, 97.9845294627281, 91.85128228934461, 91.85128228934461, 92.94825282196534, 92.94825282196534, 94.908060967487, 94.908060967487, 94.71326538271349, 94.71326538271349, 100.13862169564187, 100.13862169564187, 101.27435286478284, 101.27435286478284, 107.18723419784558, 107.18723419784558, 105.11150551338793, 105.11150551338793, 108.89332418604562, 108.89332418604562, 110.45800926706632, 110.45800926706632, 116.48523146511381, 116.48523146511381, 114.1292438507272, 114.1292438507272, 115.6710564645791, 115.6710564645791, 120.72623435030194, 120.72623435030194, 118.93046533906094, 118.93046533906094, 112.25835075871757, 112.25835075871757, 110.00527663324144, 110.00527663324144, 101.43663074912372, 101.43663074912372, 101.02867217786005, 101.02867217786005, 94.33053060847377, 94.33053060847377, 89.75476827975842, 89.75476827975842, 93.29245542951959, 93.29245542951959, 94.9186805787271, 94.9186805787271, 96.46551527277536, 96.46551527277536, 89.87389035969865, 89.87389035969865, 87.16376777592785, 87.16376777592785, 90.71447055509934, 90.71447055509934, 90.19536558085994, 90.19536558085994, 87.37997504032674, 87.37997504032674, 89.23463194487961, 89.23463194487961, 85.88495474723042, 85.88495474723042, 90.91229934650016, 90.91229934650016, 90.15196996137051, 90.15196996137051, 88.67602042222708, 88.67602042222708, 88.50743002514825, 88.50743002514825, 87.96325417167918, 87.96325417167918, 87.47813607760847, 87.47813607760847, 84.01053269460503, 84.01053269460503, 86.21927941269837, 86.21927941269837, 85.20026287932083, 85.20026287932083, 84.74514940369397, 84.74514940369397, 80.44680552355874, 80.44680552355874, 80.41520185078912, 80.41520185078912, 83.13776682112793, 83.13776682112793, 83.62311825579216, 83.62311825579216, 86.27091768763398, 86.27091768763398, 92.29068344923925, 92.29068344923925, 94.59113655600862, 94.59113655600862, 92.23253576603186, 92.23253576603186, 93.36203549432568, 93.36203549432568, 98.80311561440442, 98.80311561440442, 99.52383859763862, 99.52383859763862, 100.02610961464065, 100.02610961464065, 97.48148429129367, 97.48148429129367, 103.34545533154333, 103.34545533154333, 109.43020057074936, 109.43020057074936, 112.12304973808557, 112.12304973808557, 115.52003033279902, 115.52003033279902, 121.55801868602819, 121.55801868602819, 117.08958909341867, 117.08958909341867, 117.75922193520242, 117.75922193520242, 119.85458925018938, 119.85458925018938, 123.66274001251523, 123.66274001251523, 119.15604184133105, 119.15604184133105, 115.53291901293304, 115.53291901293304, 114.89363074478746, 114.89363074478746, 111.82198288405428, 111.82198288405428, 115.87910014654939, 115.87910014654939, 121.11836567425608, 121.11836567425608, 123.6936575690804, 123.6936575690804, 128.58085298226052, 128.58085298226052, 121.95792293344105, 121.95792293344105, 123.60374048079915, 123.60374048079915, 116.48935752258258, 116.48935752258258, 123.55808091733965, 123.55808091733965, 115.82597098962636, 115.82597098962636, 106.77349871746914, 106.77349871746914, 98.16867422379417, 98.16867422379417, 101.74594768140646, 101.74594768140646, 95.1243047124417, 95.1243047124417, 87.65512294066052, 87.65512294066052, 81.34224880318148, 81.34224880318148, 74.25512295493493, 74.25512295493493, 72.08158085400078, 72.08158085400078, 100, 96.49965803159492, 96.49965803159492, 96.89282234085528, 96.89282234085528, 96.66395700156504, 96.66395700156504, 98.84511851049147, 98.84511851049147, 97.72022468264952, 97.72022468264952, 97.69539195252099, 97.69539195252099, 96.04474200505408, 96.04474200505408, 92.12122707795169, 92.12122707795169, 90.7524578823741, 90.7524578823741, 91.86620599866295, 91.86620599866295, 91.18321550679761, 91.18321550679761, 91.77076300242805, 91.77076300242805, 92.64886983215455, 92.64886983215455, 94.4115531951917, 94.4115531951917, 94.60105803410664, 94.60105803410664, 96.77426923210655, 96.77426923210655, 92.95584004241334, 92.95584004241334, 93.0988602155345, 93.0988602155345, 93.66372732853505, 93.66372732853505, 93.03719912084956, 93.03719912084956, 95.452716939988, 95.452716939988, 95.51738150606599, 95.51738150606599, 98.05425788440175, 98.05425788440175, 96.45618107548292, 96.45618107548292, 97.85694974565604, 97.85694974565604, 98.17927424291095, 98.17927424291095, 100.65800191623217, 100.65800191623217, 99.23013457226213, 99.23013457226213, 99.68075990493776, 99.68075990493776, 101.76892968159176, 101.76892968159176, 100.93152794995164, 100.93152794995164, 98.15507445203599, 98.15507445203599, 97.32448920917646, 97.32448920917646, 93.8712393709979, 93.8712393709979, 93.94055110646606, 93.94055110646606, 91.25561322951836, 91.25561322951836, 89.45152914637421, 89.45152914637421, 91.38648456820863, 91.38648456820863, 92.40702828733023, 92.40702828733023, 93.37466906480901, 93.37466906480901, 90.60421743023397, 90.60421743023397, 89.54727537765943, 89.54727537765943, 91.50562818437629, 91.50562818437629, 91.43629555560625, 91.43629555560625, 90.22387819072098, 90.22387819072098, 91.286734506583, 91.286734506583, 89.70792037849891, 89.70792037849891, 92.36523442648821, 92.36523442648821, 92.01299752297405, 92.01299752297405, 91.26989588133198, 91.26989588133198, 91.16338302394053, 91.16338302394053, 90.8266416539283, 90.8266416539283, 90.48973346931841, 90.48973346931841, 88.53135087902336, 88.53135087902336, 89.58435442398849, 89.58435442398849, 88.8253866031861, 88.8253866031861, 88.3389425664917, 88.3389425664917, 85.6690510129246, 85.6690510129246, 85.33734615018504, 85.33734615018504, 86.51603920143914, 86.51603920143914, 86.33828493348129, 86.33828493348129, 87.36304955582791, 87.36304955582791, 90.23284652388249, 90.23284652388249, 90.91718361444943, 90.91718361444943, 88.99242906220593, 88.99242906220593, 88.99938883525597, 88.99938883525597, 91.30743180141197, 91.30743180141197, 91.05295854841216, 91.05295854841216, 90.67174729743687, 90.67174729743687, 88.7604154487307, 88.7604154487307, 91.21667934978741, 91.21667934978741, 93.6338256538187, 93.6338256538187, 94.37558676757705, 94.37558676757705, 95.47321941160612, 95.47321941160612, 97.77075917390104, 97.77075917390104, 95.59282238220855, 95.59282238220855, 95.72059903293992, 95.72059903293992, 96.52854695498216, 96.52854695498216, 98.09563460829936, 98.09563460829936, 96.51532722863074, 96.51532722863074, 95.4085247939158, 95.4085247939158, 95.52465821995634, 95.52465821995634, 94.8087017899729, 94.8087017899729, 96.88999312951138, 96.88999312951138, 99.41181607140739, 99.41181607140739, 101.0349689701463, 101.0349689701463, 103.52291722549926, 103.52291722549926, 102.29402709966891, 102.29402709966891, 103.89599855840412, 103.89599855840412, 102.66305598951656, 102.66305598951656, 106.35128198458621, 106.35128198458621, 105.2153347445648, 105.2153347445648, 103.54761969318548, 103.54761969318548, 101.9104419064554, 101.9104419064554, 104.68762728033715, 104.68762728033715, 103.74561762296544, 103.74561762296544, 102.29177188240789, 102.29177188240789, 100.99065500957371, 100.99065500957371, 99.08829773238939, 99.08829773238939, 99.25050915772879, 99.25050915772879 ], "xaxis": "x", "y": [ 15, 15.0025881631884, 15.0025881631884, 15.001496702185737, 15.001496702185737, 15.002361804039465, 15.002361804039465, 15.003883708196188, 15.003883708196188, 15.00568393679195, 15.00568393679195, 15.007415489103332, 15.007415489103332, 15.007679903819312, 15.007679903819312, 15.00785846437848, 15.00785846437848, 15.005149988731267, 15.005149988731267, 15.003693218370183, 15.003693218370183, 15.003201208353792, 15.003201208353792, 15.001441720795848, 15.001441720795848, 15.000133583406503, 15.000133583406503, 14.998369352308925, 14.998369352308925, 14.996174666815067, 14.996174666815067, 14.994789169151316, 14.994789169151316, 14.99321394632609, 14.99321394632609, 14.990466967358335, 14.990466967358335, 14.98892812664762, 14.98892812664762, 14.987709914471244, 14.987709914471244, 14.987290241379329, 14.987290241379329, 14.985547623238297, 14.985547623238297, 14.986392330287694, 14.986392330287694, 14.9857180023299, 14.9857180023299, 14.984461841594834, 14.984461841594834, 14.985073680988108, 14.985073680988108, 14.985562867120061, 14.985562867120061, 14.98541282187458, 14.98541282187458, 14.984719710317288, 14.984719710317288, 14.985916999281203, 14.985916999281203, 14.98625696832826, 14.98625696832826, 14.986605681348385, 14.986605681348385, 14.985955421994834, 14.985955421994834, 14.986129886338091, 14.986129886338091, 14.984477177626776, 14.984477177626776, 14.981225059271852, 14.981225059271852, 14.976432391666856, 14.976432391666856, 14.973674166171941, 14.973674166171941, 14.96980019046312, 14.96980019046312, 14.966768040636888, 14.966768040636888, 14.962334392385861, 14.962334392385861, 14.957429395595303, 14.957429395595303, 14.953568887352041, 14.953568887352041, 14.948548302693771, 14.948548302693771, 14.945167884771239, 14.945167884771239, 14.940572465174537, 14.940572465174537, 14.936861141832518, 14.936861141832518, 14.931906107640428, 14.931906107640428, 14.927219898398723, 14.927219898398723, 14.921427580941707, 14.921427580941707, 14.91592475619714, 14.91592475619714, 14.910827079437475, 14.910827079437475, 14.90399212146379, 14.90399212146379, 14.897887136036417, 14.897887136036417, 14.891130476962763, 14.891130476962763, 14.883405497521546, 14.883405497521546, 14.876434503668987, 14.876434503668987, 14.870076791929769, 14.870076791929769, 14.862470074033991, 14.862470074033991, 14.853101924486802, 14.853101924486802, 14.845417890954725, 14.845417890954725, 14.834854591138358, 14.834854591138358, 14.82487867160691, 14.82487867160691, 14.817333893722857, 14.817333893722857, 14.80795542406726, 14.80795542406726, 14.799736508431591, 14.799736508431591, 14.789248058469765, 14.789248058469765, 14.7801175136321, 14.7801175136321, 14.77151478230201, 14.77151478230201, 14.762483431482917, 14.762483431482917, 14.75140910811959, 14.75140910811959, 14.742427769315322, 14.742427769315322, 14.731695495637132, 14.731695495637132, 14.723316727651351, 14.723316727651351, 14.714085420344661, 14.714085420344661, 14.705044067153839, 14.705044067153839, 14.695511757105502, 14.695511757105502, 14.684106161453188, 14.684106161453188, 14.673362900138697, 14.673362900138697, 14.662126777303884, 14.662126777303884, 14.650294122378542, 14.650294122378542, 14.637133503588467, 14.637133503588467, 14.625885500549552, 14.625885500549552, 14.613041318879013, 14.613041318879013, 14.600491228516, 14.600491228516, 14.589826301169238, 14.589826301169238, 14.579097284458562, 14.579097284458562, 14.567445029812177, 14.567445029812177, 14.555065538321779, 14.555065538321779, 14.543083171721651, 14.543083171721651, 14.530543871653219, 14.530543871653219, 14.519732090172331, 14.519732090172331, 14.50728664083606, 14.50728664083606, 14.494761059082773, 14.494761059082773, 14.480759862525757, 14.480759862525757, 14.466954078017151, 14.466954078017151, 14.452655312592428, 14.452655312592428, 14.43861439698937, 14.43861439698937, 14.421950182244203, 14.421950182244203, 14.404714317939641, 14.404714317939641, 15, 15.025881631884008, 15.025881631884008, 14.919856780977506, 14.919856780977506, 14.84340539956636, 14.84340539956636, 14.768172517785956, 14.768172517785956, 14.753355341717914, 14.753355341717914, 14.710325587285196, 14.710325587285196, 14.65501286735965, 14.65501286735965, 14.558960244492898, 14.558960244492898, 14.343261540533113, 14.343261540533113, 14.112473629068363, 14.112473629068363, 13.923048492146386, 13.923048492146386, 13.716505105851384, 13.716505105851384, 13.536396160701718, 13.536396160701718, 13.382627368919778, 13.382627368919778, 13.273403497288376, 13.273403497288376, 13.18737339314849, 13.18737339314849, 13.15696932845709, 13.15696932845709, 13.046690159522171, 13.046690159522171, 12.961691639243096, 12.961691639243096, 12.904545878763365, 12.904545878763365, 12.853989386327374, 12.853989386327374, 12.856562555701977, 12.856562555701977, 12.89695026210208, 12.89695026210208, 12.99401382064389, 12.99401382064389, 13.064986472742175, 13.064986472742175, 13.200100005296521, 13.200100005296521, 13.356245186734787, 13.356245186734787, 13.581858258648817, 13.581858258648817, 13.779446331861786, 13.779446331861786, 14.020887197803892, 14.020887197803892, 14.322226633251981, 14.322226633251981, 14.607966995872808, 14.607966995872808, 14.80045909939326, 14.80045909939326, 14.974742020331096, 14.974742020331096, 15.014139514654353, 15.014139514654353, 15.031590488973418, 15.031590488973418, 14.942284460374912, 14.942284460374912, 14.810526845162071, 14.810526845162071, 14.71725604402707, 14.71725604402707, 14.654423668399897, 14.654423668399897, 14.59904128346401, 14.59904128346401, 14.452865602940358, 14.452865602940358, 14.282261478879674, 14.282261478879674, 14.149772009038367, 14.149772009038367, 14.027052069983485, 14.027052069983485, 13.859992607077059, 13.859992607077059, 13.726038665079807, 13.726038665079807, 13.542762810472052, 13.542762810472052, 13.426206655218582, 13.426206655218582, 13.293233924236567, 13.293233924236567, 13.147791616712704, 13.147791616712704, 13.006610763951292, 13.006610763951292, 12.84823986731333, 12.84823986731333, 12.693804885133208, 12.693804885133208, 12.498890192871052, 12.498890192871052, 12.325809989121367, 12.325809989121367, 12.151607078337484, 12.151607078337484, 11.98176127509246, 11.98176127509246, 11.761719359770526, 11.761719359770526, 11.535738338854555, 11.535738338854555, 11.356031924588308, 11.356031924588308, 11.166858150706151, 11.166858150706151, 11.013537609868145, 11.013537609868145, 10.940785833361874, 10.940785833361874, 10.880470893076224, 10.880470893076224, 10.810492031684296, 10.810492031684296, 10.738828174758915, 10.738828174758915, 10.732227365833888, 10.732227365833888, 10.74063259552893, 10.74063259552893, 10.754970118090359, 10.754970118090359, 10.733785904628672, 10.733785904628672, 10.787976887758164, 10.787976887758164, 10.88944458640169, 10.88944458640169, 11.04254907916619, 11.04254907916619, 11.228202407568958, 11.228202407568958, 11.482818264639777, 11.482818264639777, 11.69687181566044, 11.69687181566044, 11.906283961960796, 11.906283961960796, 12.151929632994989, 12.151929632994989, 12.442078661195602, 12.442078661195602, 12.685614756768384, 12.685614756768384, 12.882246373678006, 12.882246373678006, 13.098033807459965, 13.098033807459965, 13.265644619378074, 13.265644619378074, 13.488205244369283, 13.488205244369283, 13.801786381602861, 13.801786381602861, 14.15661507092392, 14.15661507092392, 14.571319896228996, 14.571319896228996, 14.900498464260913, 14.900498464260913, 15.264447207321453, 15.264447207321453, 15.531123380217505, 15.531123380217505, 15.924513627073946, 15.924513627073946, 16.19019922374802, 16.19019922374802, 16.322098263657374, 16.322098263657374, 16.304174332335062, 16.304174332335062, 16.340241196629936, 16.340241196629936, 16.268904220202955, 16.268904220202955, 16.086253203878236, 16.086253203878236, 15.782468169262778, 15.782468169262778, 15.374958294571538, 15.374958294571538, 15, 15.012940815942004, 15.012940815942004, 14.98636610132836, 14.98636610132836, 14.971810745493599, 14.971810745493599, 14.959082346076983, 14.959082346076983, 14.960947875173133, 14.960947875173133, 14.95565263271521, 14.95565263271521, 14.943059453110807, 14.943059453110807, 14.920042423099233, 14.920042423099233, 14.859798697725925, 14.859798697725925, 14.797521921922066, 14.797521921922066, 14.746699458020705, 14.746699458020705, 14.686175690662845, 14.686175690662845, 14.631471102128723, 14.631471102128723, 14.58023065366825, 14.58023065366825, 14.537568554812667, 14.537568554812667, 14.500231317119468, 14.500231317119468, 14.474722857563513, 14.474722857563513, 14.4220647350196, 14.4220647350196, 14.376180825464203, 14.376180825464203, 14.335464151009303, 14.335464151009303, 14.295170307805137, 14.295170307805137, 14.263049608683579, 14.263049608683579, 14.243626386186193, 14.243626386186193, 14.231930990766053, 14.231930990766053, 14.208866161776603, 14.208866161776603, 14.202879759057403, 14.202879759057403, 14.198542451693676, 14.198542451693676, 14.205568788947831, 14.205568788947831, 14.202391682296767, 14.202391682296767, 14.211179246898407, 14.211179246898407, 14.22809282401728, 14.22809282401728, 14.240716868942075, 14.240716868942075, 14.233201323513999, 14.233201323513999, 14.225227297004473, 14.225227297004473, 14.189429886330164, 14.189429886330164, 14.147165369806896, 14.147165369806896, 14.08333714510193, 14.08333714510193, 14.019069291306938, 14.019069291306938, 13.961481416227368, 13.961481416227368, 13.913958049210835, 13.913958049210835, 13.866151471260338, 13.866151471260338, 13.801817295121142, 13.801817295121142, 13.737042236766802, 13.737042236766802, 13.678767238942457, 13.678767238942457, 13.628052525015123, 13.628052525015123, 13.56643704645608, 13.56643704645608, 13.515035696227566, 13.515035696227566, 13.450876501139497, 13.450876501139497, 13.402818129238593, 13.402818129238593, 13.348944553667687, 13.348944553667687, 13.293373264063145, 13.293373264063145, 13.239891656584982, 13.239891656584982, 13.178310915340727, 13.178310915340727, 13.11914363309317, 13.11914363309317, 13.04834605494057, 13.04834605494057, 12.980008418510142, 12.980008418510142, 12.912100563936535, 12.912100563936535, 12.84548257168026, 12.84548257168026, 12.761653328708682, 12.761653328708682, 12.670680742782599, 12.670680742782599, 12.593746048181327, 12.593746048181327, 12.505966192387636, 12.505966192387636, 12.426975415778585, 12.426975415778585, 12.372987114877688, 12.372987114877688, 12.316124888297376, 12.316124888297376, 12.25624784136798, 12.25624784136798, 12.188780748399955, 12.188780748399955, 12.139029429691613, 12.139029429691613, 12.091613175035052, 12.091613175035052, 12.042152685505714, 12.042152685505714, 11.977247905600317, 11.977247905600317, 11.933433733774168, 11.933433733774168, 11.89504783502318, 11.89504783502318, 11.871147080760428, 11.871147080760428, 11.850217659047976, 11.850217659047976, 11.84192192212905, 11.84192192212905, 11.82311969344896, 11.82311969344896, 11.798468322241224, 11.798468322241224, 11.781618541251447, 11.781618541251447, 11.771189982727265, 11.771189982727265, 11.752590059889691, 11.752590059889691, 11.725074162195554, 11.725074162195554, 11.707552281866988, 11.707552281866988, 11.681614136981478, 11.681614136981478, 11.667586378488018, 11.667586378488018, 11.674231291283325, 11.674231291283325, 11.689501880321215, 11.689501880321215, 11.71312985613572, 11.71312985613572, 11.729541695595978, 11.729541695595978, 11.756346252143663, 11.756346252143663, 11.776821825896544, 11.776821825896544, 11.823144360448932, 11.823144360448932, 11.858480184796978, 11.858480184796978, 11.887381186413212, 11.887381186413212, 11.903274853981108, 11.903274853981108, 11.934053284575308, 11.934053284575308, 11.959946529310686, 11.959946529310686, 11.981458643093886, 11.981458643093886, 11.986109221284174, 11.986109221284174, 11.98062484432249, 11.98062484432249 ], "yaxis": "y" }, { "hovertemplate": "color=8
x=%{x}
y=%{y}", "legendgroup": "8", "line": { "color": "#B6E880", "dash": "solid" }, "marker": { "symbol": "circle" }, "mode": "lines", "name": "8", "showlegend": true, "type": "scattergl", "x": [ 100, 99.29993160631898, 99.29993160631898, 99.38148169571427, 99.38148169571427, 99.33344287701127, 99.33344287701127, 99.78052429956195, 99.78052429956195, 99.54958970085868, 99.54958970085868, 99.5415288602601, 99.5415288602601, 99.20043010937233, 99.20043010937233, 98.38175972088112, 98.38175972088112, 98.08171337358606, 98.08171337358606, 98.3146135545321, 98.3146135545321, 98.15163483592876, 98.15163483592876, 98.2617316271704, 98.2617316271704, 98.4307104729456, 98.4307104729456, 98.78953357215462, 98.78953357215462, 98.79985727776051, 98.79985727776051, 99.23692266333096, 99.23692266333096, 98.39279376646044, 98.39279376646044, 98.38874784974972, 98.38874784974972, 98.47174801810372, 98.47174801810372, 98.2916973612909, 98.2916973612909, 98.77808827688989, 98.77808827688989, 98.74409721517681, 98.74409721517681, 99.24190042277999, 99.24190042277999, 98.84599456847697, 98.84599456847697, 99.09135177709153, 99.09135177709153, 99.10434894166539, 99.10434894166539, 99.57328874254877, 99.57328874254877, 99.21501237298247, 99.21501237298247, 99.25020700392601, 99.25020700392601, 99.63288351336783, 99.63288351336783, 99.40473856709445, 99.40473856709445, 98.7710291940686, 98.7710291940686, 98.5407493936721, 98.5407493936721, 97.7508566239193, 97.7508566239193, 97.71072647387824, 97.71072647387824, 97.06612114764668, 97.06612114764668, 96.60023270185529, 96.60023270185529, 96.97950519720334, 96.97950519720334, 97.13875284807816, 97.13875284807816, 97.28197178315625, 97.28197178315625, 96.58033571299049, 96.58033571299049, 96.25643172904921, 96.25643172904921, 96.6261400000404, 96.6261400000404, 96.52079469759674, 96.52079469759674, 96.14265950886788, 96.14265950886788, 96.29506225210642, 96.29506225210642, 95.82910831575578, 95.82910831575578, 96.35112441973347, 96.35112441973347, 96.16329269178928, 96.16329269178928, 95.87027246972195, 95.87027246972195, 95.7307727305111, 95.7307727305111, 95.52782525481386, 95.52782525481386, 95.3266966060663, 95.3266966060663, 94.73244989096955, 94.73244989096955, 94.85863986535756, 94.85863986535756, 94.5348526851931, 94.5348526851931, 94.27697635190073, 94.27697635190073, 93.47026915554588, 93.47026915554588, 93.23682795968988, 93.23682795968988, 93.37231139151324, 93.37231139151324, 93.15534439539415, 93.15534439539415, 93.24217287585641, 93.24217287585641, 93.78860723896459, 93.78860723896459, 93.77560714675685, 93.77560714675685, 93.0999726791823, 93.0999726791823, 92.90606801326578, 92.90606801326578, 93.2831221906634, 93.2831221906634, 93.01583352672039, 93.01583352672039, 92.70359835023112, 92.70359835023112, 92.00530036542673, 92.00530036542673, 92.42100834060409, 92.42100834060409, 92.7895835919253, 92.7895835919253, 92.73717490018763, 92.73717490018763, 92.76883196952322, 92.76883196952322, 93.08317487684629, 93.08317487684629, 92.33451766496589, 92.33451766496589, 92.13498897315472, 92.13498897315472, 92.09928886790658, 92.09928886790658, 92.22680948420437, 92.22680948420437, 91.62546599412939, 91.62546599412939, 91.12033628158707, 91.12033628158707, 90.91703470428618, 90.91703470428618, 90.51203613658468, 90.51203613658468, 90.76461607129751, 90.76461607129751, 91.12216656725413, 91.12216656725413, 91.25249379875453, 91.25249379875453, 91.58012004487541, 91.58012004487541, 91.06486472813755, 91.06486472813755, 91.18797649222013, 91.18797649222013, 90.69671638734081, 90.69671638734081, 91.26790712942591, 91.26790712942591, 90.79702047570592, 90.79702047570592, 90.23186056687439, 90.23186056687439, 89.67634735880623, 89.67634735880623, 90.06987166421722, 90.06987166421722, 89.65940405481305, 89.65940405481305, 89.14786912937605, 89.14786912937605, 88.68086196244481, 88.68086196244481, 88.08424380115036, 88.08424380115036, 87.92914636627808, 87.92914636627808, 100, 92.99931606318984, 92.99931606318984, 93.74968330870446, 93.74968330870446, 93.35200242595599, 93.35200242595599, 97.61217815984494, 97.61217815984494, 95.54997817570786, 95.54997817570786, 95.635092884268, 95.635092884268, 92.61880754039443, 92.61880754039443, 85.39231796273906, 85.39231796273906, 83.12912862094319, 83.12912862094319, 85.40561642328275, 85.40561642328275, 84.62039860344953, 84.62039860344953, 86.16474388636449, 86.16474388636449, 88.32785188924211, 88.32785188924211, 92.10765900299248, 92.10765900299248, 93.26077770768009, 93.26077770768009, 97.9845294627281, 97.9845294627281, 91.85128228934461, 91.85128228934461, 92.94825282196534, 92.94825282196534, 94.908060967487, 94.908060967487, 94.71326538271349, 94.71326538271349, 100.13862169564187, 100.13862169564187, 101.27435286478284, 101.27435286478284, 107.18723419784558, 107.18723419784558, 105.11150551338793, 105.11150551338793, 108.89332418604562, 108.89332418604562, 110.45800926706632, 110.45800926706632, 116.48523146511381, 116.48523146511381, 114.1292438507272, 114.1292438507272, 115.6710564645791, 115.6710564645791, 120.72623435030194, 120.72623435030194, 118.93046533906094, 118.93046533906094, 112.25835075871757, 112.25835075871757, 110.00527663324144, 110.00527663324144, 101.43663074912372, 101.43663074912372, 101.02867217786005, 101.02867217786005, 94.33053060847377, 94.33053060847377, 89.75476827975842, 89.75476827975842, 93.29245542951959, 93.29245542951959, 94.9186805787271, 94.9186805787271, 96.46551527277536, 96.46551527277536, 89.87389035969865, 89.87389035969865, 87.16376777592785, 87.16376777592785, 90.71447055509934, 90.71447055509934, 90.19536558085994, 90.19536558085994, 87.37997504032674, 87.37997504032674, 89.23463194487961, 89.23463194487961, 85.88495474723042, 85.88495474723042, 90.91229934650016, 90.91229934650016, 90.15196996137051, 90.15196996137051, 88.67602042222708, 88.67602042222708, 88.50743002514825, 88.50743002514825, 87.96325417167918, 87.96325417167918, 87.47813607760847, 87.47813607760847, 84.01053269460503, 84.01053269460503, 86.21927941269837, 86.21927941269837, 85.20026287932083, 85.20026287932083, 84.74514940369397, 84.74514940369397, 80.44680552355874, 80.44680552355874, 80.41520185078912, 80.41520185078912, 83.13776682112793, 83.13776682112793, 83.62311825579216, 83.62311825579216, 86.27091768763398, 86.27091768763398, 92.29068344923925, 92.29068344923925, 94.59113655600862, 94.59113655600862, 92.23253576603186, 92.23253576603186, 93.36203549432568, 93.36203549432568, 98.80311561440442, 98.80311561440442, 99.52383859763862, 99.52383859763862, 100.02610961464065, 100.02610961464065, 97.48148429129367, 97.48148429129367, 103.34545533154333, 103.34545533154333, 109.43020057074936, 109.43020057074936, 112.12304973808557, 112.12304973808557, 115.52003033279902, 115.52003033279902, 121.55801868602819, 121.55801868602819, 117.08958909341867, 117.08958909341867, 117.75922193520242, 117.75922193520242, 119.85458925018938, 119.85458925018938, 123.66274001251523, 123.66274001251523, 119.15604184133105, 119.15604184133105, 115.53291901293304, 115.53291901293304, 114.89363074478746, 114.89363074478746, 111.82198288405428, 111.82198288405428, 115.87910014654939, 115.87910014654939, 121.11836567425608, 121.11836567425608, 123.6936575690804, 123.6936575690804, 128.58085298226052, 128.58085298226052, 121.95792293344105, 121.95792293344105, 123.60374048079915, 123.60374048079915, 116.48935752258258, 116.48935752258258, 123.55808091733965, 123.55808091733965, 115.82597098962636, 115.82597098962636, 106.77349871746914, 106.77349871746914, 98.16867422379417, 98.16867422379417, 101.74594768140646, 101.74594768140646, 95.1243047124417, 95.1243047124417, 87.65512294066052, 87.65512294066052, 81.34224880318148, 81.34224880318148, 74.25512295493493, 74.25512295493493, 72.08158085400078, 72.08158085400078, 100, 96.49965803159492, 96.49965803159492, 96.89282234085528, 96.89282234085528, 96.66395700156504, 96.66395700156504, 98.84511851049147, 98.84511851049147, 97.72022468264952, 97.72022468264952, 97.69539195252099, 97.69539195252099, 96.04474200505408, 96.04474200505408, 92.12122707795169, 92.12122707795169, 90.7524578823741, 90.7524578823741, 91.86620599866295, 91.86620599866295, 91.18321550679761, 91.18321550679761, 91.77076300242805, 91.77076300242805, 92.64886983215455, 92.64886983215455, 94.4115531951917, 94.4115531951917, 94.60105803410664, 94.60105803410664, 96.77426923210655, 96.77426923210655, 92.95584004241334, 92.95584004241334, 93.0988602155345, 93.0988602155345, 93.66372732853505, 93.66372732853505, 93.03719912084956, 93.03719912084956, 95.452716939988, 95.452716939988, 95.51738150606599, 95.51738150606599, 98.05425788440175, 98.05425788440175, 96.45618107548292, 96.45618107548292, 97.85694974565604, 97.85694974565604, 98.17927424291095, 98.17927424291095, 100.65800191623217, 100.65800191623217, 99.23013457226213, 99.23013457226213, 99.68075990493776, 99.68075990493776, 101.76892968159176, 101.76892968159176, 100.93152794995164, 100.93152794995164, 98.15507445203599, 98.15507445203599, 97.32448920917646, 97.32448920917646, 93.8712393709979, 93.8712393709979, 93.94055110646606, 93.94055110646606, 91.25561322951836, 91.25561322951836, 89.45152914637421, 89.45152914637421, 91.38648456820863, 91.38648456820863, 92.40702828733023, 92.40702828733023, 93.37466906480901, 93.37466906480901, 90.60421743023397, 90.60421743023397, 89.54727537765943, 89.54727537765943, 91.50562818437629, 91.50562818437629, 91.43629555560625, 91.43629555560625, 90.22387819072098, 90.22387819072098, 91.286734506583, 91.286734506583, 89.70792037849891, 89.70792037849891, 92.36523442648821, 92.36523442648821, 92.01299752297405, 92.01299752297405, 91.26989588133198, 91.26989588133198, 91.16338302394053, 91.16338302394053, 90.8266416539283, 90.8266416539283, 90.48973346931841, 90.48973346931841, 88.53135087902336, 88.53135087902336, 89.58435442398849, 89.58435442398849, 88.8253866031861, 88.8253866031861, 88.3389425664917, 88.3389425664917, 85.6690510129246, 85.6690510129246, 85.33734615018504, 85.33734615018504, 86.51603920143914, 86.51603920143914, 86.33828493348129, 86.33828493348129, 87.36304955582791, 87.36304955582791, 90.23284652388249, 90.23284652388249, 90.91718361444943, 90.91718361444943, 88.99242906220593, 88.99242906220593, 88.99938883525597, 88.99938883525597, 91.30743180141197, 91.30743180141197, 91.05295854841216, 91.05295854841216, 90.67174729743687, 90.67174729743687, 88.7604154487307, 88.7604154487307, 91.21667934978741, 91.21667934978741, 93.6338256538187, 93.6338256538187, 94.37558676757705, 94.37558676757705, 95.47321941160612, 95.47321941160612, 97.77075917390104, 97.77075917390104, 95.59282238220855, 95.59282238220855, 95.72059903293992, 95.72059903293992, 96.52854695498216, 96.52854695498216, 98.09563460829936, 98.09563460829936, 96.51532722863074, 96.51532722863074, 95.4085247939158, 95.4085247939158, 95.52465821995634, 95.52465821995634, 94.8087017899729, 94.8087017899729, 96.88999312951138, 96.88999312951138, 99.41181607140739, 99.41181607140739, 101.0349689701463, 101.0349689701463, 103.52291722549926, 103.52291722549926, 102.29402709966891, 102.29402709966891, 103.89599855840412, 103.89599855840412, 102.66305598951656, 102.66305598951656, 106.35128198458621, 106.35128198458621, 105.2153347445648, 105.2153347445648, 103.54761969318548, 103.54761969318548, 101.9104419064554, 101.9104419064554, 104.68762728033715, 104.68762728033715, 103.74561762296544, 103.74561762296544, 102.29177188240789, 102.29177188240789, 100.99065500957371, 100.99065500957371, 99.08829773238939, 99.08829773238939, 99.25050915772879, 99.25050915772879 ], "xaxis": "x", "y": [ 15, 15.0025881631884, 15.0025881631884, 15.001496702185737, 15.001496702185737, 15.002361804039465, 15.002361804039465, 15.003883708196188, 15.003883708196188, 15.00568393679195, 15.00568393679195, 15.007415489103332, 15.007415489103332, 15.007679903819312, 15.007679903819312, 15.00785846437848, 15.00785846437848, 15.005149988731267, 15.005149988731267, 15.003693218370183, 15.003693218370183, 15.003201208353792, 15.003201208353792, 15.001441720795848, 15.001441720795848, 15.000133583406503, 15.000133583406503, 14.998369352308925, 14.998369352308925, 14.996174666815067, 14.996174666815067, 14.994789169151316, 14.994789169151316, 14.99321394632609, 14.99321394632609, 14.990466967358335, 14.990466967358335, 14.98892812664762, 14.98892812664762, 14.987709914471244, 14.987709914471244, 14.987290241379329, 14.987290241379329, 14.985547623238297, 14.985547623238297, 14.986392330287694, 14.986392330287694, 14.9857180023299, 14.9857180023299, 14.984461841594834, 14.984461841594834, 14.985073680988108, 14.985073680988108, 14.985562867120061, 14.985562867120061, 14.98541282187458, 14.98541282187458, 14.984719710317288, 14.984719710317288, 14.985916999281203, 14.985916999281203, 14.98625696832826, 14.98625696832826, 14.986605681348385, 14.986605681348385, 14.985955421994834, 14.985955421994834, 14.986129886338091, 14.986129886338091, 14.984477177626776, 14.984477177626776, 14.981225059271852, 14.981225059271852, 14.976432391666856, 14.976432391666856, 14.973674166171941, 14.973674166171941, 14.96980019046312, 14.96980019046312, 14.966768040636888, 14.966768040636888, 14.962334392385861, 14.962334392385861, 14.957429395595303, 14.957429395595303, 14.953568887352041, 14.953568887352041, 14.948548302693771, 14.948548302693771, 14.945167884771239, 14.945167884771239, 14.940572465174537, 14.940572465174537, 14.936861141832518, 14.936861141832518, 14.931906107640428, 14.931906107640428, 14.927219898398723, 14.927219898398723, 14.921427580941707, 14.921427580941707, 14.91592475619714, 14.91592475619714, 14.910827079437475, 14.910827079437475, 14.90399212146379, 14.90399212146379, 14.897887136036417, 14.897887136036417, 14.891130476962763, 14.891130476962763, 14.883405497521546, 14.883405497521546, 14.876434503668987, 14.876434503668987, 14.870076791929769, 14.870076791929769, 14.862470074033991, 14.862470074033991, 14.853101924486802, 14.853101924486802, 14.845417890954725, 14.845417890954725, 14.834854591138358, 14.834854591138358, 14.82487867160691, 14.82487867160691, 14.817333893722857, 14.817333893722857, 14.80795542406726, 14.80795542406726, 14.799736508431591, 14.799736508431591, 14.789248058469765, 14.789248058469765, 14.7801175136321, 14.7801175136321, 14.77151478230201, 14.77151478230201, 14.762483431482917, 14.762483431482917, 14.75140910811959, 14.75140910811959, 14.742427769315322, 14.742427769315322, 14.731695495637132, 14.731695495637132, 14.723316727651351, 14.723316727651351, 14.714085420344661, 14.714085420344661, 14.705044067153839, 14.705044067153839, 14.695511757105502, 14.695511757105502, 14.684106161453188, 14.684106161453188, 14.673362900138697, 14.673362900138697, 14.662126777303884, 14.662126777303884, 14.650294122378542, 14.650294122378542, 14.637133503588467, 14.637133503588467, 14.625885500549552, 14.625885500549552, 14.613041318879013, 14.613041318879013, 14.600491228516, 14.600491228516, 14.589826301169238, 14.589826301169238, 14.579097284458562, 14.579097284458562, 14.567445029812177, 14.567445029812177, 14.555065538321779, 14.555065538321779, 14.543083171721651, 14.543083171721651, 14.530543871653219, 14.530543871653219, 14.519732090172331, 14.519732090172331, 14.50728664083606, 14.50728664083606, 14.494761059082773, 14.494761059082773, 14.480759862525757, 14.480759862525757, 14.466954078017151, 14.466954078017151, 14.452655312592428, 14.452655312592428, 14.43861439698937, 14.43861439698937, 14.421950182244203, 14.421950182244203, 14.404714317939641, 14.404714317939641, 15, 15.025881631884008, 15.025881631884008, 14.919856780977506, 14.919856780977506, 14.84340539956636, 14.84340539956636, 14.768172517785956, 14.768172517785956, 14.753355341717914, 14.753355341717914, 14.710325587285196, 14.710325587285196, 14.65501286735965, 14.65501286735965, 14.558960244492898, 14.558960244492898, 14.343261540533113, 14.343261540533113, 14.112473629068363, 14.112473629068363, 13.923048492146386, 13.923048492146386, 13.716505105851384, 13.716505105851384, 13.536396160701718, 13.536396160701718, 13.382627368919778, 13.382627368919778, 13.273403497288376, 13.273403497288376, 13.18737339314849, 13.18737339314849, 13.15696932845709, 13.15696932845709, 13.046690159522171, 13.046690159522171, 12.961691639243096, 12.961691639243096, 12.904545878763365, 12.904545878763365, 12.853989386327374, 12.853989386327374, 12.856562555701977, 12.856562555701977, 12.89695026210208, 12.89695026210208, 12.99401382064389, 12.99401382064389, 13.064986472742175, 13.064986472742175, 13.200100005296521, 13.200100005296521, 13.356245186734787, 13.356245186734787, 13.581858258648817, 13.581858258648817, 13.779446331861786, 13.779446331861786, 14.020887197803892, 14.020887197803892, 14.322226633251981, 14.322226633251981, 14.607966995872808, 14.607966995872808, 14.80045909939326, 14.80045909939326, 14.974742020331096, 14.974742020331096, 15.014139514654353, 15.014139514654353, 15.031590488973418, 15.031590488973418, 14.942284460374912, 14.942284460374912, 14.810526845162071, 14.810526845162071, 14.71725604402707, 14.71725604402707, 14.654423668399897, 14.654423668399897, 14.59904128346401, 14.59904128346401, 14.452865602940358, 14.452865602940358, 14.282261478879674, 14.282261478879674, 14.149772009038367, 14.149772009038367, 14.027052069983485, 14.027052069983485, 13.859992607077059, 13.859992607077059, 13.726038665079807, 13.726038665079807, 13.542762810472052, 13.542762810472052, 13.426206655218582, 13.426206655218582, 13.293233924236567, 13.293233924236567, 13.147791616712704, 13.147791616712704, 13.006610763951292, 13.006610763951292, 12.84823986731333, 12.84823986731333, 12.693804885133208, 12.693804885133208, 12.498890192871052, 12.498890192871052, 12.325809989121367, 12.325809989121367, 12.151607078337484, 12.151607078337484, 11.98176127509246, 11.98176127509246, 11.761719359770526, 11.761719359770526, 11.535738338854555, 11.535738338854555, 11.356031924588308, 11.356031924588308, 11.166858150706151, 11.166858150706151, 11.013537609868145, 11.013537609868145, 10.940785833361874, 10.940785833361874, 10.880470893076224, 10.880470893076224, 10.810492031684296, 10.810492031684296, 10.738828174758915, 10.738828174758915, 10.732227365833888, 10.732227365833888, 10.74063259552893, 10.74063259552893, 10.754970118090359, 10.754970118090359, 10.733785904628672, 10.733785904628672, 10.787976887758164, 10.787976887758164, 10.88944458640169, 10.88944458640169, 11.04254907916619, 11.04254907916619, 11.228202407568958, 11.228202407568958, 11.482818264639777, 11.482818264639777, 11.69687181566044, 11.69687181566044, 11.906283961960796, 11.906283961960796, 12.151929632994989, 12.151929632994989, 12.442078661195602, 12.442078661195602, 12.685614756768384, 12.685614756768384, 12.882246373678006, 12.882246373678006, 13.098033807459965, 13.098033807459965, 13.265644619378074, 13.265644619378074, 13.488205244369283, 13.488205244369283, 13.801786381602861, 13.801786381602861, 14.15661507092392, 14.15661507092392, 14.571319896228996, 14.571319896228996, 14.900498464260913, 14.900498464260913, 15.264447207321453, 15.264447207321453, 15.531123380217505, 15.531123380217505, 15.924513627073946, 15.924513627073946, 16.19019922374802, 16.19019922374802, 16.322098263657374, 16.322098263657374, 16.304174332335062, 16.304174332335062, 16.340241196629936, 16.340241196629936, 16.268904220202955, 16.268904220202955, 16.086253203878236, 16.086253203878236, 15.782468169262778, 15.782468169262778, 15.374958294571538, 15.374958294571538, 15, 15.012940815942004, 15.012940815942004, 14.98636610132836, 14.98636610132836, 14.971810745493599, 14.971810745493599, 14.959082346076983, 14.959082346076983, 14.960947875173133, 14.960947875173133, 14.95565263271521, 14.95565263271521, 14.943059453110807, 14.943059453110807, 14.920042423099233, 14.920042423099233, 14.859798697725925, 14.859798697725925, 14.797521921922066, 14.797521921922066, 14.746699458020705, 14.746699458020705, 14.686175690662845, 14.686175690662845, 14.631471102128723, 14.631471102128723, 14.58023065366825, 14.58023065366825, 14.537568554812667, 14.537568554812667, 14.500231317119468, 14.500231317119468, 14.474722857563513, 14.474722857563513, 14.4220647350196, 14.4220647350196, 14.376180825464203, 14.376180825464203, 14.335464151009303, 14.335464151009303, 14.295170307805137, 14.295170307805137, 14.263049608683579, 14.263049608683579, 14.243626386186193, 14.243626386186193, 14.231930990766053, 14.231930990766053, 14.208866161776603, 14.208866161776603, 14.202879759057403, 14.202879759057403, 14.198542451693676, 14.198542451693676, 14.205568788947831, 14.205568788947831, 14.202391682296767, 14.202391682296767, 14.211179246898407, 14.211179246898407, 14.22809282401728, 14.22809282401728, 14.240716868942075, 14.240716868942075, 14.233201323513999, 14.233201323513999, 14.225227297004473, 14.225227297004473, 14.189429886330164, 14.189429886330164, 14.147165369806896, 14.147165369806896, 14.08333714510193, 14.08333714510193, 14.019069291306938, 14.019069291306938, 13.961481416227368, 13.961481416227368, 13.913958049210835, 13.913958049210835, 13.866151471260338, 13.866151471260338, 13.801817295121142, 13.801817295121142, 13.737042236766802, 13.737042236766802, 13.678767238942457, 13.678767238942457, 13.628052525015123, 13.628052525015123, 13.56643704645608, 13.56643704645608, 13.515035696227566, 13.515035696227566, 13.450876501139497, 13.450876501139497, 13.402818129238593, 13.402818129238593, 13.348944553667687, 13.348944553667687, 13.293373264063145, 13.293373264063145, 13.239891656584982, 13.239891656584982, 13.178310915340727, 13.178310915340727, 13.11914363309317, 13.11914363309317, 13.04834605494057, 13.04834605494057, 12.980008418510142, 12.980008418510142, 12.912100563936535, 12.912100563936535, 12.84548257168026, 12.84548257168026, 12.761653328708682, 12.761653328708682, 12.670680742782599, 12.670680742782599, 12.593746048181327, 12.593746048181327, 12.505966192387636, 12.505966192387636, 12.426975415778585, 12.426975415778585, 12.372987114877688, 12.372987114877688, 12.316124888297376, 12.316124888297376, 12.25624784136798, 12.25624784136798, 12.188780748399955, 12.188780748399955, 12.139029429691613, 12.139029429691613, 12.091613175035052, 12.091613175035052, 12.042152685505714, 12.042152685505714, 11.977247905600317, 11.977247905600317, 11.933433733774168, 11.933433733774168, 11.89504783502318, 11.89504783502318, 11.871147080760428, 11.871147080760428, 11.850217659047976, 11.850217659047976, 11.84192192212905, 11.84192192212905, 11.82311969344896, 11.82311969344896, 11.798468322241224, 11.798468322241224, 11.781618541251447, 11.781618541251447, 11.771189982727265, 11.771189982727265, 11.752590059889691, 11.752590059889691, 11.725074162195554, 11.725074162195554, 11.707552281866988, 11.707552281866988, 11.681614136981478, 11.681614136981478, 11.667586378488018, 11.667586378488018, 11.674231291283325, 11.674231291283325, 11.689501880321215, 11.689501880321215, 11.71312985613572, 11.71312985613572, 11.729541695595978, 11.729541695595978, 11.756346252143663, 11.756346252143663, 11.776821825896544, 11.776821825896544, 11.823144360448932, 11.823144360448932, 11.858480184796978, 11.858480184796978, 11.887381186413212, 11.887381186413212, 11.903274853981108, 11.903274853981108, 11.934053284575308, 11.934053284575308, 11.959946529310686, 11.959946529310686, 11.981458643093886, 11.981458643093886, 11.986109221284174, 11.986109221284174, 11.98062484432249, 11.98062484432249 ], "yaxis": "y" }, { "hovertemplate": "color=9
x=%{x}
y=%{y}", "legendgroup": "9", "line": { "color": "#FF97FF", "dash": "solid" }, "marker": { "symbol": "circle" }, "mode": "lines", "name": "9", "showlegend": true, "type": "scattergl", "x": [ 100, 99.29993160631898, 99.29993160631898, 99.38148169571427, 99.38148169571427, 99.33344287701127, 99.33344287701127, 99.78052429956195, 99.78052429956195, 99.54958970085868, 99.54958970085868, 99.5415288602601, 99.5415288602601, 99.20043010937233, 99.20043010937233, 98.38175972088112, 98.38175972088112, 98.08171337358606, 98.08171337358606, 98.3146135545321, 98.3146135545321, 98.15163483592876, 98.15163483592876, 98.2617316271704, 98.2617316271704, 98.4307104729456, 98.4307104729456, 98.78953357215462, 98.78953357215462, 98.79985727776051, 98.79985727776051, 99.23692266333096, 99.23692266333096, 98.39279376646044, 98.39279376646044, 98.38874784974972, 98.38874784974972, 98.47174801810372, 98.47174801810372, 98.2916973612909, 98.2916973612909, 98.77808827688989, 98.77808827688989, 98.74409721517681, 98.74409721517681, 99.24190042277999, 99.24190042277999, 98.84599456847697, 98.84599456847697, 99.09135177709153, 99.09135177709153, 99.10434894166539, 99.10434894166539, 99.57328874254877, 99.57328874254877, 99.21501237298247, 99.21501237298247, 99.25020700392601, 99.25020700392601, 99.63288351336783, 99.63288351336783, 99.40473856709445, 99.40473856709445, 98.7710291940686, 98.7710291940686, 98.5407493936721, 98.5407493936721, 97.7508566239193, 97.7508566239193, 97.71072647387824, 97.71072647387824, 97.06612114764668, 97.06612114764668, 96.60023270185529, 96.60023270185529, 96.97950519720334, 96.97950519720334, 97.13875284807816, 97.13875284807816, 97.28197178315625, 97.28197178315625, 96.58033571299049, 96.58033571299049, 96.25643172904921, 96.25643172904921, 96.6261400000404, 96.6261400000404, 96.52079469759674, 96.52079469759674, 96.14265950886788, 96.14265950886788, 96.29506225210642, 96.29506225210642, 95.82910831575578, 95.82910831575578, 96.35112441973347, 96.35112441973347, 96.16329269178928, 96.16329269178928, 95.87027246972195, 95.87027246972195, 95.7307727305111, 95.7307727305111, 95.52782525481386, 95.52782525481386, 95.3266966060663, 95.3266966060663, 94.73244989096955, 94.73244989096955, 94.85863986535756, 94.85863986535756, 94.5348526851931, 94.5348526851931, 94.27697635190073, 94.27697635190073, 93.47026915554588, 93.47026915554588, 93.23682795968988, 93.23682795968988, 93.37231139151324, 93.37231139151324, 93.15534439539415, 93.15534439539415, 93.24217287585641, 93.24217287585641, 93.78860723896459, 93.78860723896459, 93.77560714675685, 93.77560714675685, 93.0999726791823, 93.0999726791823, 92.90606801326578, 92.90606801326578, 93.2831221906634, 93.2831221906634, 93.01583352672039, 93.01583352672039, 92.70359835023112, 92.70359835023112, 92.00530036542673, 92.00530036542673, 92.42100834060409, 92.42100834060409, 92.7895835919253, 92.7895835919253, 92.73717490018763, 92.73717490018763, 92.76883196952322, 92.76883196952322, 93.08317487684629, 93.08317487684629, 92.33451766496589, 92.33451766496589, 92.13498897315472, 92.13498897315472, 92.09928886790658, 92.09928886790658, 92.22680948420437, 92.22680948420437, 91.62546599412939, 91.62546599412939, 91.12033628158707, 91.12033628158707, 90.91703470428618, 90.91703470428618, 90.51203613658468, 90.51203613658468, 90.76461607129751, 90.76461607129751, 91.12216656725413, 91.12216656725413, 91.25249379875453, 91.25249379875453, 91.58012004487541, 91.58012004487541, 91.06486472813755, 91.06486472813755, 91.18797649222013, 91.18797649222013, 90.69671638734081, 90.69671638734081, 91.26790712942591, 91.26790712942591, 90.79702047570592, 90.79702047570592, 90.23186056687439, 90.23186056687439, 89.67634735880623, 89.67634735880623, 90.06987166421722, 90.06987166421722, 89.65940405481305, 89.65940405481305, 89.14786912937605, 89.14786912937605, 88.68086196244481, 88.68086196244481, 88.08424380115036, 88.08424380115036, 87.92914636627808, 87.92914636627808, 100, 92.99931606318984, 92.99931606318984, 93.74968330870446, 93.74968330870446, 93.35200242595599, 93.35200242595599, 97.61217815984494, 97.61217815984494, 95.54997817570786, 95.54997817570786, 95.635092884268, 95.635092884268, 92.61880754039443, 92.61880754039443, 85.39231796273906, 85.39231796273906, 83.12912862094319, 83.12912862094319, 85.40561642328275, 85.40561642328275, 84.62039860344953, 84.62039860344953, 86.16474388636449, 86.16474388636449, 88.32785188924211, 88.32785188924211, 92.10765900299248, 92.10765900299248, 93.26077770768009, 93.26077770768009, 97.9845294627281, 97.9845294627281, 91.85128228934461, 91.85128228934461, 92.94825282196534, 92.94825282196534, 94.908060967487, 94.908060967487, 94.71326538271349, 94.71326538271349, 100.13862169564187, 100.13862169564187, 101.27435286478284, 101.27435286478284, 107.18723419784558, 107.18723419784558, 105.11150551338793, 105.11150551338793, 108.89332418604562, 108.89332418604562, 110.45800926706632, 110.45800926706632, 116.48523146511381, 116.48523146511381, 114.1292438507272, 114.1292438507272, 115.6710564645791, 115.6710564645791, 120.72623435030194, 120.72623435030194, 118.93046533906094, 118.93046533906094, 112.25835075871757, 112.25835075871757, 110.00527663324144, 110.00527663324144, 101.43663074912372, 101.43663074912372, 101.02867217786005, 101.02867217786005, 94.33053060847377, 94.33053060847377, 89.75476827975842, 89.75476827975842, 93.29245542951959, 93.29245542951959, 94.9186805787271, 94.9186805787271, 96.46551527277536, 96.46551527277536, 89.87389035969865, 89.87389035969865, 87.16376777592785, 87.16376777592785, 90.71447055509934, 90.71447055509934, 90.19536558085994, 90.19536558085994, 87.37997504032674, 87.37997504032674, 89.23463194487961, 89.23463194487961, 85.88495474723042, 85.88495474723042, 90.91229934650016, 90.91229934650016, 90.15196996137051, 90.15196996137051, 88.67602042222708, 88.67602042222708, 88.50743002514825, 88.50743002514825, 87.96325417167918, 87.96325417167918, 87.47813607760847, 87.47813607760847, 84.01053269460503, 84.01053269460503, 86.21927941269837, 86.21927941269837, 85.20026287932083, 85.20026287932083, 84.74514940369397, 84.74514940369397, 80.44680552355874, 80.44680552355874, 80.41520185078912, 80.41520185078912, 83.13776682112793, 83.13776682112793, 83.62311825579216, 83.62311825579216, 86.27091768763398, 86.27091768763398, 92.29068344923925, 92.29068344923925, 94.59113655600862, 94.59113655600862, 92.23253576603186, 92.23253576603186, 93.36203549432568, 93.36203549432568, 98.80311561440442, 98.80311561440442, 99.52383859763862, 99.52383859763862, 100.02610961464065, 100.02610961464065, 97.48148429129367, 97.48148429129367, 103.34545533154333, 103.34545533154333, 109.43020057074936, 109.43020057074936, 112.12304973808557, 112.12304973808557, 115.52003033279902, 115.52003033279902, 121.55801868602819, 121.55801868602819, 117.08958909341867, 117.08958909341867, 117.75922193520242, 117.75922193520242, 119.85458925018938, 119.85458925018938, 123.66274001251523, 123.66274001251523, 119.15604184133105, 119.15604184133105, 115.53291901293304, 115.53291901293304, 114.89363074478746, 114.89363074478746, 111.82198288405428, 111.82198288405428, 115.87910014654939, 115.87910014654939, 121.11836567425608, 121.11836567425608, 123.6936575690804, 123.6936575690804, 128.58085298226052, 128.58085298226052, 121.95792293344105, 121.95792293344105, 123.60374048079915, 123.60374048079915, 116.48935752258258, 116.48935752258258, 123.55808091733965, 123.55808091733965, 115.82597098962636, 115.82597098962636, 106.77349871746914, 106.77349871746914, 98.16867422379417, 98.16867422379417, 101.74594768140646, 101.74594768140646, 95.1243047124417, 95.1243047124417, 87.65512294066052, 87.65512294066052, 81.34224880318148, 81.34224880318148, 74.25512295493493, 74.25512295493493, 72.08158085400078, 72.08158085400078, 100, 96.49965803159492, 96.49965803159492, 96.89282234085528, 96.89282234085528, 96.66395700156504, 96.66395700156504, 98.84511851049147, 98.84511851049147, 97.72022468264952, 97.72022468264952, 97.69539195252099, 97.69539195252099, 96.04474200505408, 96.04474200505408, 92.12122707795169, 92.12122707795169, 90.7524578823741, 90.7524578823741, 91.86620599866295, 91.86620599866295, 91.18321550679761, 91.18321550679761, 91.77076300242805, 91.77076300242805, 92.64886983215455, 92.64886983215455, 94.4115531951917, 94.4115531951917, 94.60105803410664, 94.60105803410664, 96.77426923210655, 96.77426923210655, 92.95584004241334, 92.95584004241334, 93.0988602155345, 93.0988602155345, 93.66372732853505, 93.66372732853505, 93.03719912084956, 93.03719912084956, 95.452716939988, 95.452716939988, 95.51738150606599, 95.51738150606599, 98.05425788440175, 98.05425788440175, 96.45618107548292, 96.45618107548292, 97.85694974565604, 97.85694974565604, 98.17927424291095, 98.17927424291095, 100.65800191623217, 100.65800191623217, 99.23013457226213, 99.23013457226213, 99.68075990493776, 99.68075990493776, 101.76892968159176, 101.76892968159176, 100.93152794995164, 100.93152794995164, 98.15507445203599, 98.15507445203599, 97.32448920917646, 97.32448920917646, 93.8712393709979, 93.8712393709979, 93.94055110646606, 93.94055110646606, 91.25561322951836, 91.25561322951836, 89.45152914637421, 89.45152914637421, 91.38648456820863, 91.38648456820863, 92.40702828733023, 92.40702828733023, 93.37466906480901, 93.37466906480901, 90.60421743023397, 90.60421743023397, 89.54727537765943, 89.54727537765943, 91.50562818437629, 91.50562818437629, 91.43629555560625, 91.43629555560625, 90.22387819072098, 90.22387819072098, 91.286734506583, 91.286734506583, 89.70792037849891, 89.70792037849891, 92.36523442648821, 92.36523442648821, 92.01299752297405, 92.01299752297405, 91.26989588133198, 91.26989588133198, 91.16338302394053, 91.16338302394053, 90.8266416539283, 90.8266416539283, 90.48973346931841, 90.48973346931841, 88.53135087902336, 88.53135087902336, 89.58435442398849, 89.58435442398849, 88.8253866031861, 88.8253866031861, 88.3389425664917, 88.3389425664917, 85.6690510129246, 85.6690510129246, 85.33734615018504, 85.33734615018504, 86.51603920143914, 86.51603920143914, 86.33828493348129, 86.33828493348129, 87.36304955582791, 87.36304955582791, 90.23284652388249, 90.23284652388249, 90.91718361444943, 90.91718361444943, 88.99242906220593, 88.99242906220593, 88.99938883525597, 88.99938883525597, 91.30743180141197, 91.30743180141197, 91.05295854841216, 91.05295854841216, 90.67174729743687, 90.67174729743687, 88.7604154487307, 88.7604154487307, 91.21667934978741, 91.21667934978741, 93.6338256538187, 93.6338256538187, 94.37558676757705, 94.37558676757705, 95.47321941160612, 95.47321941160612, 97.77075917390104, 97.77075917390104, 95.59282238220855, 95.59282238220855, 95.72059903293992, 95.72059903293992, 96.52854695498216, 96.52854695498216, 98.09563460829936, 98.09563460829936, 96.51532722863074, 96.51532722863074, 95.4085247939158, 95.4085247939158, 95.52465821995634, 95.52465821995634, 94.8087017899729, 94.8087017899729, 96.88999312951138, 96.88999312951138, 99.41181607140739, 99.41181607140739, 101.0349689701463, 101.0349689701463, 103.52291722549926, 103.52291722549926, 102.29402709966891, 102.29402709966891, 103.89599855840412, 103.89599855840412, 102.66305598951656, 102.66305598951656, 106.35128198458621, 106.35128198458621, 105.2153347445648, 105.2153347445648, 103.54761969318548, 103.54761969318548, 101.9104419064554, 101.9104419064554, 104.68762728033715, 104.68762728033715, 103.74561762296544, 103.74561762296544, 102.29177188240789, 102.29177188240789, 100.99065500957371, 100.99065500957371, 99.08829773238939, 99.08829773238939, 99.25050915772879, 99.25050915772879 ], "xaxis": "x", "y": [ 15, 15.0025881631884, 15.0025881631884, 15.001496702185737, 15.001496702185737, 15.002361804039465, 15.002361804039465, 15.003883708196188, 15.003883708196188, 15.00568393679195, 15.00568393679195, 15.007415489103332, 15.007415489103332, 15.007679903819312, 15.007679903819312, 15.00785846437848, 15.00785846437848, 15.005149988731267, 15.005149988731267, 15.003693218370183, 15.003693218370183, 15.003201208353792, 15.003201208353792, 15.001441720795848, 15.001441720795848, 15.000133583406503, 15.000133583406503, 14.998369352308925, 14.998369352308925, 14.996174666815067, 14.996174666815067, 14.994789169151316, 14.994789169151316, 14.99321394632609, 14.99321394632609, 14.990466967358335, 14.990466967358335, 14.98892812664762, 14.98892812664762, 14.987709914471244, 14.987709914471244, 14.987290241379329, 14.987290241379329, 14.985547623238297, 14.985547623238297, 14.986392330287694, 14.986392330287694, 14.9857180023299, 14.9857180023299, 14.984461841594834, 14.984461841594834, 14.985073680988108, 14.985073680988108, 14.985562867120061, 14.985562867120061, 14.98541282187458, 14.98541282187458, 14.984719710317288, 14.984719710317288, 14.985916999281203, 14.985916999281203, 14.98625696832826, 14.98625696832826, 14.986605681348385, 14.986605681348385, 14.985955421994834, 14.985955421994834, 14.986129886338091, 14.986129886338091, 14.984477177626776, 14.984477177626776, 14.981225059271852, 14.981225059271852, 14.976432391666856, 14.976432391666856, 14.973674166171941, 14.973674166171941, 14.96980019046312, 14.96980019046312, 14.966768040636888, 14.966768040636888, 14.962334392385861, 14.962334392385861, 14.957429395595303, 14.957429395595303, 14.953568887352041, 14.953568887352041, 14.948548302693771, 14.948548302693771, 14.945167884771239, 14.945167884771239, 14.940572465174537, 14.940572465174537, 14.936861141832518, 14.936861141832518, 14.931906107640428, 14.931906107640428, 14.927219898398723, 14.927219898398723, 14.921427580941707, 14.921427580941707, 14.91592475619714, 14.91592475619714, 14.910827079437475, 14.910827079437475, 14.90399212146379, 14.90399212146379, 14.897887136036417, 14.897887136036417, 14.891130476962763, 14.891130476962763, 14.883405497521546, 14.883405497521546, 14.876434503668987, 14.876434503668987, 14.870076791929769, 14.870076791929769, 14.862470074033991, 14.862470074033991, 14.853101924486802, 14.853101924486802, 14.845417890954725, 14.845417890954725, 14.834854591138358, 14.834854591138358, 14.82487867160691, 14.82487867160691, 14.817333893722857, 14.817333893722857, 14.80795542406726, 14.80795542406726, 14.799736508431591, 14.799736508431591, 14.789248058469765, 14.789248058469765, 14.7801175136321, 14.7801175136321, 14.77151478230201, 14.77151478230201, 14.762483431482917, 14.762483431482917, 14.75140910811959, 14.75140910811959, 14.742427769315322, 14.742427769315322, 14.731695495637132, 14.731695495637132, 14.723316727651351, 14.723316727651351, 14.714085420344661, 14.714085420344661, 14.705044067153839, 14.705044067153839, 14.695511757105502, 14.695511757105502, 14.684106161453188, 14.684106161453188, 14.673362900138697, 14.673362900138697, 14.662126777303884, 14.662126777303884, 14.650294122378542, 14.650294122378542, 14.637133503588467, 14.637133503588467, 14.625885500549552, 14.625885500549552, 14.613041318879013, 14.613041318879013, 14.600491228516, 14.600491228516, 14.589826301169238, 14.589826301169238, 14.579097284458562, 14.579097284458562, 14.567445029812177, 14.567445029812177, 14.555065538321779, 14.555065538321779, 14.543083171721651, 14.543083171721651, 14.530543871653219, 14.530543871653219, 14.519732090172331, 14.519732090172331, 14.50728664083606, 14.50728664083606, 14.494761059082773, 14.494761059082773, 14.480759862525757, 14.480759862525757, 14.466954078017151, 14.466954078017151, 14.452655312592428, 14.452655312592428, 14.43861439698937, 14.43861439698937, 14.421950182244203, 14.421950182244203, 14.404714317939641, 14.404714317939641, 15, 15.025881631884008, 15.025881631884008, 14.919856780977506, 14.919856780977506, 14.84340539956636, 14.84340539956636, 14.768172517785956, 14.768172517785956, 14.753355341717914, 14.753355341717914, 14.710325587285196, 14.710325587285196, 14.65501286735965, 14.65501286735965, 14.558960244492898, 14.558960244492898, 14.343261540533113, 14.343261540533113, 14.112473629068363, 14.112473629068363, 13.923048492146386, 13.923048492146386, 13.716505105851384, 13.716505105851384, 13.536396160701718, 13.536396160701718, 13.382627368919778, 13.382627368919778, 13.273403497288376, 13.273403497288376, 13.18737339314849, 13.18737339314849, 13.15696932845709, 13.15696932845709, 13.046690159522171, 13.046690159522171, 12.961691639243096, 12.961691639243096, 12.904545878763365, 12.904545878763365, 12.853989386327374, 12.853989386327374, 12.856562555701977, 12.856562555701977, 12.89695026210208, 12.89695026210208, 12.99401382064389, 12.99401382064389, 13.064986472742175, 13.064986472742175, 13.200100005296521, 13.200100005296521, 13.356245186734787, 13.356245186734787, 13.581858258648817, 13.581858258648817, 13.779446331861786, 13.779446331861786, 14.020887197803892, 14.020887197803892, 14.322226633251981, 14.322226633251981, 14.607966995872808, 14.607966995872808, 14.80045909939326, 14.80045909939326, 14.974742020331096, 14.974742020331096, 15.014139514654353, 15.014139514654353, 15.031590488973418, 15.031590488973418, 14.942284460374912, 14.942284460374912, 14.810526845162071, 14.810526845162071, 14.71725604402707, 14.71725604402707, 14.654423668399897, 14.654423668399897, 14.59904128346401, 14.59904128346401, 14.452865602940358, 14.452865602940358, 14.282261478879674, 14.282261478879674, 14.149772009038367, 14.149772009038367, 14.027052069983485, 14.027052069983485, 13.859992607077059, 13.859992607077059, 13.726038665079807, 13.726038665079807, 13.542762810472052, 13.542762810472052, 13.426206655218582, 13.426206655218582, 13.293233924236567, 13.293233924236567, 13.147791616712704, 13.147791616712704, 13.006610763951292, 13.006610763951292, 12.84823986731333, 12.84823986731333, 12.693804885133208, 12.693804885133208, 12.498890192871052, 12.498890192871052, 12.325809989121367, 12.325809989121367, 12.151607078337484, 12.151607078337484, 11.98176127509246, 11.98176127509246, 11.761719359770526, 11.761719359770526, 11.535738338854555, 11.535738338854555, 11.356031924588308, 11.356031924588308, 11.166858150706151, 11.166858150706151, 11.013537609868145, 11.013537609868145, 10.940785833361874, 10.940785833361874, 10.880470893076224, 10.880470893076224, 10.810492031684296, 10.810492031684296, 10.738828174758915, 10.738828174758915, 10.732227365833888, 10.732227365833888, 10.74063259552893, 10.74063259552893, 10.754970118090359, 10.754970118090359, 10.733785904628672, 10.733785904628672, 10.787976887758164, 10.787976887758164, 10.88944458640169, 10.88944458640169, 11.04254907916619, 11.04254907916619, 11.228202407568958, 11.228202407568958, 11.482818264639777, 11.482818264639777, 11.69687181566044, 11.69687181566044, 11.906283961960796, 11.906283961960796, 12.151929632994989, 12.151929632994989, 12.442078661195602, 12.442078661195602, 12.685614756768384, 12.685614756768384, 12.882246373678006, 12.882246373678006, 13.098033807459965, 13.098033807459965, 13.265644619378074, 13.265644619378074, 13.488205244369283, 13.488205244369283, 13.801786381602861, 13.801786381602861, 14.15661507092392, 14.15661507092392, 14.571319896228996, 14.571319896228996, 14.900498464260913, 14.900498464260913, 15.264447207321453, 15.264447207321453, 15.531123380217505, 15.531123380217505, 15.924513627073946, 15.924513627073946, 16.19019922374802, 16.19019922374802, 16.322098263657374, 16.322098263657374, 16.304174332335062, 16.304174332335062, 16.340241196629936, 16.340241196629936, 16.268904220202955, 16.268904220202955, 16.086253203878236, 16.086253203878236, 15.782468169262778, 15.782468169262778, 15.374958294571538, 15.374958294571538, 15, 15.012940815942004, 15.012940815942004, 14.98636610132836, 14.98636610132836, 14.971810745493599, 14.971810745493599, 14.959082346076983, 14.959082346076983, 14.960947875173133, 14.960947875173133, 14.95565263271521, 14.95565263271521, 14.943059453110807, 14.943059453110807, 14.920042423099233, 14.920042423099233, 14.859798697725925, 14.859798697725925, 14.797521921922066, 14.797521921922066, 14.746699458020705, 14.746699458020705, 14.686175690662845, 14.686175690662845, 14.631471102128723, 14.631471102128723, 14.58023065366825, 14.58023065366825, 14.537568554812667, 14.537568554812667, 14.500231317119468, 14.500231317119468, 14.474722857563513, 14.474722857563513, 14.4220647350196, 14.4220647350196, 14.376180825464203, 14.376180825464203, 14.335464151009303, 14.335464151009303, 14.295170307805137, 14.295170307805137, 14.263049608683579, 14.263049608683579, 14.243626386186193, 14.243626386186193, 14.231930990766053, 14.231930990766053, 14.208866161776603, 14.208866161776603, 14.202879759057403, 14.202879759057403, 14.198542451693676, 14.198542451693676, 14.205568788947831, 14.205568788947831, 14.202391682296767, 14.202391682296767, 14.211179246898407, 14.211179246898407, 14.22809282401728, 14.22809282401728, 14.240716868942075, 14.240716868942075, 14.233201323513999, 14.233201323513999, 14.225227297004473, 14.225227297004473, 14.189429886330164, 14.189429886330164, 14.147165369806896, 14.147165369806896, 14.08333714510193, 14.08333714510193, 14.019069291306938, 14.019069291306938, 13.961481416227368, 13.961481416227368, 13.913958049210835, 13.913958049210835, 13.866151471260338, 13.866151471260338, 13.801817295121142, 13.801817295121142, 13.737042236766802, 13.737042236766802, 13.678767238942457, 13.678767238942457, 13.628052525015123, 13.628052525015123, 13.56643704645608, 13.56643704645608, 13.515035696227566, 13.515035696227566, 13.450876501139497, 13.450876501139497, 13.402818129238593, 13.402818129238593, 13.348944553667687, 13.348944553667687, 13.293373264063145, 13.293373264063145, 13.239891656584982, 13.239891656584982, 13.178310915340727, 13.178310915340727, 13.11914363309317, 13.11914363309317, 13.04834605494057, 13.04834605494057, 12.980008418510142, 12.980008418510142, 12.912100563936535, 12.912100563936535, 12.84548257168026, 12.84548257168026, 12.761653328708682, 12.761653328708682, 12.670680742782599, 12.670680742782599, 12.593746048181327, 12.593746048181327, 12.505966192387636, 12.505966192387636, 12.426975415778585, 12.426975415778585, 12.372987114877688, 12.372987114877688, 12.316124888297376, 12.316124888297376, 12.25624784136798, 12.25624784136798, 12.188780748399955, 12.188780748399955, 12.139029429691613, 12.139029429691613, 12.091613175035052, 12.091613175035052, 12.042152685505714, 12.042152685505714, 11.977247905600317, 11.977247905600317, 11.933433733774168, 11.933433733774168, 11.89504783502318, 11.89504783502318, 11.871147080760428, 11.871147080760428, 11.850217659047976, 11.850217659047976, 11.84192192212905, 11.84192192212905, 11.82311969344896, 11.82311969344896, 11.798468322241224, 11.798468322241224, 11.781618541251447, 11.781618541251447, 11.771189982727265, 11.771189982727265, 11.752590059889691, 11.752590059889691, 11.725074162195554, 11.725074162195554, 11.707552281866988, 11.707552281866988, 11.681614136981478, 11.681614136981478, 11.667586378488018, 11.667586378488018, 11.674231291283325, 11.674231291283325, 11.689501880321215, 11.689501880321215, 11.71312985613572, 11.71312985613572, 11.729541695595978, 11.729541695595978, 11.756346252143663, 11.756346252143663, 11.776821825896544, 11.776821825896544, 11.823144360448932, 11.823144360448932, 11.858480184796978, 11.858480184796978, 11.887381186413212, 11.887381186413212, 11.903274853981108, 11.903274853981108, 11.934053284575308, 11.934053284575308, 11.959946529310686, 11.959946529310686, 11.981458643093886, 11.981458643093886, 11.986109221284174, 11.986109221284174, 11.98062484432249, 11.98062484432249 ], "yaxis": "y" }, { "hovertemplate": "color=10
x=%{x}
y=%{y}", "legendgroup": "10", "line": { "color": "#FECB52", "dash": "solid" }, "marker": { "symbol": "circle" }, "mode": "lines", "name": "10", "showlegend": true, "type": "scattergl", "x": [ 100, 99.29993160631898, 99.29993160631898, 99.38148169571427, 99.38148169571427, 99.33344287701127, 99.33344287701127, 99.78052429956195, 99.78052429956195, 99.54958970085868, 99.54958970085868, 99.5415288602601, 99.5415288602601, 99.20043010937233, 99.20043010937233, 98.38175972088112, 98.38175972088112, 98.08171337358606, 98.08171337358606, 98.3146135545321, 98.3146135545321, 98.15163483592876, 98.15163483592876, 98.2617316271704, 98.2617316271704, 98.4307104729456, 98.4307104729456, 98.78953357215462, 98.78953357215462, 98.79985727776051, 98.79985727776051, 99.23692266333096, 99.23692266333096, 98.39279376646044, 98.39279376646044, 98.38874784974972, 98.38874784974972, 98.47174801810372, 98.47174801810372, 98.2916973612909, 98.2916973612909, 98.77808827688989, 98.77808827688989, 98.74409721517681, 98.74409721517681, 99.24190042277999, 99.24190042277999, 98.84599456847697, 98.84599456847697, 99.09135177709153, 99.09135177709153, 99.10434894166539, 99.10434894166539, 99.57328874254877, 99.57328874254877, 99.21501237298247, 99.21501237298247, 99.25020700392601, 99.25020700392601, 99.63288351336783, 99.63288351336783, 99.40473856709445, 99.40473856709445, 98.7710291940686, 98.7710291940686, 98.5407493936721, 98.5407493936721, 97.7508566239193, 97.7508566239193, 97.71072647387824, 97.71072647387824, 97.06612114764668, 97.06612114764668, 96.60023270185529, 96.60023270185529, 96.97950519720334, 96.97950519720334, 97.13875284807816, 97.13875284807816, 97.28197178315625, 97.28197178315625, 96.58033571299049, 96.58033571299049, 96.25643172904921, 96.25643172904921, 96.6261400000404, 96.6261400000404, 96.52079469759674, 96.52079469759674, 96.14265950886788, 96.14265950886788, 96.29506225210642, 96.29506225210642, 95.82910831575578, 95.82910831575578, 96.35112441973347, 96.35112441973347, 96.16329269178928, 96.16329269178928, 95.87027246972195, 95.87027246972195, 95.7307727305111, 95.7307727305111, 95.52782525481386, 95.52782525481386, 95.3266966060663, 95.3266966060663, 94.73244989096955, 94.73244989096955, 94.85863986535756, 94.85863986535756, 94.5348526851931, 94.5348526851931, 94.27697635190073, 94.27697635190073, 93.47026915554588, 93.47026915554588, 93.23682795968988, 93.23682795968988, 93.37231139151324, 93.37231139151324, 93.15534439539415, 93.15534439539415, 93.24217287585641, 93.24217287585641, 93.78860723896459, 93.78860723896459, 93.77560714675685, 93.77560714675685, 93.0999726791823, 93.0999726791823, 92.90606801326578, 92.90606801326578, 93.2831221906634, 93.2831221906634, 93.01583352672039, 93.01583352672039, 92.70359835023112, 92.70359835023112, 92.00530036542673, 92.00530036542673, 92.42100834060409, 92.42100834060409, 92.7895835919253, 92.7895835919253, 92.73717490018763, 92.73717490018763, 92.76883196952322, 92.76883196952322, 93.08317487684629, 93.08317487684629, 92.33451766496589, 92.33451766496589, 92.13498897315472, 92.13498897315472, 92.09928886790658, 92.09928886790658, 92.22680948420437, 92.22680948420437, 91.62546599412939, 91.62546599412939, 91.12033628158707, 91.12033628158707, 90.91703470428618, 90.91703470428618, 90.51203613658468, 90.51203613658468, 90.76461607129751, 90.76461607129751, 91.12216656725413, 91.12216656725413, 91.25249379875453, 91.25249379875453, 91.58012004487541, 91.58012004487541, 91.06486472813755, 91.06486472813755, 91.18797649222013, 91.18797649222013, 90.69671638734081, 90.69671638734081, 91.26790712942591, 91.26790712942591, 90.79702047570592, 90.79702047570592, 90.23186056687439, 90.23186056687439, 89.67634735880623, 89.67634735880623, 90.06987166421722, 90.06987166421722, 89.65940405481305, 89.65940405481305, 89.14786912937605, 89.14786912937605, 88.68086196244481, 88.68086196244481, 88.08424380115036, 88.08424380115036, 87.92914636627808, 87.92914636627808, 100, 92.99931606318984, 92.99931606318984, 93.74968330870446, 93.74968330870446, 93.35200242595599, 93.35200242595599, 97.61217815984494, 97.61217815984494, 95.54997817570786, 95.54997817570786, 95.635092884268, 95.635092884268, 92.61880754039443, 92.61880754039443, 85.39231796273906, 85.39231796273906, 83.12912862094319, 83.12912862094319, 85.40561642328275, 85.40561642328275, 84.62039860344953, 84.62039860344953, 86.16474388636449, 86.16474388636449, 88.32785188924211, 88.32785188924211, 92.10765900299248, 92.10765900299248, 93.26077770768009, 93.26077770768009, 97.9845294627281, 97.9845294627281, 91.85128228934461, 91.85128228934461, 92.94825282196534, 92.94825282196534, 94.908060967487, 94.908060967487, 94.71326538271349, 94.71326538271349, 100.13862169564187, 100.13862169564187, 101.27435286478284, 101.27435286478284, 107.18723419784558, 107.18723419784558, 105.11150551338793, 105.11150551338793, 108.89332418604562, 108.89332418604562, 110.45800926706632, 110.45800926706632, 116.48523146511381, 116.48523146511381, 114.1292438507272, 114.1292438507272, 115.6710564645791, 115.6710564645791, 120.72623435030194, 120.72623435030194, 118.93046533906094, 118.93046533906094, 112.25835075871757, 112.25835075871757, 110.00527663324144, 110.00527663324144, 101.43663074912372, 101.43663074912372, 101.02867217786005, 101.02867217786005, 94.33053060847377, 94.33053060847377, 89.75476827975842, 89.75476827975842, 93.29245542951959, 93.29245542951959, 94.9186805787271, 94.9186805787271, 96.46551527277536, 96.46551527277536, 89.87389035969865, 89.87389035969865, 87.16376777592785, 87.16376777592785, 90.71447055509934, 90.71447055509934, 90.19536558085994, 90.19536558085994, 87.37997504032674, 87.37997504032674, 89.23463194487961, 89.23463194487961, 85.88495474723042, 85.88495474723042, 90.91229934650016, 90.91229934650016, 90.15196996137051, 90.15196996137051, 88.67602042222708, 88.67602042222708, 88.50743002514825, 88.50743002514825, 87.96325417167918, 87.96325417167918, 87.47813607760847, 87.47813607760847, 84.01053269460503, 84.01053269460503, 86.21927941269837, 86.21927941269837, 85.20026287932083, 85.20026287932083, 84.74514940369397, 84.74514940369397, 80.44680552355874, 80.44680552355874, 80.41520185078912, 80.41520185078912, 83.13776682112793, 83.13776682112793, 83.62311825579216, 83.62311825579216, 86.27091768763398, 86.27091768763398, 92.29068344923925, 92.29068344923925, 94.59113655600862, 94.59113655600862, 92.23253576603186, 92.23253576603186, 93.36203549432568, 93.36203549432568, 98.80311561440442, 98.80311561440442, 99.52383859763862, 99.52383859763862, 100.02610961464065, 100.02610961464065, 97.48148429129367, 97.48148429129367, 103.34545533154333, 103.34545533154333, 109.43020057074936, 109.43020057074936, 112.12304973808557, 112.12304973808557, 115.52003033279902, 115.52003033279902, 121.55801868602819, 121.55801868602819, 117.08958909341867, 117.08958909341867, 117.75922193520242, 117.75922193520242, 119.85458925018938, 119.85458925018938, 123.66274001251523, 123.66274001251523, 119.15604184133105, 119.15604184133105, 115.53291901293304, 115.53291901293304, 114.89363074478746, 114.89363074478746, 111.82198288405428, 111.82198288405428, 115.87910014654939, 115.87910014654939, 121.11836567425608, 121.11836567425608, 123.6936575690804, 123.6936575690804, 128.58085298226052, 128.58085298226052, 121.95792293344105, 121.95792293344105, 123.60374048079915, 123.60374048079915, 116.48935752258258, 116.48935752258258, 123.55808091733965, 123.55808091733965, 115.82597098962636, 115.82597098962636, 106.77349871746914, 106.77349871746914, 98.16867422379417, 98.16867422379417, 101.74594768140646, 101.74594768140646, 95.1243047124417, 95.1243047124417, 87.65512294066052, 87.65512294066052, 81.34224880318148, 81.34224880318148, 74.25512295493493, 74.25512295493493, 72.08158085400078, 72.08158085400078, 100, 96.49965803159492, 96.49965803159492, 96.89282234085528, 96.89282234085528, 96.66395700156504, 96.66395700156504, 98.84511851049147, 98.84511851049147, 97.72022468264952, 97.72022468264952, 97.69539195252099, 97.69539195252099, 96.04474200505408, 96.04474200505408, 92.12122707795169, 92.12122707795169, 90.7524578823741, 90.7524578823741, 91.86620599866295, 91.86620599866295, 91.18321550679761, 91.18321550679761, 91.77076300242805, 91.77076300242805, 92.64886983215455, 92.64886983215455, 94.4115531951917, 94.4115531951917, 94.60105803410664, 94.60105803410664, 96.77426923210655, 96.77426923210655, 92.95584004241334, 92.95584004241334, 93.0988602155345, 93.0988602155345, 93.66372732853505, 93.66372732853505, 93.03719912084956, 93.03719912084956, 95.452716939988, 95.452716939988, 95.51738150606599, 95.51738150606599, 98.05425788440175, 98.05425788440175, 96.45618107548292, 96.45618107548292, 97.85694974565604, 97.85694974565604, 98.17927424291095, 98.17927424291095, 100.65800191623217, 100.65800191623217, 99.23013457226213, 99.23013457226213, 99.68075990493776, 99.68075990493776, 101.76892968159176, 101.76892968159176, 100.93152794995164, 100.93152794995164, 98.15507445203599, 98.15507445203599, 97.32448920917646, 97.32448920917646, 93.8712393709979, 93.8712393709979, 93.94055110646606, 93.94055110646606, 91.25561322951836, 91.25561322951836, 89.45152914637421, 89.45152914637421, 91.38648456820863, 91.38648456820863, 92.40702828733023, 92.40702828733023, 93.37466906480901, 93.37466906480901, 90.60421743023397, 90.60421743023397, 89.54727537765943, 89.54727537765943, 91.50562818437629, 91.50562818437629, 91.43629555560625, 91.43629555560625, 90.22387819072098, 90.22387819072098, 91.286734506583, 91.286734506583, 89.70792037849891, 89.70792037849891, 92.36523442648821, 92.36523442648821, 92.01299752297405, 92.01299752297405, 91.26989588133198, 91.26989588133198, 91.16338302394053, 91.16338302394053, 90.8266416539283, 90.8266416539283, 90.48973346931841, 90.48973346931841, 88.53135087902336, 88.53135087902336, 89.58435442398849, 89.58435442398849, 88.8253866031861, 88.8253866031861, 88.3389425664917, 88.3389425664917, 85.6690510129246, 85.6690510129246, 85.33734615018504, 85.33734615018504, 86.51603920143914, 86.51603920143914, 86.33828493348129, 86.33828493348129, 87.36304955582791, 87.36304955582791, 90.23284652388249, 90.23284652388249, 90.91718361444943, 90.91718361444943, 88.99242906220593, 88.99242906220593, 88.99938883525597, 88.99938883525597, 91.30743180141197, 91.30743180141197, 91.05295854841216, 91.05295854841216, 90.67174729743687, 90.67174729743687, 88.7604154487307, 88.7604154487307, 91.21667934978741, 91.21667934978741, 93.6338256538187, 93.6338256538187, 94.37558676757705, 94.37558676757705, 95.47321941160612, 95.47321941160612, 97.77075917390104, 97.77075917390104, 95.59282238220855, 95.59282238220855, 95.72059903293992, 95.72059903293992, 96.52854695498216, 96.52854695498216, 98.09563460829936, 98.09563460829936, 96.51532722863074, 96.51532722863074, 95.4085247939158, 95.4085247939158, 95.52465821995634, 95.52465821995634, 94.8087017899729, 94.8087017899729, 96.88999312951138, 96.88999312951138, 99.41181607140739, 99.41181607140739, 101.0349689701463, 101.0349689701463, 103.52291722549926, 103.52291722549926, 102.29402709966891, 102.29402709966891, 103.89599855840412, 103.89599855840412, 102.66305598951656, 102.66305598951656, 106.35128198458621, 106.35128198458621, 105.2153347445648, 105.2153347445648, 103.54761969318548, 103.54761969318548, 101.9104419064554, 101.9104419064554, 104.68762728033715, 104.68762728033715, 103.74561762296544, 103.74561762296544, 102.29177188240789, 102.29177188240789, 100.99065500957371, 100.99065500957371, 99.08829773238939, 99.08829773238939, 99.25050915772879, 99.25050915772879 ], "xaxis": "x", "y": [ 15, 15.0025881631884, 15.0025881631884, 15.001496702185737, 15.001496702185737, 15.002361804039465, 15.002361804039465, 15.003883708196188, 15.003883708196188, 15.00568393679195, 15.00568393679195, 15.007415489103332, 15.007415489103332, 15.007679903819312, 15.007679903819312, 15.00785846437848, 15.00785846437848, 15.005149988731267, 15.005149988731267, 15.003693218370183, 15.003693218370183, 15.003201208353792, 15.003201208353792, 15.001441720795848, 15.001441720795848, 15.000133583406503, 15.000133583406503, 14.998369352308925, 14.998369352308925, 14.996174666815067, 14.996174666815067, 14.994789169151316, 14.994789169151316, 14.99321394632609, 14.99321394632609, 14.990466967358335, 14.990466967358335, 14.98892812664762, 14.98892812664762, 14.987709914471244, 14.987709914471244, 14.987290241379329, 14.987290241379329, 14.985547623238297, 14.985547623238297, 14.986392330287694, 14.986392330287694, 14.9857180023299, 14.9857180023299, 14.984461841594834, 14.984461841594834, 14.985073680988108, 14.985073680988108, 14.985562867120061, 14.985562867120061, 14.98541282187458, 14.98541282187458, 14.984719710317288, 14.984719710317288, 14.985916999281203, 14.985916999281203, 14.98625696832826, 14.98625696832826, 14.986605681348385, 14.986605681348385, 14.985955421994834, 14.985955421994834, 14.986129886338091, 14.986129886338091, 14.984477177626776, 14.984477177626776, 14.981225059271852, 14.981225059271852, 14.976432391666856, 14.976432391666856, 14.973674166171941, 14.973674166171941, 14.96980019046312, 14.96980019046312, 14.966768040636888, 14.966768040636888, 14.962334392385861, 14.962334392385861, 14.957429395595303, 14.957429395595303, 14.953568887352041, 14.953568887352041, 14.948548302693771, 14.948548302693771, 14.945167884771239, 14.945167884771239, 14.940572465174537, 14.940572465174537, 14.936861141832518, 14.936861141832518, 14.931906107640428, 14.931906107640428, 14.927219898398723, 14.927219898398723, 14.921427580941707, 14.921427580941707, 14.91592475619714, 14.91592475619714, 14.910827079437475, 14.910827079437475, 14.90399212146379, 14.90399212146379, 14.897887136036417, 14.897887136036417, 14.891130476962763, 14.891130476962763, 14.883405497521546, 14.883405497521546, 14.876434503668987, 14.876434503668987, 14.870076791929769, 14.870076791929769, 14.862470074033991, 14.862470074033991, 14.853101924486802, 14.853101924486802, 14.845417890954725, 14.845417890954725, 14.834854591138358, 14.834854591138358, 14.82487867160691, 14.82487867160691, 14.817333893722857, 14.817333893722857, 14.80795542406726, 14.80795542406726, 14.799736508431591, 14.799736508431591, 14.789248058469765, 14.789248058469765, 14.7801175136321, 14.7801175136321, 14.77151478230201, 14.77151478230201, 14.762483431482917, 14.762483431482917, 14.75140910811959, 14.75140910811959, 14.742427769315322, 14.742427769315322, 14.731695495637132, 14.731695495637132, 14.723316727651351, 14.723316727651351, 14.714085420344661, 14.714085420344661, 14.705044067153839, 14.705044067153839, 14.695511757105502, 14.695511757105502, 14.684106161453188, 14.684106161453188, 14.673362900138697, 14.673362900138697, 14.662126777303884, 14.662126777303884, 14.650294122378542, 14.650294122378542, 14.637133503588467, 14.637133503588467, 14.625885500549552, 14.625885500549552, 14.613041318879013, 14.613041318879013, 14.600491228516, 14.600491228516, 14.589826301169238, 14.589826301169238, 14.579097284458562, 14.579097284458562, 14.567445029812177, 14.567445029812177, 14.555065538321779, 14.555065538321779, 14.543083171721651, 14.543083171721651, 14.530543871653219, 14.530543871653219, 14.519732090172331, 14.519732090172331, 14.50728664083606, 14.50728664083606, 14.494761059082773, 14.494761059082773, 14.480759862525757, 14.480759862525757, 14.466954078017151, 14.466954078017151, 14.452655312592428, 14.452655312592428, 14.43861439698937, 14.43861439698937, 14.421950182244203, 14.421950182244203, 14.404714317939641, 14.404714317939641, 15, 15.025881631884008, 15.025881631884008, 14.919856780977506, 14.919856780977506, 14.84340539956636, 14.84340539956636, 14.768172517785956, 14.768172517785956, 14.753355341717914, 14.753355341717914, 14.710325587285196, 14.710325587285196, 14.65501286735965, 14.65501286735965, 14.558960244492898, 14.558960244492898, 14.343261540533113, 14.343261540533113, 14.112473629068363, 14.112473629068363, 13.923048492146386, 13.923048492146386, 13.716505105851384, 13.716505105851384, 13.536396160701718, 13.536396160701718, 13.382627368919778, 13.382627368919778, 13.273403497288376, 13.273403497288376, 13.18737339314849, 13.18737339314849, 13.15696932845709, 13.15696932845709, 13.046690159522171, 13.046690159522171, 12.961691639243096, 12.961691639243096, 12.904545878763365, 12.904545878763365, 12.853989386327374, 12.853989386327374, 12.856562555701977, 12.856562555701977, 12.89695026210208, 12.89695026210208, 12.99401382064389, 12.99401382064389, 13.064986472742175, 13.064986472742175, 13.200100005296521, 13.200100005296521, 13.356245186734787, 13.356245186734787, 13.581858258648817, 13.581858258648817, 13.779446331861786, 13.779446331861786, 14.020887197803892, 14.020887197803892, 14.322226633251981, 14.322226633251981, 14.607966995872808, 14.607966995872808, 14.80045909939326, 14.80045909939326, 14.974742020331096, 14.974742020331096, 15.014139514654353, 15.014139514654353, 15.031590488973418, 15.031590488973418, 14.942284460374912, 14.942284460374912, 14.810526845162071, 14.810526845162071, 14.71725604402707, 14.71725604402707, 14.654423668399897, 14.654423668399897, 14.59904128346401, 14.59904128346401, 14.452865602940358, 14.452865602940358, 14.282261478879674, 14.282261478879674, 14.149772009038367, 14.149772009038367, 14.027052069983485, 14.027052069983485, 13.859992607077059, 13.859992607077059, 13.726038665079807, 13.726038665079807, 13.542762810472052, 13.542762810472052, 13.426206655218582, 13.426206655218582, 13.293233924236567, 13.293233924236567, 13.147791616712704, 13.147791616712704, 13.006610763951292, 13.006610763951292, 12.84823986731333, 12.84823986731333, 12.693804885133208, 12.693804885133208, 12.498890192871052, 12.498890192871052, 12.325809989121367, 12.325809989121367, 12.151607078337484, 12.151607078337484, 11.98176127509246, 11.98176127509246, 11.761719359770526, 11.761719359770526, 11.535738338854555, 11.535738338854555, 11.356031924588308, 11.356031924588308, 11.166858150706151, 11.166858150706151, 11.013537609868145, 11.013537609868145, 10.940785833361874, 10.940785833361874, 10.880470893076224, 10.880470893076224, 10.810492031684296, 10.810492031684296, 10.738828174758915, 10.738828174758915, 10.732227365833888, 10.732227365833888, 10.74063259552893, 10.74063259552893, 10.754970118090359, 10.754970118090359, 10.733785904628672, 10.733785904628672, 10.787976887758164, 10.787976887758164, 10.88944458640169, 10.88944458640169, 11.04254907916619, 11.04254907916619, 11.228202407568958, 11.228202407568958, 11.482818264639777, 11.482818264639777, 11.69687181566044, 11.69687181566044, 11.906283961960796, 11.906283961960796, 12.151929632994989, 12.151929632994989, 12.442078661195602, 12.442078661195602, 12.685614756768384, 12.685614756768384, 12.882246373678006, 12.882246373678006, 13.098033807459965, 13.098033807459965, 13.265644619378074, 13.265644619378074, 13.488205244369283, 13.488205244369283, 13.801786381602861, 13.801786381602861, 14.15661507092392, 14.15661507092392, 14.571319896228996, 14.571319896228996, 14.900498464260913, 14.900498464260913, 15.264447207321453, 15.264447207321453, 15.531123380217505, 15.531123380217505, 15.924513627073946, 15.924513627073946, 16.19019922374802, 16.19019922374802, 16.322098263657374, 16.322098263657374, 16.304174332335062, 16.304174332335062, 16.340241196629936, 16.340241196629936, 16.268904220202955, 16.268904220202955, 16.086253203878236, 16.086253203878236, 15.782468169262778, 15.782468169262778, 15.374958294571538, 15.374958294571538, 15, 15.012940815942004, 15.012940815942004, 14.98636610132836, 14.98636610132836, 14.971810745493599, 14.971810745493599, 14.959082346076983, 14.959082346076983, 14.960947875173133, 14.960947875173133, 14.95565263271521, 14.95565263271521, 14.943059453110807, 14.943059453110807, 14.920042423099233, 14.920042423099233, 14.859798697725925, 14.859798697725925, 14.797521921922066, 14.797521921922066, 14.746699458020705, 14.746699458020705, 14.686175690662845, 14.686175690662845, 14.631471102128723, 14.631471102128723, 14.58023065366825, 14.58023065366825, 14.537568554812667, 14.537568554812667, 14.500231317119468, 14.500231317119468, 14.474722857563513, 14.474722857563513, 14.4220647350196, 14.4220647350196, 14.376180825464203, 14.376180825464203, 14.335464151009303, 14.335464151009303, 14.295170307805137, 14.295170307805137, 14.263049608683579, 14.263049608683579, 14.243626386186193, 14.243626386186193, 14.231930990766053, 14.231930990766053, 14.208866161776603, 14.208866161776603, 14.202879759057403, 14.202879759057403, 14.198542451693676, 14.198542451693676, 14.205568788947831, 14.205568788947831, 14.202391682296767, 14.202391682296767, 14.211179246898407, 14.211179246898407, 14.22809282401728, 14.22809282401728, 14.240716868942075, 14.240716868942075, 14.233201323513999, 14.233201323513999, 14.225227297004473, 14.225227297004473, 14.189429886330164, 14.189429886330164, 14.147165369806896, 14.147165369806896, 14.08333714510193, 14.08333714510193, 14.019069291306938, 14.019069291306938, 13.961481416227368, 13.961481416227368, 13.913958049210835, 13.913958049210835, 13.866151471260338, 13.866151471260338, 13.801817295121142, 13.801817295121142, 13.737042236766802, 13.737042236766802, 13.678767238942457, 13.678767238942457, 13.628052525015123, 13.628052525015123, 13.56643704645608, 13.56643704645608, 13.515035696227566, 13.515035696227566, 13.450876501139497, 13.450876501139497, 13.402818129238593, 13.402818129238593, 13.348944553667687, 13.348944553667687, 13.293373264063145, 13.293373264063145, 13.239891656584982, 13.239891656584982, 13.178310915340727, 13.178310915340727, 13.11914363309317, 13.11914363309317, 13.04834605494057, 13.04834605494057, 12.980008418510142, 12.980008418510142, 12.912100563936535, 12.912100563936535, 12.84548257168026, 12.84548257168026, 12.761653328708682, 12.761653328708682, 12.670680742782599, 12.670680742782599, 12.593746048181327, 12.593746048181327, 12.505966192387636, 12.505966192387636, 12.426975415778585, 12.426975415778585, 12.372987114877688, 12.372987114877688, 12.316124888297376, 12.316124888297376, 12.25624784136798, 12.25624784136798, 12.188780748399955, 12.188780748399955, 12.139029429691613, 12.139029429691613, 12.091613175035052, 12.091613175035052, 12.042152685505714, 12.042152685505714, 11.977247905600317, 11.977247905600317, 11.933433733774168, 11.933433733774168, 11.89504783502318, 11.89504783502318, 11.871147080760428, 11.871147080760428, 11.850217659047976, 11.850217659047976, 11.84192192212905, 11.84192192212905, 11.82311969344896, 11.82311969344896, 11.798468322241224, 11.798468322241224, 11.781618541251447, 11.781618541251447, 11.771189982727265, 11.771189982727265, 11.752590059889691, 11.752590059889691, 11.725074162195554, 11.725074162195554, 11.707552281866988, 11.707552281866988, 11.681614136981478, 11.681614136981478, 11.667586378488018, 11.667586378488018, 11.674231291283325, 11.674231291283325, 11.689501880321215, 11.689501880321215, 11.71312985613572, 11.71312985613572, 11.729541695595978, 11.729541695595978, 11.756346252143663, 11.756346252143663, 11.776821825896544, 11.776821825896544, 11.823144360448932, 11.823144360448932, 11.858480184796978, 11.858480184796978, 11.887381186413212, 11.887381186413212, 11.903274853981108, 11.903274853981108, 11.934053284575308, 11.934053284575308, 11.959946529310686, 11.959946529310686, 11.981458643093886, 11.981458643093886, 11.986109221284174, 11.986109221284174, 11.98062484432249, 11.98062484432249 ], "yaxis": "y" } ], "layout": { "legend": { "title": { "text": "color" }, "tracegroupgap": 0 }, "margin": { "t": 60 }, "template": { "data": { "bar": [ { "error_x": { "color": "#2a3f5f" }, "error_y": { "color": "#2a3f5f" }, "marker": { "line": { "color": "#E5ECF6", "width": 0.5 }, "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "bar" } ], "barpolar": [ { "marker": { "line": { "color": "#E5ECF6", "width": 0.5 }, "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "barpolar" } ], "carpet": [ { "aaxis": { "endlinecolor": "#2a3f5f", "gridcolor": "white", "linecolor": "white", "minorgridcolor": "white", "startlinecolor": "#2a3f5f" }, "baxis": { "endlinecolor": "#2a3f5f", "gridcolor": "white", "linecolor": "white", "minorgridcolor": "white", "startlinecolor": "#2a3f5f" }, "type": "carpet" } ], "choropleth": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "choropleth" } ], "contour": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "contour" } ], "contourcarpet": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "contourcarpet" } ], "heatmap": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "heatmap" } ], "heatmapgl": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "heatmapgl" } ], "histogram": [ { "marker": { "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "histogram" } ], "histogram2d": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "histogram2d" } ], "histogram2dcontour": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "histogram2dcontour" } ], "mesh3d": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "mesh3d" } ], "parcoords": [ { "line": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "parcoords" } ], "pie": [ { "automargin": true, "type": "pie" } ], "scatter": [ { "fillpattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 }, "type": "scatter" } ], "scatter3d": [ { "line": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatter3d" } ], "scattercarpet": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattercarpet" } ], "scattergeo": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattergeo" } ], "scattergl": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattergl" } ], "scattermapbox": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattermapbox" } ], "scatterpolar": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterpolar" } ], "scatterpolargl": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterpolargl" } ], "scatterternary": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterternary" } ], "surface": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "surface" } ], "table": [ { "cells": { "fill": { "color": "#EBF0F8" }, "line": { "color": "white" } }, "header": { "fill": { "color": "#C8D4E3" }, "line": { "color": "white" } }, "type": "table" } ] }, "layout": { "annotationdefaults": { "arrowcolor": "#2a3f5f", "arrowhead": 0, "arrowwidth": 1 }, "autotypenumbers": "strict", "coloraxis": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "colorscale": { "diverging": [ [ 0, "#8e0152" ], [ 0.1, "#c51b7d" ], [ 0.2, "#de77ae" ], [ 0.3, "#f1b6da" ], [ 0.4, "#fde0ef" ], [ 0.5, "#f7f7f7" ], [ 0.6, "#e6f5d0" ], [ 0.7, "#b8e186" ], [ 0.8, "#7fbc41" ], [ 0.9, "#4d9221" ], [ 1, "#276419" ] ], "sequential": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "sequentialminus": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ] }, "colorway": [ "#636efa", "#EF553B", "#00cc96", "#ab63fa", "#FFA15A", "#19d3f3", "#FF6692", "#B6E880", "#FF97FF", "#FECB52" ], "font": { "color": "#2a3f5f" }, "geo": { "bgcolor": "white", "lakecolor": "white", "landcolor": "#E5ECF6", "showlakes": true, "showland": true, "subunitcolor": "white" }, "hoverlabel": { "align": "left" }, "hovermode": "closest", "mapbox": { "style": "light" }, "paper_bgcolor": "white", "plot_bgcolor": "#E5ECF6", "polar": { "angularaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "bgcolor": "#E5ECF6", "radialaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" } }, "scene": { "xaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" }, "yaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" }, "zaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" } }, "shapedefaults": { "line": { "color": "#2a3f5f" } }, "ternary": { "aaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "baxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "bgcolor": "#E5ECF6", "caxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" } }, "title": { "x": 0.05 }, "xaxis": { "automargin": true, "gridcolor": "white", "linecolor": "white", "ticks": "", "title": { "standoff": 15 }, "zerolinecolor": "white", "zerolinewidth": 2 }, "yaxis": { "automargin": true, "gridcolor": "white", "linecolor": "white", "ticks": "", "title": { "standoff": 15 }, "zerolinecolor": "white", "zerolinewidth": 2 } } }, "xaxis": { "anchor": "y", "domain": [ 0, 1 ], "title": { "text": "x" } }, "yaxis": { "anchor": "x", "domain": [ 0, 1 ], "title": { "text": "y" } } } } }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from cadCAD_tools import profile_run\n", "\n", "fig = px.line(df.query('dt == 0.1'),\n", " x=df.prey_population,\n", " y=df.predator_population,\n", " color=df.run.astype(str))\n", "\n", "fig.show()" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", " ___________ ____\n", " ________ __ ___/ / ____/ | / __ \\\n", " / ___/ __` / __ / / / /| | / / / /\n", "/ /__/ /_/ / /_/ / /___/ ___ |/ /_/ /\n", "\\___/\\__,_/\\__,_/\\____/_/ |_/_____/\n", "by cadCAD\n", "\n", "cadCAD Version: 0.4.28\n", "Execution Mode: local_proc\n", "Simulation Dimensions:\n", "Entire Simulation: (Models, Unique Timesteps, Params, Total Runs, Sub-States) = (1, 20, 5, 30, 3)\n", " Simulation 0: (Timesteps, Params, Runs, Sub-States) = (20, 5, 30, 3)\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "Initializing configurations: 100%|██████████| 30/30 [00:00<00:00, 662.65it/s]" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Execution Method: parallelize_simulations\n", "Execution Mode: parallelized\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\n", "Flattening results: 100%|██████████| 30/30 [00:00<00:00, 666.25it/s]" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Total execution time: 0.48s\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\n" ] } ], "source": [ "df = profile_run(initial_conditions,\n", " params,\n", " partial_state_update_blocks,\n", " 20,\n", " 10,\n", " use_label=True)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "0 Initial State\n", "1 Time Measure\n", "2 Lotka-Volterra Equations\n", "3 Time Measure\n", "4 Do Nothing\n", "5 Time Measure\n", "6 Time Measure\n", "7 Lotka-Volterra Equations\n", "Name: substep_label, dtype: object" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "df.head(8).substep_label" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "application/vnd.plotly.v1+json": { "config": { "plotlyServerURL": "https://plot.ly" }, "data": [ { "alignmentgroup": "True", "hovertemplate": "timestep=%{x}
time_since_start=%{y}", "legendgroup": "", "marker": { "color": "#636efa" }, "name": "", "notched": false, "offsetgroup": "", "orientation": "v", "showlegend": false, "type": "box", "x": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 ], "x0": " ", "xaxis": "x", "y": [ null, 0.26558995246887207, 0.2659590244293213, 0.2660501003265381, 0.2661259174346924, 0.2663848400115967, 0.2664608955383301, 0.2665390968322754, 0.266618013381958, 0.26669907569885254, 0.2667720317840576, 0.2668471336364746, 0.2669200897216797, 0.266995906829834, 0.26707005500793457, 0.26714301109313965, 0.2672159671783447, 0.26729512214660645, 0.267733097076416, 0.2681009769439697, 0.26819801330566406, null, 0.27036190032958984, 0.2707710266113281, 0.2710988521575928, 0.2712888717651367, 0.27136993408203125, 0.27144384384155273, 0.2715179920196533, 0.2716028690338135, 0.2716810703277588, 0.2717549800872803, 0.2718698978424072, 0.27195191383361816, 0.2720298767089844, 0.2722759246826172, 0.27252674102783203, 0.2726719379425049, 0.2727508544921875, 0.272824764251709, 0.27289772033691406, 0.27296996116638184, null, 0.276965856552124, 0.27704882621765137, 0.27712392807006836, 0.27719688415527344, 0.27727174758911133, 0.2773449420928955, 0.2774178981781006, 0.2774968147277832, 0.2775750160217285, 0.2776467800140381, 0.27771973609924316, 0.27779197692871094, 0.27786707878112793, 0.2779388427734375, 0.2780117988586426, 0.27808594703674316, 0.27815985679626465, 0.2782328128814697, 0.27835893630981445, 0.27843594551086426, null, 0.28354501724243164, 0.2838010787963867, 0.28403782844543457, 0.2842710018157959, 0.284527063369751, 0.28476572036743164, 0.28499889373779297, 0.28540492057800293, 0.2857358455657959, 0.2861349582672119, 0.2863729000091553, 0.2866988182067871, 0.28699374198913574, 0.2870907783508301, 0.28716492652893066, 0.28723883628845215, 0.2873198986053467, 0.28739404678344727, 0.28746795654296875, 0.28754091262817383, null, 0.2860229015350342, 0.2860989570617676, 0.28617000579833984, 0.2862389087677002, 0.2863130569458008, 0.28638315200805664, 0.286452054977417, 0.28652501106262207, 0.28659820556640625, 0.2866659164428711, 0.2867431640625, 0.28681111335754395, 0.2868809700012207, 0.28695201873779297, 0.2870211601257324, 0.287092924118042, 0.28716421127319336, 0.2872331142425537, 0.28730225563049316, 0.287369966506958, null, 0.2810492515563965, 0.2811269760131836, 0.28119826316833496, 0.2812690734863281, 0.2813410758972168, 0.28141117095947266, 0.2814810276031494, 0.2815561294555664, 0.2816300392150879, 0.28170204162597656, 0.281771183013916, 0.28184008598327637, 0.28191328048706055, 0.2819819450378418, 0.28205299377441406, 0.282120943069458, 0.2821919918060303, 0.28226208686828613, 0.2823309898376465, 0.28239917755126953, null, 0.27811098098754883, 0.27818989753723145, 0.2782609462738037, 0.27833080291748047, 0.27840280532836914, 0.2784738540649414, 0.27854275703430176, 0.27861785888671875, 0.27869582176208496, 0.2787637710571289, 0.27883291244506836, 0.2789020538330078, 0.27897191047668457, 0.2790398597717285, 0.2791109085083008, 0.27917981147766113, 0.279249906539917, 0.27931880950927734, 0.2793879508972168, 0.27945590019226074, null, 0.26662278175354004, 0.26670384407043457, 0.26677489280700684, 0.2668459415435791, 0.26691770553588867, 0.26698899269104004, 0.2670598030090332, 0.2671349048614502, 0.26720690727233887, 0.2672770023345947, 0.2673468589782715, 0.26741695404052734, 0.2674880027770996, 0.2675619125366211, 0.26763081550598145, 0.26770687103271484, 0.26778483390808105, 0.26786303520202637, 0.26793599128723145, 0.2680046558380127, null, 0.26627492904663086, 0.2663588523864746, 0.2664330005645752, 0.2665059566497803, 0.26657891273498535, 0.2666490077972412, 0.2667198181152344, 0.26679277420043945, 0.26686882972717285, 0.26694297790527344, 0.267014741897583, 0.2670876979827881, 0.2671627998352051, 0.26735877990722656, 0.26743292808532715, 0.2675046920776367, 0.2675788402557373, 0.2676527500152588, 0.26772499084472656, 0.26779794692993164, null, 0.2680220603942871, 0.26810216903686523, 0.2681732177734375, 0.2682492733001709, 0.26832103729248047, 0.26839137077331543, 0.2684621810913086, 0.2685360908508301, 0.26860809326171875, 0.2686781883239746, 0.26874709129333496, 0.2688171863555908, 0.26889705657958984, 0.2689692974090576, 0.26903820037841797, 0.2691073417663574, 0.2691771984100342, 0.26924633979797363, 0.269315242767334, 0.26938438415527344 ], "y0": " ", "yaxis": "y" } ], "layout": { "boxmode": "group", "legend": { "tracegroupgap": 0 }, "margin": { "t": 60 }, "template": { "data": { "bar": [ { "error_x": { "color": "#2a3f5f" }, "error_y": { "color": "#2a3f5f" }, "marker": { "line": { "color": "#E5ECF6", "width": 0.5 }, "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "bar" } ], "barpolar": [ { "marker": { "line": { "color": "#E5ECF6", "width": 0.5 }, "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "barpolar" } ], "carpet": [ { "aaxis": { "endlinecolor": "#2a3f5f", "gridcolor": "white", "linecolor": "white", "minorgridcolor": "white", "startlinecolor": "#2a3f5f" }, "baxis": { "endlinecolor": "#2a3f5f", "gridcolor": "white", "linecolor": "white", "minorgridcolor": "white", "startlinecolor": "#2a3f5f" }, "type": "carpet" } ], "choropleth": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "choropleth" } ], "contour": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "contour" } ], "contourcarpet": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "contourcarpet" } ], "heatmap": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "heatmap" } ], "heatmapgl": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "heatmapgl" } ], "histogram": [ { "marker": { "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "histogram" } ], "histogram2d": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "histogram2d" } ], "histogram2dcontour": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "histogram2dcontour" } ], "mesh3d": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "mesh3d" } ], "parcoords": [ { "line": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "parcoords" } ], "pie": [ { "automargin": true, "type": "pie" } ], "scatter": [ { "fillpattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 }, "type": "scatter" } ], "scatter3d": [ { "line": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatter3d" } ], "scattercarpet": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattercarpet" } ], "scattergeo": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattergeo" } ], "scattergl": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattergl" } ], "scattermapbox": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattermapbox" } ], "scatterpolar": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterpolar" } ], "scatterpolargl": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterpolargl" } ], "scatterternary": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterternary" } ], "surface": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "surface" } ], "table": [ { "cells": { "fill": { "color": "#EBF0F8" }, "line": { "color": "white" } }, "header": { "fill": { "color": "#C8D4E3" }, "line": { "color": "white" } }, "type": "table" } ] }, "layout": { "annotationdefaults": { "arrowcolor": "#2a3f5f", "arrowhead": 0, "arrowwidth": 1 }, "autotypenumbers": "strict", "coloraxis": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "colorscale": { "diverging": [ [ 0, "#8e0152" ], [ 0.1, "#c51b7d" ], [ 0.2, "#de77ae" ], [ 0.3, "#f1b6da" ], [ 0.4, "#fde0ef" ], [ 0.5, "#f7f7f7" ], [ 0.6, "#e6f5d0" ], [ 0.7, "#b8e186" ], [ 0.8, "#7fbc41" ], [ 0.9, "#4d9221" ], [ 1, "#276419" ] ], "sequential": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "sequentialminus": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ] }, "colorway": [ "#636efa", "#EF553B", "#00cc96", "#ab63fa", "#FFA15A", "#19d3f3", "#FF6692", "#B6E880", "#FF97FF", "#FECB52" ], "font": { "color": "#2a3f5f" }, "geo": { "bgcolor": "white", "lakecolor": "white", "landcolor": "#E5ECF6", "showlakes": true, "showland": true, "subunitcolor": "white" }, "hoverlabel": { "align": "left" }, "hovermode": "closest", "mapbox": { "style": "light" }, "paper_bgcolor": "white", "plot_bgcolor": "#E5ECF6", "polar": { "angularaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "bgcolor": "#E5ECF6", "radialaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" } }, "scene": { "xaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" }, "yaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" }, "zaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" } }, "shapedefaults": { "line": { "color": "#2a3f5f" } }, "ternary": { "aaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "baxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "bgcolor": "#E5ECF6", "caxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" } }, "title": { "x": 0.05 }, "xaxis": { "automargin": true, "gridcolor": "white", "linecolor": "white", "ticks": "", "title": { "standoff": 15 }, "zerolinecolor": "white", "zerolinewidth": 2 }, "yaxis": { "automargin": true, "gridcolor": "white", "linecolor": "white", "ticks": "", "title": { "standoff": 15 }, "zerolinecolor": "white", "zerolinewidth": 2 } } }, "xaxis": { "anchor": "y", "domain": [ 0, 1 ], "title": { "text": "timestep" } }, "yaxis": { "anchor": "x", "domain": [ 0, 1 ], "title": { "text": "time_since_start" } } } } }, "metadata": {}, "output_type": "display_data" } ], "source": [ "from cadCAD_tools.profiling.visualizations import visualize_elapsed_time_per_ts\n", "\n", "visualize_elapsed_time_per_ts(df, relative=False)" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "application/vnd.plotly.v1+json": { "config": { "plotlyServerURL": "https://plot.ly" }, "data": [ { "alignmentgroup": "True", "hovertemplate": "timestep=%{x}
psub_duration=%{y}", "legendgroup": "", "marker": { "color": "#636efa" }, "name": "", "notched": false, "offsetgroup": "", "orientation": "v", "showlegend": false, "type": "box", "x": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 ], "x0": " ", "xaxis": "x", "y": [ null, null, 0.00036907196044921875, 0.00009107589721679688, 0.00007581710815429688, 0.0002589225769042969, 0.00007605552673339844, 0.0000782012939453125, 0.00007891654968261719, 0.00008106231689453125, 0.00007295608520507812, 0.00007510185241699219, 0.00007295608520507812, 0.00007581710815429688, 0.00007414817810058594, 0.00007295608520507812, 0.00007295608520507812, 0.00007915496826171875, 0.0004379749298095703, 0.00036787986755371094, 0.00009703636169433594, null, null, 0.00040912628173828125, 0.00032782554626464844, 0.0001900196075439453, 0.00008106231689453125, 0.00007390975952148438, 0.00007414817810058594, 0.00008487701416015625, 0.0000782012939453125, 0.00007390975952148438, 0.00011491775512695312, 0.0000820159912109375, 0.00007796287536621094, 0.0002460479736328125, 0.00025081634521484375, 0.00014519691467285156, 0.00007891654968261719, 0.00007390975952148438, 0.00007295608520507812, 0.00007224082946777344, null, null, 0.00008296966552734375, 0.00007510185241699219, 0.00007295608520507812, 0.00007486343383789062, 0.00007319450378417969, 0.00007295608520507812, 0.00007891654968261719, 0.0000782012939453125, 0.00007176399230957031, 0.00007295608520507812, 0.00007224082946777344, 0.00007510185241699219, 0.00007176399230957031, 0.00007295608520507812, 0.00007414817810058594, 0.00007390975952148438, 0.00007295608520507812, 0.00012612342834472656, 0.00007700920104980469, null, null, 0.0002560615539550781, 0.00023674964904785156, 0.00023317337036132812, 0.0002560615539550781, 0.00023865699768066406, 0.00023317337036132812, 0.00040602684020996094, 0.00033092498779296875, 0.0003991127014160156, 0.00023794174194335938, 0.00032591819763183594, 0.0002949237823486328, 0.00009703636169433594, 0.00007414817810058594, 0.00007390975952148438, 0.00008106231689453125, 0.00007414817810058594, 0.00007390975952148438, 0.00007295608520507812, null, null, 0.00007605552673339844, 0.00007104873657226562, 0.00006890296936035156, 0.00007414817810058594, 0.00007009506225585938, 0.00006890296936035156, 0.00007295608520507812, 0.00007319450378417969, 0.00006771087646484375, 0.00007724761962890625, 0.00006794929504394531, 0.00006985664367675781, 0.00007104873657226562, 0.00006914138793945312, 0.00007176399230957031, 0.00007128715515136719, 0.00006890296936035156, 0.00006914138793945312, 0.00006771087646484375, null, null, 0.00007772445678710938, 0.00007128715515136719, 0.00007081031799316406, 0.00007200241088867188, 0.00007009506225585938, 0.00006985664367675781, 0.00007510185241699219, 0.00007390975952148438, 0.00007200241088867188, 0.00006914138793945312, 0.00006890296936035156, 0.00007319450378417969, 0.00006866455078125, 0.00007104873657226562, 0.00006794929504394531, 0.00007104873657226562, 0.00007009506225585938, 0.00006890296936035156, 0.00006818771362304688, null, null, 0.00007891654968261719, 0.00007104873657226562, 0.00006985664367675781, 0.00007200241088867188, 0.00007104873657226562, 0.00006890296936035156, 0.00007510185241699219, 0.00007796287536621094, 0.00006794929504394531, 0.00006914138793945312, 0.00006914138793945312, 0.00006985664367675781, 0.00006794929504394531, 0.00007104873657226562, 0.00006890296936035156, 0.00007009506225585938, 0.00006890296936035156, 0.00006914138793945312, 0.00006794929504394531, null, null, 0.00008106231689453125, 0.00007104873657226562, 0.00007104873657226562, 0.00007176399230957031, 0.00007128715515136719, 0.00007081031799316406, 0.00007510185241699219, 0.00007200241088867188, 0.00007009506225585938, 0.00006985664367675781, 0.00007009506225585938, 0.00007104873657226562, 0.00007390975952148438, 0.00006890296936035156, 0.00007605552673339844, 0.00007796287536621094, 0.0000782012939453125, 0.00007295608520507812, 0.00006866455078125, null, null, 0.00008392333984375, 0.00007414817810058594, 0.00007295608520507812, 0.00007295608520507812, 0.00007009506225585938, 0.00007081031799316406, 0.00007295608520507812, 0.00007605552673339844, 0.00007414817810058594, 0.00007176399230957031, 0.00007295608520507812, 0.00007510185241699219, 0.00019598007202148438, 0.00007414817810058594, 0.00007176399230957031, 0.00007414817810058594, 0.00007390975952148438, 0.00007224082946777344, 0.00007295608520507812, null, null, 0.000080108642578125, 0.00007104873657226562, 0.00007605552673339844, 0.00007176399230957031, 0.00007033348083496094, 0.00007081031799316406, 0.00007390975952148438, 0.00007200241088867188, 0.00007009506225585938, 0.00006890296936035156, 0.00007009506225585938, 0.00007987022399902344, 0.00007224082946777344, 0.00006890296936035156, 0.00006914138793945312, 0.00006985664367675781, 0.00006914138793945312, 0.00006890296936035156, 0.00006914138793945312 ], "y0": " ", "yaxis": "y" } ], "layout": { "boxmode": "group", "legend": { "tracegroupgap": 0 }, "margin": { "t": 60 }, "template": { "data": { "bar": [ { "error_x": { "color": "#2a3f5f" }, "error_y": { "color": "#2a3f5f" }, "marker": { "line": { "color": "#E5ECF6", "width": 0.5 }, "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "bar" } ], "barpolar": [ { "marker": { "line": { "color": "#E5ECF6", "width": 0.5 }, "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "barpolar" } ], "carpet": [ { "aaxis": { "endlinecolor": "#2a3f5f", "gridcolor": "white", "linecolor": "white", "minorgridcolor": "white", "startlinecolor": "#2a3f5f" }, "baxis": { "endlinecolor": "#2a3f5f", "gridcolor": "white", "linecolor": "white", "minorgridcolor": "white", "startlinecolor": "#2a3f5f" }, "type": "carpet" } ], "choropleth": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "choropleth" } ], "contour": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "contour" } ], "contourcarpet": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "contourcarpet" } ], "heatmap": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "heatmap" } ], "heatmapgl": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "heatmapgl" } ], "histogram": [ { "marker": { "pattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 } }, "type": "histogram" } ], "histogram2d": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "histogram2d" } ], "histogram2dcontour": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "histogram2dcontour" } ], "mesh3d": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "mesh3d" } ], "parcoords": [ { "line": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "parcoords" } ], "pie": [ { "automargin": true, "type": "pie" } ], "scatter": [ { "fillpattern": { "fillmode": "overlay", "size": 10, "solidity": 0.2 }, "type": "scatter" } ], "scatter3d": [ { "line": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatter3d" } ], "scattercarpet": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattercarpet" } ], "scattergeo": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattergeo" } ], "scattergl": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattergl" } ], "scattermapbox": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattermapbox" } ], "scatterpolar": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterpolar" } ], "scatterpolargl": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterpolargl" } ], "scatterternary": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterternary" } ], "surface": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "surface" } ], "table": [ { "cells": { "fill": { "color": "#EBF0F8" }, "line": { "color": "white" } }, "header": { "fill": { "color": "#C8D4E3" }, "line": { "color": "white" } }, "type": "table" } ] }, "layout": { "annotationdefaults": { "arrowcolor": "#2a3f5f", "arrowhead": 0, "arrowwidth": 1 }, "autotypenumbers": "strict", "coloraxis": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "colorscale": { "diverging": [ [ 0, "#8e0152" ], [ 0.1, "#c51b7d" ], [ 0.2, "#de77ae" ], [ 0.3, "#f1b6da" ], [ 0.4, "#fde0ef" ], [ 0.5, "#f7f7f7" ], [ 0.6, "#e6f5d0" ], [ 0.7, "#b8e186" ], [ 0.8, "#7fbc41" ], [ 0.9, "#4d9221" ], [ 1, "#276419" ] ], "sequential": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "sequentialminus": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ] }, "colorway": [ "#636efa", "#EF553B", "#00cc96", "#ab63fa", "#FFA15A", "#19d3f3", "#FF6692", "#B6E880", "#FF97FF", "#FECB52" ], "font": { "color": "#2a3f5f" }, "geo": { "bgcolor": "white", "lakecolor": "white", "landcolor": "#E5ECF6", "showlakes": true, "showland": true, "subunitcolor": "white" }, "hoverlabel": { "align": "left" }, "hovermode": "closest", "mapbox": { "style": "light" }, "paper_bgcolor": "white", "plot_bgcolor": "#E5ECF6", "polar": { "angularaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "bgcolor": "#E5ECF6", "radialaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" } }, "scene": { "xaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" }, "yaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" }, "zaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" } }, "shapedefaults": { "line": { "color": "#2a3f5f" } }, "ternary": { "aaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "baxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "bgcolor": "#E5ECF6", "caxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" } }, "title": { "x": 0.05 }, "xaxis": { "automargin": true, "gridcolor": "white", "linecolor": "white", "ticks": "", "title": { "standoff": 15 }, "zerolinecolor": "white", "zerolinewidth": 2 }, "yaxis": { "automargin": true, "gridcolor": "white", "linecolor": "white", "ticks": "", "title": { "standoff": 15 }, "zerolinecolor": "white", "zerolinewidth": 2 } } }, "xaxis": { "anchor": "y", "domain": [ 0, 1 ], "title": { "text": "timestep" } }, "yaxis": { "anchor": "x", "domain": [ 0, 1 ], "title": { "text": "psub_duration" } } } } }, "metadata": {}, "output_type": "display_data" } ], "source": [ "visualize_elapsed_time_per_ts(df, relative=True)" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "100%|██████████| 200/200 [00:00<00:00, 1004.62it/s]\n" ] }, { "ename": "TypeError", "evalue": "incompatible index of inserted column with frame index", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", "File \u001b[0;32m/opt/homebrew/Caskroom/miniconda/base/lib/python3.11/site-packages/pandas/core/frame.py:12304\u001b[0m, in \u001b[0;36m_reindex_for_setitem\u001b[0;34m(value, index)\u001b[0m\n\u001b[1;32m 12303\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m> 12304\u001b[0m reindexed_value \u001b[38;5;241m=\u001b[39m value\u001b[38;5;241m.\u001b[39mreindex(index)\u001b[38;5;241m.\u001b[39m_values\n\u001b[1;32m 12305\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m err:\n\u001b[1;32m 12306\u001b[0m \u001b[38;5;66;03m# raised in MultiIndex.from_tuples, see test_insert_error_msmgs\u001b[39;00m\n", "File \u001b[0;32m/opt/homebrew/Caskroom/miniconda/base/lib/python3.11/site-packages/pandas/core/series.py:4977\u001b[0m, in \u001b[0;36mSeries.reindex\u001b[0;34m(self, index, axis, method, copy, level, fill_value, limit, tolerance)\u001b[0m\n\u001b[1;32m 4960\u001b[0m \u001b[38;5;129m@doc\u001b[39m(\n\u001b[1;32m 4961\u001b[0m NDFrame\u001b[38;5;241m.\u001b[39mreindex, \u001b[38;5;66;03m# type: ignore[has-type]\u001b[39;00m\n\u001b[1;32m 4962\u001b[0m klass\u001b[38;5;241m=\u001b[39m_shared_doc_kwargs[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mklass\u001b[39m\u001b[38;5;124m\"\u001b[39m],\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 4975\u001b[0m tolerance\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mNone\u001b[39;00m,\n\u001b[1;32m 4976\u001b[0m ) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m Series:\n\u001b[0;32m-> 4977\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28msuper\u001b[39m()\u001b[38;5;241m.\u001b[39mreindex(\n\u001b[1;32m 4978\u001b[0m index\u001b[38;5;241m=\u001b[39mindex,\n\u001b[1;32m 4979\u001b[0m method\u001b[38;5;241m=\u001b[39mmethod,\n\u001b[1;32m 4980\u001b[0m copy\u001b[38;5;241m=\u001b[39mcopy,\n\u001b[1;32m 4981\u001b[0m level\u001b[38;5;241m=\u001b[39mlevel,\n\u001b[1;32m 4982\u001b[0m fill_value\u001b[38;5;241m=\u001b[39mfill_value,\n\u001b[1;32m 4983\u001b[0m limit\u001b[38;5;241m=\u001b[39mlimit,\n\u001b[1;32m 4984\u001b[0m tolerance\u001b[38;5;241m=\u001b[39mtolerance,\n\u001b[1;32m 4985\u001b[0m )\n", "File \u001b[0;32m/opt/homebrew/Caskroom/miniconda/base/lib/python3.11/site-packages/pandas/core/generic.py:5521\u001b[0m, in \u001b[0;36mNDFrame.reindex\u001b[0;34m(self, labels, index, columns, axis, method, copy, level, fill_value, limit, tolerance)\u001b[0m\n\u001b[1;32m 5520\u001b[0m \u001b[38;5;66;03m# perform the reindex on the axes\u001b[39;00m\n\u001b[0;32m-> 5521\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_reindex_axes(\n\u001b[1;32m 5522\u001b[0m axes, level, limit, tolerance, method, fill_value, copy\n\u001b[1;32m 5523\u001b[0m )\u001b[38;5;241m.\u001b[39m__finalize__(\u001b[38;5;28mself\u001b[39m, method\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mreindex\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n", "File \u001b[0;32m/opt/homebrew/Caskroom/miniconda/base/lib/python3.11/site-packages/pandas/core/generic.py:5544\u001b[0m, in \u001b[0;36mNDFrame._reindex_axes\u001b[0;34m(self, axes, level, limit, tolerance, method, fill_value, copy)\u001b[0m\n\u001b[1;32m 5543\u001b[0m ax \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_get_axis(a)\n\u001b[0;32m-> 5544\u001b[0m new_index, indexer \u001b[38;5;241m=\u001b[39m ax\u001b[38;5;241m.\u001b[39mreindex(\n\u001b[1;32m 5545\u001b[0m labels, level\u001b[38;5;241m=\u001b[39mlevel, limit\u001b[38;5;241m=\u001b[39mlimit, tolerance\u001b[38;5;241m=\u001b[39mtolerance, method\u001b[38;5;241m=\u001b[39mmethod\n\u001b[1;32m 5546\u001b[0m )\n\u001b[1;32m 5548\u001b[0m axis \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_get_axis_number(a)\n", "File \u001b[0;32m/opt/homebrew/Caskroom/miniconda/base/lib/python3.11/site-packages/pandas/core/indexes/base.py:4437\u001b[0m, in \u001b[0;36mIndex.reindex\u001b[0;34m(self, target, method, level, limit, tolerance)\u001b[0m\n\u001b[1;32m 4435\u001b[0m indexer, _ \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mget_indexer_non_unique(target)\n\u001b[0;32m-> 4437\u001b[0m target \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_wrap_reindex_result(target, indexer, preserve_names)\n\u001b[1;32m 4438\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m target, indexer\n", "File \u001b[0;32m/opt/homebrew/Caskroom/miniconda/base/lib/python3.11/site-packages/pandas/core/indexes/multi.py:2602\u001b[0m, in \u001b[0;36mMultiIndex._wrap_reindex_result\u001b[0;34m(self, target, indexer, preserve_names)\u001b[0m\n\u001b[1;32m 2601\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m-> 2602\u001b[0m target \u001b[38;5;241m=\u001b[39m MultiIndex\u001b[38;5;241m.\u001b[39mfrom_tuples(target)\n\u001b[1;32m 2603\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mTypeError\u001b[39;00m:\n\u001b[1;32m 2604\u001b[0m \u001b[38;5;66;03m# not all tuples, see test_constructor_dict_multiindex_reindex_flat\u001b[39;00m\n", "File \u001b[0;32m/opt/homebrew/Caskroom/miniconda/base/lib/python3.11/site-packages/pandas/core/indexes/multi.py:220\u001b[0m, in \u001b[0;36mnames_compat..new_meth\u001b[0;34m(self_or_cls, *args, **kwargs)\u001b[0m\n\u001b[1;32m 218\u001b[0m kwargs[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mnames\u001b[39m\u001b[38;5;124m\"\u001b[39m] \u001b[38;5;241m=\u001b[39m kwargs\u001b[38;5;241m.\u001b[39mpop(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mname\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m--> 220\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m meth(self_or_cls, \u001b[38;5;241m*\u001b[39margs, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs)\n", "File \u001b[0;32m/opt/homebrew/Caskroom/miniconda/base/lib/python3.11/site-packages/pandas/core/indexes/multi.py:615\u001b[0m, in \u001b[0;36mMultiIndex.from_tuples\u001b[0;34m(cls, tuples, sortorder, names)\u001b[0m\n\u001b[1;32m 613\u001b[0m tuples \u001b[38;5;241m=\u001b[39m np\u001b[38;5;241m.\u001b[39masarray(tuples\u001b[38;5;241m.\u001b[39m_values)\n\u001b[0;32m--> 615\u001b[0m arrays \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mlist\u001b[39m(lib\u001b[38;5;241m.\u001b[39mtuples_to_object_array(tuples)\u001b[38;5;241m.\u001b[39mT)\n\u001b[1;32m 616\u001b[0m \u001b[38;5;28;01melif\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(tuples, \u001b[38;5;28mlist\u001b[39m):\n", "File \u001b[0;32mlib.pyx:2977\u001b[0m, in \u001b[0;36mpandas._libs.lib.tuples_to_object_array\u001b[0;34m()\u001b[0m\n", "\u001b[0;31mValueError\u001b[0m: Buffer dtype mismatch, expected 'Python object' but got 'long'", "\nThe above exception was the direct cause of the following exception:\n", "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m/var/folders/y4/dvc6qr5j30s3frwztjt5shg40000gn/T/ipykernel_61363/3498303338.py\u001b[0m in \u001b[0;36m?\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mcadCAD_tools\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mprofiling\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mvisualizations\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mvisualize_substep_impact\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0mvisualize_substep_impact\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mrelative\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;32m/opt/homebrew/Caskroom/miniconda/base/lib/python3.11/site-packages/cadCAD_tools/profiling/visualizations.py\u001b[0m in \u001b[0;36m?\u001b[0;34m(df, relative, **kwargs)\u001b[0m\n\u001b[1;32m 61\u001b[0m \u001b[0mx_col\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m'substep'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 62\u001b[0m \u001b[0mfig_df\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mx_col\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfig_df\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mx_col\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m/\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 63\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 64\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mrelative\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mTrue\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 65\u001b[0;31m \u001b[0mfig_df\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfig_df\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0massign\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mrelative_psub_time\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mfig_df\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mgroupby\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mindexes\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpsub_time\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mapply\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;32mlambda\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mx\u001b[0m \u001b[0;34m/\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msum\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 66\u001b[0m \u001b[0my_col\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m'relative_psub_time'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 67\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 68\u001b[0m \u001b[0my_col\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m'psub_time'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m/opt/homebrew/Caskroom/miniconda/base/lib/python3.11/site-packages/pandas/core/frame.py\u001b[0m in \u001b[0;36m?\u001b[0;34m(self, **kwargs)\u001b[0m\n\u001b[1;32m 5008\u001b[0m \"\"\"\n\u001b[1;32m 5009\u001b[0m \u001b[0mdata\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcopy\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdeep\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5010\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5011\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mk\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mv\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mkwargs\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mitems\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 5012\u001b[0;31m \u001b[0mdata\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mk\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcom\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mapply_if_callable\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mv\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdata\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 5013\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mdata\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m/opt/homebrew/Caskroom/miniconda/base/lib/python3.11/site-packages/pandas/core/frame.py\u001b[0m in \u001b[0;36m?\u001b[0;34m(self, key, value)\u001b[0m\n\u001b[1;32m 4087\u001b[0m \u001b[0;31m# Column to set is duplicated\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4088\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_setitem_array\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4089\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4090\u001b[0m \u001b[0;31m# set column\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 4091\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_set_item\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", "\u001b[0;32m/opt/homebrew/Caskroom/miniconda/base/lib/python3.11/site-packages/pandas/core/frame.py\u001b[0m in \u001b[0;36m?\u001b[0;34m(self, key, value)\u001b[0m\n\u001b[1;32m 4296\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4297\u001b[0m \u001b[0mSeries\u001b[0m\u001b[0;34m/\u001b[0m\u001b[0mTimeSeries\u001b[0m \u001b[0mwill\u001b[0m \u001b[0mbe\u001b[0m \u001b[0mconformed\u001b[0m \u001b[0mto\u001b[0m \u001b[0mthe\u001b[0m \u001b[0mDataFrames\u001b[0m \u001b[0mindex\u001b[0m \u001b[0mto\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4298\u001b[0m \u001b[0mensure\u001b[0m \u001b[0mhomogeneity\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4299\u001b[0m \"\"\"\n\u001b[0;32m-> 4300\u001b[0;31m \u001b[0mvalue\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mrefs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_sanitize_column\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvalue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 4301\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4302\u001b[0m if (\n\u001b[1;32m 4303\u001b[0m \u001b[0mkey\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcolumns\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m/opt/homebrew/Caskroom/miniconda/base/lib/python3.11/site-packages/pandas/core/frame.py\u001b[0m in \u001b[0;36m?\u001b[0;34m(self, value)\u001b[0m\n\u001b[1;32m 5032\u001b[0m \u001b[0;32massert\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvalue\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mDataFrame\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5033\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mis_dict_like\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvalue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5034\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvalue\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mSeries\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5035\u001b[0m \u001b[0mvalue\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mSeries\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvalue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 5036\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0m_reindex_for_setitem\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvalue\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mindex\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 5037\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5038\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mis_list_like\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvalue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5039\u001b[0m \u001b[0mcom\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrequire_length_match\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvalue\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mindex\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;32m/opt/homebrew/Caskroom/miniconda/base/lib/python3.11/site-packages/pandas/core/frame.py\u001b[0m in \u001b[0;36m?\u001b[0;34m(value, index)\u001b[0m\n\u001b[1;32m 12307\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mvalue\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mindex\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mis_unique\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 12308\u001b[0m \u001b[0;31m# duplicate axis\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 12309\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0merr\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 12310\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m> 12311\u001b[0;31m raise TypeError(\n\u001b[0m\u001b[1;32m 12312\u001b[0m \u001b[0;34m\"incompatible index of inserted column with frame index\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 12313\u001b[0m ) from err\n\u001b[1;32m 12314\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mreindexed_value\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;31mTypeError\u001b[0m: incompatible index of inserted column with frame index" ] } ], "source": [ "from cadCAD_tools.profiling.visualizations import visualize_substep_impact\n", "\n", "visualize_substep_impact(df, relative=True)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [ { "data": { "application/vnd.jupyter.widget-view+json": { "model_id": "c7a8382fce234affa682e5be26089cba", "version_major": 2, "version_minor": 0 }, "text/plain": [ "HBox(children=(FloatProgress(value=0.0, max=600.0), HTML(value='')))" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "\n" ] }, { "data": { "application/vnd.plotly.v1+json": { "config": { "plotlyServerURL": "https://plot.ly" }, "data": [ { "alignmentgroup": "True", "hovertemplate": "substep_label=%{x}
psub_time=%{y}", "legendgroup": "", "marker": { "color": "#636efa" }, "name": "", "notched": false, "offsetgroup": "", "orientation": "v", "showlegend": false, "type": "box", "x": [ "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Do Nothing", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Do Nothing", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Do Nothing", "Do Nothing", "Do Nothing", "Do Nothing", "Do Nothing", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Do Nothing", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Lotka-Volterra Equations", "Do Nothing", "Do Nothing", "Do Nothing", "Do Nothing", "Do Nothing", "Do Nothing", "Do Nothing", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing", "Lotka-Volterra Equations", "Do Nothing" ], "x0": " ", "xaxis": "x", "y": [ 0.000213623046875, 0.0001201629638671875, 0.00015401840209960938, 0.00011467933654785156, 0.0001506805419921875, 0.00019168853759765625, 0.0001285076141357422, 0.00009202957153320312, 0.00012993812561035156, 0.00017142295837402344, 0.0001304149627685547, 0.00010156631469726562, 0.00013756752014160156, 0.00010561943054199219, 0.00011491775512695312, 0.00008702278137207031, 0.00010752677917480469, 0.000087738037109375, 0.00010800361633300781, 0.00008916854858398438, 0.00010633468627929688, 0.00008869171142578125, 0.00014901161193847656, 0.0001392364501953125, 0.0001914501190185547, 0.00014710426330566406, 0.00024271011352539062, 0.00014662742614746094, 0.00018787384033203125, 0.00013256072998046875, 0.00008869171142578125, 0.00011134147644042969, 0.00015592575073242188, 0.000152587890625, 0.000202178955078125, 0.00018024444580078125, 0.00020051002502441406, 0.0001697540283203125, 0.00019931793212890625, 0.00009608268737792969, 0.00011682510375976562, 0.00009942054748535156, 0.00013136863708496094, 0.00010061264038085938, 0.00019669532775878906, 0.00010061264038085938, 0.00012111663818359375, 0.00009369850158691406, 0.00012755393981933594, 0.00010037422180175781, 0.00011301040649414062, 0.00008893013000488281, 0.00010991096496582031, 0.0001068115234375, 0.00008726119995117188, 0.00010848045349121094, 0.00008988380432128906, 0.0001125335693359375, 0.00009012222290039062, 0.000156402587890625, 0.00009083747863769531, 0.00011324882507324219, 0.0001666545867919922, 0.00008797645568847656, 0.00011277198791503906, 0.00008821487426757812, 0.00011610984802246094, 0.00009012222290039062, 0.00011301040649414062, 0.00009131431579589844, 0.00011110305786132812, 0.00019431114196777344, 0.00017762184143066406, 0.00022673606872558594, 0.0001709461212158203, 0.0001926422119140625, 0.0001010894775390625, 0.00023603439331054688, 0.0001704692840576172, 0.00019288063049316406, 0.0001239776611328125, 0.0001308917999267578, 0.000095367431640625, 0.0001480579376220703, 0.00017189979553222656, 0.0002257823944091797, 0.0001761913299560547, 0.00017023086547851562, 0.00009751319885253906, 0.00013589859008789062, 0.00014352798461914062, 0.00016808509826660156, 0.0001347064971923828, 0.00009989738464355469, 0.00013446807861328125, 0.00010204315185546875, 0.00018835067749023438, 0.00020051002502441406, 0.00018072128295898438, 0.0001316070556640625, 0.00015974044799804688, 0.00010895729064941406, 0.00013685226440429688, 0.00022935867309570312, 0.00015401840209960938, 0.0001583099365234375, 0.0001308917999267578, 0.0001842975616455078, 0.00022077560424804688, 0.0002543926239013672, 0.0001125335693359375, 0.00014591217041015625, 0.00009846687316894531, 0.00015211105346679688, 0.00011444091796875, 0.0001571178436279297, 0.00011205673217773438, 0.00009799003601074219, 0.00014448165893554688, 0.00011873245239257812, 0.0001544952392578125, 0.00011467933654785156, 0.00014662742614746094, 0.000091552734375, 0.00011205673217773438, 0.00008893013000488281, 0.00010895729064941406, 0.000091552734375, 0.00022649765014648438, 0.0001556873321533203, 0.00020194053649902344, 0.00016307830810546875, 0.0001392364501953125, 0.00014901161193847656, 0.00009179115295410156, 0.00011992454528808594, 0.00008845329284667969, 0.00011539459228515625, 0.00009012222290039062, 0.00011348724365234375, 0.00009369850158691406, 0.00012159347534179688, 0.00009441375732421875, 0.00011110305786132812, 0.0001590251922607422, 0.00013375282287597656, 0.00010704994201660156, 0.0001914501190185547, 0.00009846687316894531, 0.0001327991485595703, 0.00009322166442871094, 0.00012731552124023438, 0.00010514259338378906, 0.0001289844512939453, 0.00010466575622558594, 0.0001327991485595703, 0.00010657310485839844, 0.00010943412780761719, 0.00010657310485839844, 0.00010466575622558594, 0.000102996826171875, 0.00010466575622558594, 0.00014853477478027344, 0.000091552734375, 0.00011038780212402344, 0.00008916854858398438, 0.00010943412780761719, 0.00008988380432128906, 0.00011157989501953125, 0.00009131431579589844, 0.00011992454528808594, 0.00008869171142578125, 0.00012183189392089844, 0.00009393692016601562, 0.00011992454528808594, 0.00009942054748535156, 0.00012040138244628906, 0.00009560585021972656, 0.0001232624053955078, 0.00015878677368164062, 0.0001010894775390625, 0.00016689300537109375, 0.0001246929168701172, 0.00015854835510253906, 0.0000972747802734375, 0.0001361370086669922, 0.00011110305786132812, 0.0001399517059326172, 0.00011205673217773438, 0.0001361370086669922, 0.0001087188720703125, 0.00014519691467285156, 0.0001270771026611328, 0.0001575946807861328, 0.00013637542724609375, 0.00016641616821289062, 0.00015592575073242188, 0.00025272369384765625, 0.00021958351135253906, 0.00026488304138183594, 0.0002071857452392578, 0.00023436546325683594, 0.00017642974853515625, 0.0001838207244873047, 0.0002167224884033203, 0.0001590251922607422, 0.00019931793212890625, 0.0001480579376220703, 0.00021839141845703125, 0.00009036064147949219, 0.0001125335693359375, 0.00008678436279296875, 0.00010776519775390625, 0.00010728836059570312, 0.00012302398681640625, 0.00009584426879882812, 0.00021028518676757812, 0.00011873245239257812, 0.0001666545867919922, 0.00012159347534179688, 0.00014901161193847656, 0.000091552734375, 0.00020360946655273438, 0.00009274482727050781, 0.00011324882507324219, 0.00010752677917480469, 0.0001068115234375, 0.00010609626770019531, 0.00010728836059570312, 0.00010395050048828125, 0.00010228157043457031, 0.00010275840759277344, 0.0001404285430908203, 0.00014162063598632812, 0.00011277198791503906, 0.00008702278137207031, 0.00010800361633300781, 0.00009274482727050781, 0.00011706352233886719, 0.00012063980102539062, 0.00010037422180175781, 0.0001308917999267578, 0.00014257431030273438, 0.0001671314239501953, 0.00011968612670898438, 0.00020265579223632812, 0.00010561943054199219, 0.00013875961303710938, 0.00009465217590332031, 0.0001327991485595703, 0.00009083747863769531, 0.00011110305786132812, 0.00009179115295410156, 0.00011086463928222656, 0.00008916854858398438, 0.00011205673217773438, 0.00009322166442871094, 0.00011873245239257812, 0.00009393692016601562, 0.00011491775512695312, 0.0000934600830078125, 0.00011301040649414062, 0.0000896453857421875, 0.00011348724365234375, 0.00009202957153320312, 0.00011944770812988281, 0.00009369850158691406, 0.00011491775512695312, 0.00009107589721679688, 0.00011229515075683594, 0.00009298324584960938, 0.00011086463928222656, 0.00008749961853027344, 0.00010800361633300781, 0.0001232624053955078, 0.00011777877807617188, 0.00009417533874511719, 0.00011682510375976562, 0.0000934600830078125, 0.00011849403381347656, 0.0000934600830078125, 0.0002079010009765625, 0.00011277198791503906, 0.00014162063598632812, 0.00010633468627929688, 0.0001480579376220703, 0.00010156631469726562, 0.0001437664031982422, 0.00010728836059570312, 0.00013256072998046875, 0.00010037422180175781, 0.00014209747314453125, 0.00011348724365234375, 0.00012969970703125, 0.00012087821960449219, 0.00020265579223632812, 0.00011348724365234375, 0.00012826919555664062, 0.00012087821960449219, 0.00015234947204589844, 0.0001347064971923828, 0.00018405914306640625, 0.00011491775512695312, 0.0001621246337890625, 0.0001819133758544922, 0.0002601146697998047, 0.00009369850158691406, 0.00011801719665527344, 0.000087738037109375, 0.00010895729064941406, 0.00008702278137207031, 0.00015282630920410156, 0.000091552734375, 0.00010704994201660156, 0.00017380714416503906, 0.00010633468627929688, 0.0001049041748046875, 0.00010538101196289062, 0.00020003318786621094, 0.00009965896606445312, 0.00017690658569335938, 0.00010585784912109375, 0.00011301040649414062, 0.0000896453857421875, 0.00011324882507324219, 0.000087738037109375, 0.0001087188720703125, 0.00008797645568847656, 0.0001220703125, 0.00009107589721679688, 0.00018072128295898438, 0.00009250640869140625, 0.00011515617370605469, 0.00009202957153320312, 0.0001163482666015625, 0.00009417533874511719, 0.00013446807861328125, 0.000133514404296875, 0.00012373924255371094, 0.00009560585021972656, 0.00016570091247558594, 0.00009822845458984375, 0.00011491775512695312, 0.00008797645568847656, 0.00011205673217773438, 0.00012493133544921875, 0.00011706352233886719, 0.00008749961853027344, 0.00011515617370605469, 0.00009202957153320312, 0.00011515617370605469, 0.00008797645568847656, 0.0001304149627685547, 0.0001399517059326172, 0.0000896453857421875, 0.00011563301086425781, 0.00008749961853027344, 0.00028014183044433594, 0.00015473365783691406, 0.0002455711364746094, 0.00009822845458984375, 0.00011849403381347656, 0.00010967254638671875, 0.00009608268737792969, 0.00012183189392089844, 0.00009751319885253906, 0.0001163482666015625, 0.00009560585021972656, 0.00012946128845214844, 0.00009250640869140625, 0.00012731552124023438, 0.00009441375732421875, 0.00011610984802246094, 0.00008916854858398438, 0.00011181831359863281, 0.000091552734375, 0.00011038780212402344, 0.00011277198791503906, 0.00008869171142578125, 0.00011539459228515625, 0.00009298324584960938, 0.00011110305786132812, 0.0001621246337890625, 0.00010895729064941406, 0.0001938343048095703, 0.00013017654418945312, 0.0002396106719970703, 0.0001804828643798828, 0.00024771690368652344, 0.00018644332885742188, 0.00022339820861816406, 0.0001804828643798828, 0.00012922286987304688, 0.00009131431579589844, 0.00011396408081054688, 0.00009250640869140625, 0.00010943412780761719, 0.00008797645568847656, 0.0001773834228515625, 0.00009775161743164062, 0.00011801719665527344, 0.00008869171142578125, 0.00011372566223144531, 0.000091552734375, 0.00011324882507324219, 0.00008869171142578125, 0.0001385211944580078, 0.00011754035949707031, 0.00017523765563964844, 0.00011897087097167969, 0.00017452239990234375, 0.0001239776611328125, 0.00021696090698242188, 0.00009918212890625, 0.000194549560546875, 0.00012969970703125, 0.0001404285430908203, 0.00010585784912109375, 0.00013899803161621094, 0.00020956993103027344, 0.00011110305786132812, 0.00015592575073242188, 0.00011277198791503906, 0.00016570091247558594, 0.000118255615234375, 0.00016427040100097656, 0.00010848045349121094, 0.0001926422119140625, 0.00010442733764648438, 0.00011873245239257812, 0.00009393692016601562, 0.0002048015594482422, 0.00011372566223144531, 0.00011777877807617188, 0.00008821487426757812, 0.00010848045349121094, 0.000118255615234375, 0.00008797645568847656, 0.0001068115234375, 0.00008702278137207031, 0.00010848045349121094, 0.00008702278137207031, 0.00010657310485839844, 0.00010323524475097656, 0.00010466575622558594, 0.00010466575622558594, 0.00014543533325195312, 0.00009012222290039062, 0.00011730194091796875, 0.00009679794311523438, 0.0001373291015625, 0.00009655952453613281, 0.00013947486877441406, 0.00010848045349121094, 0.0001418590545654297, 0.00011372566223144531, 0.00011730194091796875, 0.00010013580322265625, 0.00012946128845214844, 0.00009417533874511719, 0.00009131431579589844, 0.00011944770812988281, 0.0001499652862548828, 0.00018453598022460938, 0.00009608268737792969, 0.00011372566223144531, 0.00008845329284667969, 0.00010895729064941406, 0.00008988380432128906, 0.000110626220703125, 0.00008916854858398438, 0.00011348724365234375, 0.00009608268737792969, 0.00011849403381347656, 0.00009632110595703125, 0.0001652240753173828, 0.00008821487426757812, 0.00010514259338378906, 0.00010514259338378906, 0.00011157989501953125, 0.00010824203491210938, 0.00008726119995117188, 0.00010466575622558594, 0.00012636184692382812, 0.00011277198791503906, 0.00024700164794921875, 0.00024008750915527344, 0.0002193450927734375, 0.00012564659118652344, 0.0001964569091796875, 0.0001780986785888672, 0.00010943412780761719, 0.00017118453979492188, 0.00011992454528808594, 0.0001575946807861328, 0.00011849403381347656, 0.00017213821411132812, 0.00015234947204589844, 0.000213623046875, 0.0001087188720703125, 0.0002143383026123047, 0.00009822845458984375, 0.00013637542724609375, 0.00008869171142578125, 0.00013566017150878906, 0.0001068115234375, 0.00014162063598632812, 0.00010228157043457031, 0.00014710426330566406, 0.00011134147644042969, 0.00015020370483398438, 0.00009369850158691406, 0.00011086463928222656, 0.00008702278137207031, 0.00010585784912109375, 0.00010895729064941406, 0.00008845329284667969, 0.00011157989501953125, 0.00008797645568847656, 0.00010561943054199219, 0.00012159347534179688, 0.00009918212890625, 0.00014972686767578125, 0.000118255615234375, 0.0001614093780517578, 0.000179290771484375, 0.00013327598571777344, 0.00010609626770019531, 0.0001900196075439453, 0.00010323524475097656, 0.00011467933654785156, 0.00008845329284667969, 0.0001087188720703125, 0.000087738037109375, 0.00010657310485839844, 0.0002090930938720703, 0.000152587890625, 0.00011324882507324219, 0.00014662742614746094, 0.00010895729064941406, 0.00011920928955078125, 0.00009107589721679688, 0.00011014938354492188, 0.00009107589721679688, 0.00010848045349121094, 0.00009965896606445312, 0.00012636184692382812, 0.00008916854858398438, 0.00010776519775390625, 0.00010395050048828125, 0.00010395050048828125, 0.00010323524475097656, 0.00010538101196289062, 0.00010156631469726562, 0.00011992454528808594, 0.00013327598571777344, 0.00008749961853027344, 0.00010895729064941406, 0.00010991096496582031, 0.00008702278137207031, 0.00010752677917480469, 0.00008940696716308594, 0.00011157989501953125, 0.00008940696716308594, 0.0001785755157470703, 0.00022172927856445312, 0.00017118453979492188, 0.0001888275146484375, 0.00015354156494140625, 0.00019621849060058594, 0.00009083747863769531, 0.000125885009765625, 0.00017023086547851562, 0.00018930435180664062, 0.00014972686767578125, 0.0001823902130126953, 0.00008821487426757812, 0.00011086463928222656, 0.000133514404296875, 0.00010800361633300781, 0.0001087188720703125, 0.0001087188720703125, 0.00008893013000488281, 0.00011014938354492188, 0.00008916854858398438, 0.00011229515075683594, 0.00009298324584960938, 0.00011229515075683594, 0.00009322166442871094, 0.00014138221740722656, 0.00014925003051757812, 0.00009775161743164062, 0.0001423358917236328, 0.00014090538024902344, 0.00010585784912109375, 0.00025200843811035156, 0.00014662742614746094, 0.00023126602172851562, 0.0001919269561767578, 0.0001289844512939453, 0.00009369850158691406, 0.00011134147644042969, 0.00008749961853027344, 0.00014328956604003906, 0.00008893013000488281, 0.0001251697540283203, 0.00009894371032714844, 0.0001347064971923828, 0.000110626220703125, 0.00014448165893554688, 0.00010967254638671875, 0.00012445449829101562, 0.00009179115295410156, 0.00013136863708496094, 0.00010323524475097656, 0.0001354217529296875, 0.00010395050048828125, 0.00013303756713867188, 0.00009608268737792969, 0.00018525123596191406, 0.00020241737365722656, 0.00019693374633789062, 0.00009775161743164062, 0.00012612342834472656, 0.0001068115234375, 0.00013828277587890625, 0.00011086463928222656, 0.0001506805419921875, 0.00009584426879882812, 0.00011897087097167969, 0.00009083747863769531, 0.000110626220703125, 0.000087738037109375, 0.0001068115234375, 0.00008726119995117188, 0.00010538101196289062, 0.00011134147644042969, 0.0002675056457519531, 0.00020623207092285156, 0.00024008750915527344, 0.00010466575622558594, 0.00013685226440429688, 0.00010228157043457031, 0.00014925003051757812, 0.00011682510375976562, 0.00014162063598632812, 0.00011038780212402344, 0.00014638900756835938, 0.00010395050048828125, 0.00011181831359863281, 0.00008797645568847656, 0.00011301040649414062, 0.000091552734375, 0.00016570091247558594, 0.00008821487426757812, 0.00010657310485839844, 0.00010538101196289062, 0.0001049041748046875, 0.00010418891906738281, 0.00010728836059570312, 0.00008678436279296875, 0.00010704994201660156, 0.00008702278137207031, 0.00010657310485839844, 0.00008869171142578125, 0.00011301040649414062, 0.00016117095947265625, 0.00009322166442871094, 0.00017786026000976562, 0.0001049041748046875, 0.00013518333435058594, 0.00013065338134765625, 0.000171661376953125, 0.00009131431579589844, 0.00011157989501953125, 0.00011658668518066406, 0.00009679794311523438, 0.00011324882507324219, 0.00009775161743164062, 0.00014066696166992188, 0.00010919570922851562, 0.00013399124145507812, 0.00016164779663085938, 0.0001366138458251953, 0.00009703636169433594, 0.0001354217529296875, 0.00009870529174804688, 0.00011730194091796875, 0.00009202957153320312, 0.00010800361633300781, 0.00010585784912109375, 0.00010752677917480469, 0.00009036064147949219, 0.00011610984802246094, 0.00009322166442871094, 0.00011324882507324219, 0.000095367431640625, 0.00011706352233886719, 0.00009131431579589844, 0.00011730194091796875, 0.000091552734375, 0.00011444091796875, 0.00009107589721679688, 0.00011539459228515625, 0.0000896453857421875, 0.00018787384033203125, 0.0002827644348144531, 0.0002124309539794922, 0.00017833709716796875, 0.00012111663818359375, 0.0001952648162841797, 0.00012826919555664062, 0.00015473365783691406, 0.00011467933654785156, 0.00015211105346679688, 0.00012373924255371094, 0.0001666545867919922, 0.0001437664031982422, 0.00011992454528808594, 0.00008726119995117188, 0.00010776519775390625, 0.00010347366333007812, 0.0001430511474609375, 0.00011301040649414062, 0.00015163421630859375, 0.00011229515075683594, 0.00014352798461914062, 0.00012302398681640625, 0.00012874603271484375, 0.00010561943054199219, 0.0001366138458251953, 0.00010538101196289062, 0.00013899803161621094, 0.00010728836059570312, 0.0001251697540283203, 0.00010442733764648438, 0.0001308917999267578, 0.00009226799011230469, 0.00013780593872070312, 0.00023245811462402344, 0.0001735687255859375, 0.0002543926239013672, 0.00016045570373535156, 0.0001266002655029297, 0.00009059906005859375, 0.00011539459228515625, 0.00020885467529296875, 0.00010657310485839844, 0.00013971328735351562, 0.00010585784912109375, 0.00011944770812988281, 0.00009942054748535156, 0.0001308917999267578, 0.00010585784912109375, 0.000164031982421875, 0.0001461505889892578, 0.0001628398895263672, 0.00011444091796875, 0.0001327991485595703, 0.00012350082397460938, 0.00016927719116210938, 0.0001957416534423828, 0.000194549560546875, 0.00010156631469726562, 0.0001347064971923828, 0.0001010894775390625, 0.00012493133544921875, 0.0001423358917236328, 0.00014901161193847656, 0.00020265579223632812, 0.00016736984252929688, 0.00009059906005859375, 0.000110626220703125, 0.00013017654418945312, 0.0001285076141357422, 0.00008726119995117188, 0.00011181831359863281, 0.00009250640869140625, 0.00011587142944335938, 0.00009012222290039062, 0.00012135505676269531, 0.00009083747863769531, 0.00017833709716796875, 0.00012063980102539062, 0.00014138221740722656, 0.00009298324584960938, 0.00010800361633300781, 0.00010776519775390625, 0.0001049041748046875, 0.00010514259338378906, 0.00010442733764648438, 0.00010418891906738281, 0.00010848045349121094, 0.00009202957153320312, 0.00010728836059570312, 0.00008702278137207031, 0.0001392364501953125, 0.00009322166442871094, 0.00010967254638671875, 0.00009322166442871094, 0.00010943412780761719, 0.00009298324584960938, 0.00011348724365234375, 0.00017499923706054688, 0.00011467933654785156, 0.00008821487426757812, 0.00011038780212402344, 0.00011181831359863281, 0.00011563301086425781, 0.00009274482727050781, 0.00011181831359863281, 0.00009107589721679688, 0.00009918212890625, 0.0001220703125, 0.0001361370086669922, 0.00013065338134765625, 0.00009632110595703125, 0.0001347064971923828, 0.00011515617370605469, 0.00014829635620117188, 0.00011491775512695312, 0.00014853477478027344, 0.00009274482727050781, 0.0001373291015625, 0.00009393692016601562, 0.00011038780212402344, 0.0000972747802734375, 0.0001285076141357422, 0.00010561943054199219, 0.00013065338134765625, 0.00010395050048828125, 0.00013637542724609375, 0.0001087188720703125, 0.00013375282287597656, 0.00009465217590332031, 0.0001277923583984375, 0.00010132789611816406, 0.00016951560974121094, 0.00009226799011230469, 0.00012826919555664062, 0.000102996826171875, 0.00012731552124023438, 0.00010132789611816406, 0.00012373924255371094, 0.000102996826171875, 0.00012636184692382812, 0.00010347366333007812, 0.0001842975616455078, 0.00010991096496582031, 0.00014448165893554688, 0.00010180473327636719, 0.00011444091796875, 0.000091552734375, 0.00010800361633300781, 0.00009584426879882812, 0.00021386146545410156, 0.0001087188720703125, 0.00012540817260742188, 0.00009655952453613281, 0.0001227855682373047, 0.00009703636169433594, 0.00011992454528808594, 0.00009775161743164062, 0.00014925003051757812, 0.00012946128845214844, 0.0002028942108154297, 0.00010919570922851562, 0.00015354156494140625, 0.0001323223114013672, 0.0001666545867919922, 0.00011444091796875, 0.00016546249389648438, 0.00010967254638671875, 0.0001437664031982422, 0.00011444091796875, 0.000148773193359375, 0.00010776519775390625, 0.00014591217041015625, 0.00011229515075683594, 0.00014781951904296875, 0.00011444091796875, 0.00020265579223632812, 0.00012302398681640625, 0.00016999244689941406, 0.00012874603271484375, 0.00009131431579589844, 0.00011491775512695312, 0.00009298324584960938, 0.00011348724365234375, 0.000091552734375, 0.00011420249938964844, 0.00009107589721679688, 0.00011587142944335938, 0.00009489059448242188, 0.00028252601623535156, 0.00011277198791503906, 0.00015974044799804688, 0.00012350082397460938, 0.0002543926239013672, 0.00012421607971191406, 0.00017333030700683594, 0.00012922286987304688, 0.0001709461212158203, 0.0001347064971923828, 0.00016045570373535156, 0.00011420249938964844, 0.0001659393310546875, 0.0001380443572998047, 0.00018286705017089844, 0.00013518333435058594, 0.00013184547424316406, 0.00009799003601074219, 0.00011754035949707031, 0.00009512901306152344, 0.00011682510375976562, 0.000095367431640625, 0.00011301040649414062, 0.0001456737518310547, 0.00011777877807617188, 0.00009226799011230469, 0.00011491775512695312, 0.00010228157043457031, 0.00014019012451171875, 0.00009489059448242188, 0.00011706352233886719, 0.00009369850158691406, 0.00011873245239257812, 0.000095367431640625, 0.00011777877807617188, 0.00009918212890625, 0.0001246929168701172, 0.00010037422180175781, 0.0001327991485595703, 0.00010728836059570312, 0.00015211105346679688, 0.00009965896606445312, 0.00012135505676269531, 0.00010752677917480469, 0.0001361370086669922, 0.00010728836059570312, 0.00013518333435058594, 0.00011610984802246094, 0.0001437664031982422, 0.00011324882507324219, 0.0001964569091796875, 0.00014281272888183594, 0.00012636184692382812, 0.00009489059448242188, 0.00011897087097167969, 0.00009775161743164062, 0.00012040138244628906, 0.00010371208190917969, 0.00012421607971191406, 0.00009894371032714844, 0.0001232624053955078, 0.00009989738464355469, 0.00013494491577148438, 0.00018644332885742188, 0.00010085105895996094, 0.00012087821960449219, 0.00010848045349121094, 0.000244140625, 0.00011134147644042969, 0.00015401840209960938, 0.00012230873107910156, 0.00016617774963378906, 0.0001347064971923828, 0.00017380714416503906, 0.00010704994201660156, 0.00014853477478027344, 0.00011348724365234375, 0.0001499652862548828, 0.0001068115234375, 0.00022482872009277344, 0.00011277198791503906, 0.00012564659118652344, 0.00009679794311523438, 0.0001227855682373047, 0.00009822845458984375, 0.0001342296600341797, 0.00010085105895996094, 0.0001251697540283203, 0.00010156631469726562, 0.0001239776611328125, 0.0001010894775390625, 0.00012230873107910156, 0.00009584426879882812, 0.00012230873107910156, 0.00013065338134765625, 0.0000972747802734375, 0.0001201629638671875, 0.00012636184692382812, 0.00016188621520996094, 0.00011801719665527344, 0.0001595020294189453, 0.00012803077697753906, 0.00016498565673828125, 0.00016260147094726562, 0.0001366138458251953, 0.0001678466796875, 0.00010371208190917969, 0.00012826919555664062, 0.00010085105895996094, 0.00012230873107910156, 0.00009870529174804688, 0.0001227855682373047, 0.00009965896606445312, 0.0001327991485595703, 0.0001747608184814453, 0.00011157989501953125, 0.00015974044799804688, 0.00016736984252929688, 0.0001087188720703125, 0.00016450881958007812, 0.0001583099365234375, 0.00017452239990234375, 0.0001418590545654297, 0.0001697540283203125, 0.00012636184692382812, 0.0001342296600341797, 0.00013113021850585938, 0.00028133392333984375, 0.0001742839813232422, 0.00016260147094726562, 0.00019931793212890625, 0.00014352798461914062, 0.00011610984802246094, 0.0001595020294189453, 0.00012040138244628906, 0.00016355514526367188, 0.00011706352233886719, 0.0002429485321044922, 0.0002560615539550781, 0.00023865699768066406, 0.0002372264862060547, 0.00023794174194335938, 0.00025963783264160156, 0.0002732276916503906, 0.00022602081298828125, 0.00021982192993164062, 0.00018334388732910156, 0.0002665519714355469, 0.00020265579223632812, 0.0002448558807373047, 0.00020599365234375, 0.00020885467529296875, 0.00017595291137695312, 0.00013256072998046875, 0.0002624988555908203, 0.0002818107604980469, 0.0002503395080566406, 0.0002300739288330078, 0.00014710426330566406, 0.00010418891906738281, 0.0001246929168701172, 0.00010251998901367188, 0.00013256072998046875, 0.000179290771484375, 0.00014162063598632812, 0.0002410411834716797, 0.0002498626708984375, 0.00024437904357910156, 0.000244140625, 0.00027251243591308594, 0.0002689361572265625, 0.00023174285888671875, 0.0002598762512207031, 0.00013017654418945312, 0.0001800060272216797, 0.00013637542724609375 ], "y0": " ", "yaxis": "y" } ], "layout": { "boxmode": "group", "legend": { "tracegroupgap": 0 }, "margin": { "t": 60 }, "template": { "data": { "bar": [ { "error_x": { "color": "#2a3f5f" }, "error_y": { "color": "#2a3f5f" }, "marker": { "line": { "color": "#E5ECF6", "width": 0.5 } }, "type": "bar" } ], "barpolar": [ { "marker": { "line": { "color": "#E5ECF6", "width": 0.5 } }, "type": "barpolar" } ], "carpet": [ { "aaxis": { "endlinecolor": "#2a3f5f", "gridcolor": "white", "linecolor": "white", "minorgridcolor": "white", "startlinecolor": "#2a3f5f" }, "baxis": { "endlinecolor": "#2a3f5f", "gridcolor": "white", "linecolor": "white", "minorgridcolor": "white", "startlinecolor": "#2a3f5f" }, "type": "carpet" } ], "choropleth": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "choropleth" } ], "contour": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "contour" } ], "contourcarpet": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "contourcarpet" } ], "heatmap": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "heatmap" } ], "heatmapgl": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "heatmapgl" } ], "histogram": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "histogram" } ], "histogram2d": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "histogram2d" } ], "histogram2dcontour": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "histogram2dcontour" } ], "mesh3d": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "mesh3d" } ], "parcoords": [ { "line": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "parcoords" } ], "pie": [ { "automargin": true, "type": "pie" } ], "scatter": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatter" } ], "scatter3d": [ { "line": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatter3d" } ], "scattercarpet": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattercarpet" } ], "scattergeo": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattergeo" } ], "scattergl": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattergl" } ], "scattermapbox": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattermapbox" } ], "scatterpolar": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterpolar" } ], "scatterpolargl": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterpolargl" } ], "scatterternary": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterternary" } ], "surface": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "surface" } ], "table": [ { "cells": { "fill": { "color": "#EBF0F8" }, "line": { "color": "white" } }, "header": { "fill": { "color": "#C8D4E3" }, "line": { "color": "white" } }, "type": "table" } ] }, "layout": { "annotationdefaults": { "arrowcolor": "#2a3f5f", "arrowhead": 0, "arrowwidth": 1 }, "autotypenumbers": "strict", "coloraxis": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "colorscale": { "diverging": [ [ 0, "#8e0152" ], [ 0.1, "#c51b7d" ], [ 0.2, "#de77ae" ], [ 0.3, "#f1b6da" ], [ 0.4, "#fde0ef" ], [ 0.5, "#f7f7f7" ], [ 0.6, "#e6f5d0" ], [ 0.7, "#b8e186" ], [ 0.8, "#7fbc41" ], [ 0.9, "#4d9221" ], [ 1, "#276419" ] ], "sequential": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "sequentialminus": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ] }, "colorway": [ "#636efa", "#EF553B", "#00cc96", "#ab63fa", "#FFA15A", "#19d3f3", "#FF6692", "#B6E880", "#FF97FF", "#FECB52" ], "font": { "color": "#2a3f5f" }, "geo": { "bgcolor": "white", "lakecolor": "white", "landcolor": "#E5ECF6", "showlakes": true, "showland": true, "subunitcolor": "white" }, "hoverlabel": { "align": "left" }, "hovermode": "closest", "mapbox": { "style": "light" }, "paper_bgcolor": "white", "plot_bgcolor": "#E5ECF6", "polar": { "angularaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "bgcolor": "#E5ECF6", "radialaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" } }, "scene": { "xaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" }, "yaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" }, "zaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" } }, "shapedefaults": { "line": { "color": "#2a3f5f" } }, "ternary": { "aaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "baxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "bgcolor": "#E5ECF6", "caxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" } }, "title": { "x": 0.05 }, "xaxis": { "automargin": true, "gridcolor": "white", "linecolor": "white", "ticks": "", "title": { "standoff": 15 }, "zerolinecolor": "white", "zerolinewidth": 2 }, "yaxis": { "automargin": true, "gridcolor": "white", "linecolor": "white", "ticks": "", "title": { "standoff": 15 }, "zerolinecolor": "white", "zerolinewidth": 2 } } }, "xaxis": { "anchor": "y", "domain": [ 0, 1 ], "title": { "text": "substep_label" } }, "yaxis": { "anchor": "x", "domain": [ 0, 1 ], "title": { "text": "psub_time" } } } }, "text/html": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "visualize_substep_impact(df, relative=False)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.0" } }, "nbformat": 4, "nbformat_minor": 2 } ================================================ FILE: documentation/examples/example_1.py ================================================ from pprint import pprint import pandas as pd from tabulate import tabulate from cadCAD.engine import ExecutionMode, ExecutionContext, Executor from documentation.examples import sys_model_A, sys_model_B, system_model_AB_exp from documentation.examples.sys_model_A import exp exec_mode = ExecutionMode() # Single Process Execution using a Single System Model Configuration: # sys_model_A local_proc_ctx = ExecutionContext(context=exec_mode.local_mode) sys_model_A_simulation = Executor(exec_context=local_proc_ctx, configs=exp.configs) sys_model_A_raw_result, sys_model_A_tensor_field, sessions = sys_model_A_simulation.execute() sys_model_A_result = pd.DataFrame(sys_model_A_raw_result) print() print("Tensor Field: sys_model_A") print(tabulate(sys_model_A_tensor_field, headers='keys', tablefmt='psql')) print("Result: System Events DataFrame") print(tabulate(sys_model_A_result, headers='keys', tablefmt='psql')) print() # # Multiple Processes Execution using Multiple System Model Configurations: # # sys_model_A & sys_model_B multi_proc_ctx = ExecutionContext(context=exec_mode.multi_proc) sys_model_AB_simulation = Executor(exec_context=multi_proc_ctx, configs=system_model_AB_exp.configs) sys_model_AB_raw_result, sys_model_AB_tensor_field, sessions = sys_model_AB_simulation.execute() print() sys_model_AB_result = pd.DataFrame(sys_model_AB_raw_result) print() print(f"Tensor Field:") print(tabulate(sys_model_AB_tensor_field, headers='keys', tablefmt='psql')) print("Result: System Events DataFrame:") print(tabulate(sys_model_AB_result, headers='keys', tablefmt='psql')) print() ================================================ FILE: documentation/examples/historical_state_access.py ================================================ import pandas as pd from tabulate import tabulate from cadCAD.configuration.utils import config_sim, access_block from cadCAD.engine import ExecutionMode, ExecutionContext, Executor from cadCAD.configuration import Experiment policies, variables = {}, {} exclusion_list = ['nonexsistant', 'last_x', '2nd_to_last_x', '3rd_to_last_x', '4th_to_last_x'] # Policies per Mechanism # state_history, target_field, psu_block_offset, exculsion_list def last_update(_g, substep, sH, s): return {"last_x": access_block( state_history=sH, target_field="last_x", psu_block_offset=-1, exculsion_list=exclusion_list ) } policies["last_x"] = last_update def second2last_update(_g, substep, sH, s): return {"2nd_to_last_x": access_block(sH, "2nd_to_last_x", -2, exclusion_list)} policies["2nd_to_last_x"] = second2last_update # Internal States per Mechanism # WARNING: DO NOT delete elements from sH def add(y, x): return lambda _g, substep, sH, s, _input: (y, s[y] + x) variables['x'] = add('x', 1) # last_partial_state_update_block def nonexsistant(_g, substep, sH, s, _input): return 'nonexsistant', access_block(sH, "nonexsistant", 0, exclusion_list) variables['nonexsistant'] = nonexsistant # last_partial_state_update_block def last_x(_g, substep, sH, s, _input): return 'last_x', _input["last_x"] variables['last_x'] = last_x # 2nd to last partial state update block def second_to_last_x(_g, substep, sH, s, _input): return '2nd_to_last_x', _input["2nd_to_last_x"] variables['2nd_to_last_x'] = second_to_last_x # 3rd to last partial state update block def third_to_last_x(_g, substep, sH, s, _input): return '3rd_to_last_x', access_block(sH, "3rd_to_last_x", -3, exclusion_list) variables['3rd_to_last_x'] = third_to_last_x # 4th to last partial state update block def fourth_to_last_x(_g, substep, sH, s, _input): return '4th_to_last_x', access_block(sH, "4th_to_last_x", -4, exclusion_list) variables['4th_to_last_x'] = fourth_to_last_x genesis_states = { 'x': 0, 'nonexsistant': [], 'last_x': [], '2nd_to_last_x': [], '3rd_to_last_x': [], '4th_to_last_x': [] } PSUB = { "policies": policies, "variables": variables } psubs = { "PSUB1": PSUB, "PSUB2": PSUB, "PSUB3": PSUB } sim_config = config_sim( { "N": 1, "T": range(3), } ) exp = Experiment() exp.append_model( model_id='hist_state_access', sim_configs=sim_config, initial_state=genesis_states, partial_state_update_blocks=psubs ) exec_mode = ExecutionMode() local_proc_ctx = ExecutionContext(context=exec_mode.local_mode) run = Executor(exec_context=local_proc_ctx, configs=exp.configs) raw_result, tensor_field, sessions = run.execute() result = pd.DataFrame(raw_result) cols = ['run','substep','timestep','x','nonexsistant','last_x','2nd_to_last_x','3rd_to_last_x','4th_to_last_x'] result = result[cols] print() print("Tensor Field:") print(tabulate(tensor_field, headers='keys', tablefmt='psql')) print("Output:") print(tabulate(result, headers='keys', tablefmt='psql')) print() ================================================ FILE: documentation/examples/param_sweep.py ================================================ import pprint import pandas as pd from tabulate import tabulate from cadCAD.configuration.utils import env_trigger, var_substep_trigger, config_sim, psub_list from cadCAD.engine import ExecutionMode, ExecutionContext, Executor from cadCAD.configuration import Experiment pp = pprint.PrettyPrinter(indent=4) def some_function(x): return x g: Dict[str, List[int]] = { 'alpha': [1], 'beta': [2, 5], 'gamma': [3, 4], 'omega': [some_function] } psu_steps = ['1', '2', '3'] system_substeps = len(psu_steps) var_timestep_trigger = var_substep_trigger([0, system_substeps]) env_timestep_trigger = env_trigger(system_substeps) env_process = {} # Policies def gamma(_params, step, sH, s): return {'gamma': _params['gamma']} def omega(_params, step, sH, s): return {'omega': _params['omega'](7)} # Internal States def alpha(_params, step, sH, s, _input): return 'alpha', _params['alpha'] def alpha_plus_gamma(_params, step, sH, s, _input): return 'alpha_plus_gamma', _params['alpha'] + _params['gamma'] def beta(_params, step, sH, s, _input): return 'beta', _params['beta'] def policies(_params, step, sH, s, _input): return 'policies', _input def sweeped(_params, step, sH, s, _input): return 'sweeped', {'beta': _params['beta'], 'gamma': _params['gamma']} genesis_states = { 'alpha_plus_gamma': 0, 'alpha': 0, 'beta': 0, 'policies': {}, 'sweeped': {} } env_process['sweeped'] = env_timestep_trigger(trigger_field='timestep', trigger_vals=[5], funct_list=[lambda _g, x: _g['beta']]) sim_config = config_sim( { "N": 2, "T": range(5), "M": g, } ) psu_block = {k: {"policies": {}, "variables": {}} for k in psu_steps} for m in psu_steps: psu_block[m]['policies']['gamma'] = gamma psu_block[m]['policies']['omega'] = omega psu_block[m]["variables"]['alpha'] = alpha_plus_gamma psu_block[m]["variables"]['alpha_plus_gamma'] = alpha psu_block[m]["variables"]['beta'] = beta psu_block[m]['variables']['policies'] = policies psu_block[m]["variables"]['sweeped'] = var_timestep_trigger(y='sweeped', f=sweeped) psubs = psub_list(psu_block, psu_steps) print() pp.pprint(psu_block) print() exp = Experiment() exp.append_model( model_id='param_sweep', sim_configs=sim_config, initial_state=genesis_states, env_processes=env_process, partial_state_update_blocks=psubs ) exec_mode = ExecutionMode() local_proc_ctx = ExecutionContext(context=exec_mode.local_mode) run = Executor(exec_context=local_proc_ctx, configs=exp.configs) raw_result, tensor_field, sessions = run.execute() result = pd.DataFrame(raw_result) print() print("Tensor Field:") print(tabulate(tensor_field, headers='keys', tablefmt='psql')) print("Output:") print(tabulate(result, headers='keys', tablefmt='psql')) print() ================================================ FILE: documentation/examples/policy_aggregation.py ================================================ import pandas as pd from tabulate import tabulate from cadCAD.configuration.utils import config_sim from cadCAD.engine import ExecutionMode, ExecutionContext, Executor from cadCAD.configuration import Experiment # Policies per Mechanism def p1m1(_g, step, sH, s): return {'policy1': 1} def p2m1(_g, step, sH, s): return {'policy2': 2} def p1m2(_g, step, sH, s): return {'policy1': 2, 'policy2': 2} def p2m2(_g, step, sH, s): return {'policy1': 2, 'policy2': 2} def p1m3(_g, step, sH, s): return {'policy1': 1, 'policy2': 2, 'policy3': 3} def p2m3(_g, step, sH, s): return {'policy1': 1, 'policy2': 2, 'policy3': 3} # Internal States per Mechanism def add(y, x): return lambda _g, step, sH, s, _input: (y, s[y] + x) def policies(_g, step, sH, s, _input): y = 'policies' x = _input return (y, x) # Genesis States genesis_states = { 'policies': {}, 's1': 0 } variables = { 's1': add('s1', 1), "policies": policies } psubs = { "m1": { "policies": { "p1": p1m1, "p2": p2m1 }, "variables": variables }, "m2": { "policies": { "p1": p1m2, "p2": p2m2 }, "variables": variables }, "m3": { "policies": { "p1": p1m3, "p2": p2m3 }, "variables": variables } } sim_config = config_sim( { "N": 1, "T": range(3), } ) exp = Experiment() exp.append_model( model_id='policy_agg', sim_configs=sim_config, initial_state=genesis_states, partial_state_update_blocks=psubs, policy_ops=[lambda a, b: a + b, lambda y: y * 2] # Default: lambda a, b: a + b ) exec_mode = ExecutionMode() local_proc_ctx = ExecutionContext(context=exec_mode.local_mode) run = Executor(exec_context=local_proc_ctx, configs=exp.configs) raw_result, tensor_field, sessions = run.execute() result = pd.DataFrame(raw_result) print() print("Tensor Field:") print(tabulate(tensor_field, headers='keys', tablefmt='psql')) print("Output:") print(tabulate(result, headers='keys', tablefmt='psql')) print() ================================================ FILE: documentation/examples/sys_model_A.py ================================================ import numpy as np from datetime import timedelta from cadCAD.configuration.utils import bound_norm_random, config_sim, time_step, env_trigger from cadCAD.configuration import Experiment from documentation.examples import system_model_AB_exp seeds = { 'z': np.random.RandomState(1), 'a': np.random.RandomState(2), 'b': np.random.RandomState(3), 'c': np.random.RandomState(4) } # Policies per Mechanism def p1m1(_g, step, sH, s): return {'param1': 1} def p2m1(_g, step, sH, s): return {'param1': 1, 'param2': 4} def p1m2(_g, step, sH, s): return {'param1': 'a', 'param2': 2} def p2m2(_g, step, sH, s): return {'param1': 'b', 'param2': 4} def p1m3(_g, step, sH, s): return {'param1': ['c'], 'param2': np.array([10, 100])} def p2m3(_g, step, sH, s): return {'param1': ['d'], 'param2': np.array([20, 200])} # Internal States per Mechanism def s1m1(_g, step, sH, s, _input): y = 's1' x = s['s1'] + 1 return (y, x) def s2m1(_g, step, sH, s, _input): y = 's2' x = _input['param2'] return (y, x) def s1m2(_g, step, sH, s, _input): y = 's1' x = s['s1'] + 1 return (y, x) def s2m2(_g, step, sH, s, _input): y = 's2' x = _input['param2'] return (y, x) def s1m3(_g, step, sH, s, _input): y = 's1' x = s['s1'] + 1 return (y, x) def s2m3(_g, step, sH, s, _input): y = 's2' x = _input['param2'] return (y, x) def policies(_g, step, sH, s, _input): y = 'policies' x = _input return (y, x) # Exogenous States proc_one_coef_A = 0.7 proc_one_coef_B = 1.3 def es3(_g, step, sH, s, _input): y = 's3' x = s['s3'] * bound_norm_random(seeds['a'], proc_one_coef_A, proc_one_coef_B) return (y, x) def es4(_g, step, sH, s, _input): y = 's4' x = s['s4'] * bound_norm_random(seeds['b'], proc_one_coef_A, proc_one_coef_B) return (y, x) def update_timestamp(_g, step, sH, s, _input): y = 'timestamp' return y, time_step(dt_str=s[y], dt_format='%Y-%m-%d %H:%M:%S', _timedelta=timedelta(days=0, minutes=0, seconds=1)) # Genesis States genesis_states = { 's1': 0.0, 's2': 0.0, 's3': 1.0, 's4': 1.0, 'timestamp': '2018-10-01 15:16:24' } # Environment Process trigger_timestamps = ['2018-10-01 15:16:25', '2018-10-01 15:16:27', '2018-10-01 15:16:29'] env_processes = { "s3": [lambda _g, x: 5], "s4": env_trigger(3)(trigger_field='timestamp', trigger_vals=trigger_timestamps, funct_list=[lambda _g, x: 10]) } psubs = [ { "policies": { "b1": p1m1, "b2": p2m1 }, "variables": { "s1": s1m1, "s2": s2m1, "s3": es3, "s4": es4, "timestamp": update_timestamp } }, { "policies": { "b1": p1m2, "b2": p2m2 }, "variables": { "s1": s1m2, "s2": s2m2, # "s3": es3p1, # "s4": es4p2, } }, { "policies": { "b1": p1m3, "b2": p2m3 }, "variables": { "s1": s1m3, "s2": s2m3, # "s3": es3p1, # "s4": es4p2, } } ] sim_config = config_sim( { "N": 2, "T": range(1), } ) exp = Experiment() exp.append_model( model_id='sys_model_A', sim_configs=sim_config, initial_state=genesis_states, env_processes=env_processes, partial_state_update_blocks=psubs, policy_ops=[lambda a, b: a + b] ) system_model_AB_exp.append_model( model_id='sys_model_A', sim_configs=sim_config, initial_state=genesis_states, env_processes=env_processes, partial_state_update_blocks=psubs, policy_ops=[lambda a, b: a + b] ) ================================================ FILE: documentation/examples/sys_model_AB_exec.py ================================================ import pandas as pd from tabulate import tabulate from cadCAD.engine import ExecutionMode, ExecutionContext, Executor from documentation.examples import sys_model_A, sys_model_B, system_model_AB_exp exec_mode = ExecutionMode() # Multiple Processes Execution using Multiple System Model Configurations: local_proc_ctx = ExecutionContext(context=exec_mode.local_mode) sys_model_AB_simulation = Executor(exec_context=local_proc_ctx, configs=system_model_AB_exp.configs) i = 0 config_names = ['sys_model_A', 'sys_model_B'] sys_model_AB_raw_result, sys_model_AB_tensor_field, sessions = sys_model_AB_simulation.execute() sys_model_AB_result = pd.DataFrame(sys_model_AB_raw_result) print() print(f"Tensor Field:") print(tabulate(sys_model_AB_tensor_field, headers='keys', tablefmt='psql')) print("Result: System Events DataFrame:") print(tabulate(sys_model_AB_result, headers='keys', tablefmt='psql')) print() ================================================ FILE: documentation/examples/sys_model_A_exec.py ================================================ import pandas as pd from tabulate import tabulate from cadCAD.engine import ExecutionMode, ExecutionContext, Executor from documentation.examples import sys_model_A from documentation.examples.sys_model_A import exp exec_mode = ExecutionMode() # Single Process Execution using a Single System Model Configuration: local_proc_ctx = ExecutionContext(context=exec_mode.local_mode) sys_model_A_simulation = Executor(exec_context=local_proc_ctx, configs=exp.configs) sys_model_A_raw_result, sys_model_A_tensor_field, sessions = sys_model_A_simulation.execute() sys_model_A_result = pd.DataFrame(sys_model_A_raw_result) print() print("Tensor Field: sys_model_A") print(tabulate(sys_model_A_tensor_field, headers='keys', tablefmt='psql')) print("Result: System Events DataFrame") print(tabulate(sys_model_A_result, headers='keys', tablefmt='psql')) print() ================================================ FILE: documentation/examples/sys_model_B.py ================================================ import numpy as np from datetime import timedelta from cadCAD.configuration.utils import bound_norm_random, config_sim, env_trigger, time_step from cadCAD.configuration import Experiment from documentation.examples import system_model_AB_exp seeds = { 'z': np.random.RandomState(1), 'a': np.random.RandomState(2), 'b': np.random.RandomState(3), 'c': np.random.RandomState(3) } # Policies per Mechanism def p1m1(_g, step, sH, s): return {'param1': 1} def p2m1(_g, step, sH, s): return {'param2': 4} def p1m2(_g, step, sH, s): return {'param1': 'a', 'param2': 2} def p2m2(_g, step, sH, s): return {'param1': 'b', 'param2': 4} def p1m3(_g, step, sH, s): return {'param1': ['c'], 'param2': np.array([10, 100])} def p2m3(_g, step, sH, s): return {'param1': ['d'], 'param2': np.array([20, 200])} # Internal States per Mechanism def s1m1(_g, step, sH, s, _input): y = 's1' x = _input['param1'] return (y, x) def s2m1(_g, step, sH, s, _input): y = 's2' x = _input['param2'] return (y, x) def s1m2(_g, step, sH, s, _input): y = 's1' x = _input['param1'] return (y, x) def s2m2(_g, step, sH, s, _input): y = 's2' x = _input['param2'] return (y, x) def s1m3(_g, step, sH, s, _input): y = 's1' x = _input['param1'] return (y, x) def s2m3(_g, step, sH, s, _input): y = 's2' x = _input['param2'] return (y, x) # Exogenous States proc_one_coef_A = 0.7 proc_one_coef_B = 1.3 def es3(_g, step, sH, s, _input): y = 's3' x = s['s3'] * bound_norm_random(seeds['a'], proc_one_coef_A, proc_one_coef_B) return (y, x) def es4(_g, step, sH, s, _input): y = 's4' x = s['s4'] * bound_norm_random(seeds['b'], proc_one_coef_A, proc_one_coef_B) return (y, x) def update_timestamp(_g, step, sH, s, _input): y = 'timestamp' return y, time_step(dt_str=s[y], dt_format='%Y-%m-%d %H:%M:%S', _timedelta=timedelta(days=0, minutes=0, seconds=1)) # Genesis States genesis_states = { 's1': 0, 's2': 0, 's3': 1, 's4': 1, 'timestamp': '2018-10-01 15:16:24' } # Environment Process trigger_timestamps = ['2018-10-01 15:16:25', '2018-10-01 15:16:27', '2018-10-01 15:16:29'] env_processes = { "s3": [lambda _g, x: 5], "s4": env_trigger(3)(trigger_field='timestamp', trigger_vals=trigger_timestamps, funct_list=[lambda _g, x: 10]) } psubs = [ { "policies": { "b1": p1m1, # "b2": p2m1 }, "states": { "s1": s1m1, # "s2": s2m1 "s3": es3, "s4": es4, "timestep": update_timestamp } }, { "policies": { "b1": p1m2, # "b2": p2m2 }, "states": { "s1": s1m2, # "s2": s2m2 } }, { "policies": { "b1": p1m3, "b2": p2m3 }, "states": { "s1": s1m3, "s2": s2m3 } } ] sim_config = config_sim( { "N": 2, "T": range(5), } ) exp = Experiment() exp.append_model( model_id='sys_model_B', sim_configs=sim_config, initial_state=genesis_states, env_processes=env_processes, partial_state_update_blocks=psubs ) system_model_AB_exp.append_model( model_id='sys_model_B', sim_configs=sim_config, initial_state=genesis_states, env_processes=env_processes, partial_state_update_blocks=psubs, policy_ops=[lambda a, b: a + b] ) ================================================ FILE: documentation/examples/sys_model_B_exec.py ================================================ import pandas as pd from tabulate import tabulate # The following imports NEED to be in the exact order from cadCAD.engine import ExecutionMode, ExecutionContext, Executor from documentation.examples import sys_model_B from documentation.examples.sys_model_B import exp exec_mode = ExecutionMode() print("Simulation Execution: Single Configuration") print() local_proc_ctx = ExecutionContext(context=exec_mode.local_mode) run = Executor(exec_context=local_proc_ctx, configs=exp.configs) raw_result, tensor_field, sessions = run.execute() result = pd.DataFrame(raw_result) print() print("Tensor Field: sys_model_B") print(tabulate(tensor_field, headers='keys', tablefmt='psql')) print("Output:") print(tabulate(result, headers='keys', tablefmt='psql')) print() ================================================ FILE: requirements.txt ================================================ -i https://pypi.org/simple parameterized>=0.7.4 pytest>=6.0.2 tabulate>=0.8.7 wheel>=0.38.1 pandas>=1.1.5 funcy>=1.16 dill>=0.3.4 pathos>=0.2.8 numpy>=1.22.0 pytz>=2021.1 setuptools>=69.0.2 graphviz>=0.20.1 tqdm>=4.65.0 pytest>=7.4.3 ================================================ FILE: setup.py ================================================ from setuptools import find_packages, setup short_description = ( "cadCAD: a differential games based simulation software package for research, validation, and \ Computer Aided Design of economic systems" ) long_description = """ cadCAD (complex adaptive systems computer-aided design) is a python based, unified modeling framework for stochastic dynamical systems and differential games for research, validation, and Computer Aided Design of economic systems created by BlockScience. It is capable of modeling systems at all levels of abstraction from Agent Based Modeling (ABM) to System Dynamics (SD), and enabling smooth integration of computational social science simulations with empirical data science workflows. An economic system is treated as a state-based model and defined through a set of endogenous and exogenous state variables which are updated through mechanisms and environmental processes, respectively. Behavioral models, which may be deterministic or stochastic, provide the evolution of the system within the action space of the mechanisms. Mathematical formulations of these economic games treat agent utility as derived from the state rather than direct from an action, creating a rich, dynamic modeling framework. Simulations may be run with a range of initial conditions and parameters for states, behaviors, mechanisms, and environmental processes to understand and visualize network behavior under various conditions. Support for A/B testing policies, Monte Carlo analysis, and other common numerical methods is provided. """ name = "cadCAD" version = "0.5.3" setup( name=name, version=version, description=short_description, long_description=long_description, url="https://github.com/cadCAD-org/cadCAD", author="cadCAD-org Developers", author_email="info@block.science", license="LICENSE.txt", packages=find_packages(), install_requires=[ "pandas", "funcy", "dill", "pathos", "numpy", "pytz", "six", "tqdm", ], python_requires=">=3.9.0", ) ================================================ FILE: testing/__init__.py ================================================ ================================================ FILE: testing/experiments/__init__.py ================================================ from cadCAD.configuration import Experiment exp_param_sweep = Experiment() exp_policy_agg = Experiment() ================================================ FILE: testing/generic_test.py ================================================ import unittest from functools import reduce from tabulate import tabulate def generate_assertions_df(df, expected_results, target_cols, evaluations): test_names = [] for eval_f in evaluations: def wrapped_eval(a, b): try: return eval_f(a, b) except KeyError: return True test_name = f"{eval_f.__name__}_test" test_names.append(test_name) df[test_name] = df.apply( lambda x: wrapped_eval( x.filter(items=target_cols).to_dict(), expected_results[(x['subset'], x['run'], x['timestep'], x['substep'])] ), axis=1 ) return df, test_names def make_generic_test(params): class TestSequence(unittest.TestCase): def generic_test(self, tested_df, expected_reults, test_name): erroneous = tested_df[(tested_df[test_name] == False)] print(tabulate(tested_df, headers='keys', tablefmt='psql')) if erroneous.empty is False: # Or Entire df IS NOT erroneous for index, row in erroneous.iterrows(): # expected = expected_reults[(row['simulation'], row['run'], row['timestep'], row['substep'])] expected = expected_reults[(row['subset'], row['run'], row['timestep'], row['substep'])] unexpected = {f"invalid_{k}": expected[k] for k in expected if k in row and expected[k] != row[k]} for key in unexpected.keys(): erroneous[key] = None erroneous.at[index, key] = unexpected[key] # etc. self.assertTrue(reduce(lambda a, b: a and b, tested_df[test_name])) @parameterized.expand(params) def test_validation(self, name, result_df, expected_results, target_cols, evaluations): tested_df, test_names = generate_assertions_df(result_df, expected_results, target_cols, evaluations) for test_name in test_names: self.generic_test(tested_df, expected_results, test_name) return TestSequence ================================================ FILE: testing/models/__init__.py ================================================ from cadCAD.configuration import Experiment exp = Experiment() ================================================ FILE: testing/models/param_sweep.py ================================================ import pprint from cadCAD import experiment from cadCAD.configuration import Experiment from cadCAD.configuration.utils import env_trigger, var_substep_trigger, config_sim, psub_list from typing import Dict, List pp = pprint.PrettyPrinter(indent=4) def some_function(x): return x # Optional # dict must contain lists opf 2 distinct lengths g: Dict[str, List[int]] = { 'alpha': [1], 'beta': [2, some_function], 'gamma': [3, 4], # 'beta': [1], # 'gamma': [4], 'omega': [7] } psu_steps = ['m1', 'm2', 'm3'] system_substeps = len(psu_steps) var_timestep_trigger = var_substep_trigger([0, system_substeps]) env_timestep_trigger = env_trigger(system_substeps) env_process = {} # ['s1', 's2', 's3', 's4'] # Policies per Mechanism def gamma(_g, step, sL, s, **kwargs): return {'gamma': _g['gamma']} def omega(_g, step, sL, s, **kwargs): return {'omega': _g['omega']} # Internal States per Mechanism def alpha(_g, step, sL, s, _input, **kwargs): return 'alpha', _g['alpha'] def beta(_g, step, sL, s, _input, **kwargs): return 'beta', _g['beta'] def policies(_g, step, sL, s, _input, **kwargs): return 'policies', _input def sweeped(_g, step, sL, s, _input, **kwargs): return 'sweeped', {'beta': _g['beta'], 'gamma': _g['gamma']} psu_block = {k: {"policies": {}, "states": {}} for k in psu_steps} for m in psu_steps: psu_block[m]['policies']['gamma'] = gamma psu_block[m]['policies']['omega'] = omega psu_block[m]["states"]['alpha'] = alpha psu_block[m]["states"]['beta'] = beta psu_block[m]['states']['policies'] = policies psu_block[m]["states"]['sweeped'] = var_timestep_trigger(y='sweeped', f=sweeped) # Genesis States genesis_states = { 'alpha': 0, 'beta': 0, 'policies': {}, 'sweeped': {} } # Environment Process env_process['sweeped'] = env_timestep_trigger(trigger_field='timestep', trigger_vals=[5], funct_list=[lambda _g, x: _g['beta']]) sim_config = config_sim( { "N": 2, "T": range(5), "M": g, # Optional } ) # New Convention partial_state_update_blocks = psub_list(psu_block, psu_steps) exp = Experiment() exp.append_model( sim_configs=sim_config, initial_state=genesis_states, env_processes=env_process, partial_state_update_blocks=partial_state_update_blocks ) experiment.append_model( sim_configs=sim_config, initial_state=genesis_states, env_processes=env_process, partial_state_update_blocks=partial_state_update_blocks ) ================================================ FILE: testing/models/policy_aggregation.py ================================================ from cadCAD.configuration import Experiment from cadCAD.configuration.utils import config_sim # Policies per Mechanism def p1m1(_g, step, sL, s, **kwargs): return {'policy1': 1} def p2m1(_g, step, sL, s, **kwargs): return {'policy2': 2} def p1m2(_g, step, sL, s, **kwargs): return {'policy1': 2, 'policy2': 2} def p2m2(_g, step, sL, s, **kwargs): return {'policy1': 2, 'policy2': 2} def p1m3(_g, step, sL, s, **kwargs): return {'policy1': 1, 'policy2': 2, 'policy3': 3} def p2m3(_g, step, sL, s, **kwargs): return {'policy1': 1, 'policy2': 2, 'policy3': 3} # Internal States per Mechanism def add(y, x): return lambda _g, step, sH, s, _input, **kwargs: (y, s[y] + x) def policies(_g, step, sH, s, _input, **kwargs): y = 'policies' x = _input return (y, x) # Genesis States genesis_states = { 'policies': {}, 's1': 0 } variables = { 's1': add('s1', 1), "policies": policies } partial_state_update_block = { "m1": { "policies": { "p1": p1m1, "p2": p2m1 }, "variables": variables }, "m2": { "policies": { "p1": p1m2, "p2": p2m2 }, "variables": variables }, "m3": { "policies": { "p1": p1m3, "p2": p2m3 }, "variables": variables } } sim_config = config_sim( { "N": 1, "T": range(3), } ) exp = Experiment() exp.append_model( sim_configs=sim_config, initial_state=genesis_states, partial_state_update_blocks=partial_state_update_block, policy_ops=[lambda a, b: a + b, lambda y: y * 2] # Default: lambda a, b: a + b ) ================================================ FILE: testing/results_comparison.py ================================================ import unittest import pandas as pd # type: ignore from tabulate import tabulate # type: ignore from pandas._testing import assert_frame_equal # type: ignore from testing.utils import assertEqual def compare_results_pytest(result_diff): val_error_status_ind = False not in result_diff.val_error_status.tolist() type_error_status_ind = False not in result_diff.type_error_status.tolist() df_out = None erroneous_indexes = None select_result_diff = None if (val_error_status_ind is False) or (type_error_status_ind is False): erroneous_indexes = list(result_diff.index[result_diff["val_error_status"] == False]) select_result_diff = result_diff.iloc[erroneous_indexes] df_out = tabulate(select_result_diff, headers='keys', tablefmt='psql') assertEqual(val_error_status_ind, True, "Value Error") assertEqual(type_error_status_ind, True, "Type Error") def compare_results(result_diff): class CompareResults(unittest.TestCase): def setUp(self): result_diff.columns self.val_error_status_ind = False not in result_diff.val_error_status.tolist() self.type_error_status_ind = False not in result_diff.type_error_status.tolist() self.df_out = None self.erroneous_indexes = None self.select_result_diff = None if (self.val_error_status_ind is False) or (self.type_error_status_ind is False): self.erroneous_indexes = list(result_diff.index[result_diff["val_error_status"] == False]) self.select_result_diff = result_diff.iloc[self.erroneous_indexes] self.df_out = tabulate(self.select_result_diff, headers='keys', tablefmt='psql') def test_val_error_status(self): print(self.df_out) self.assertEqual(self.val_error_status_ind, True, "Value Error") def test_type_error_status(self): print(self.df_out) self.assertEqual(self.type_error_status_ind, True, "Type Error") return CompareResults def dataframe_difference(df1, df2): def discrepancies(row): return { col: {'values': list(vals), 'type': [type(v) for v in vals]} for col, vals in row.items() if vals[0] != vals[1] } def val_error_status(val): if type(val) is dict and len(val) != 0: return False else: return True def type_error_status(val): if type(val) is dict and len(val) != 0: return list(set([v['type'][0] == v['type'][1] for k, v in val.items()]))[0] else: return True df1_cols, df2_cols = list(df1.columns), list(df2.columns) if set(df1_cols) == set(df2_cols) and df1.shape == df2.shape: df_equal_ind = True try: assert_frame_equal(df1, df2) except: df_equal_ind = False if df_equal_ind is False: data = [list(zip(df1[col], df2[col])) for col in df1_cols] df = pd.DataFrame(data).T df.columns = df1_cols df['discrepancies'] = df.apply(discrepancies, axis=1) result_df1 = df1.reset_index() discrepancies_df = df[['discrepancies']].reset_index() result_diff = result_df1.merge(discrepancies_df, how='left', on='index') result_diff['val_error_status'] = result_diff['discrepancies'].apply(val_error_status) result_diff['type_error_status'] = result_diff['discrepancies'].apply(type_error_status) return result_diff else: df1['discrepancies'] = None df1['val_error_status'] = True df1['type_error_status'] = True return df1 else: df1_row_count, df1_col_count = df1.shape df2_row_count, df2_col_count = df2.shape raise Exception(f""" DataFrames have mismatched dimensions or columns: Columns: * df1: {df1_cols} * df2: {df2_cols} Shapes: * df1: * Row Count: {df1_row_count} * Column Count: {df1_col_count} * df2: * Row Count: {df2_row_count} * Column Count: {df2_col_count} """) ================================================ FILE: testing/test_additional_objs.py ================================================ from typing import Dict, List from cadCAD.engine import Executor, ExecutionContext, ExecutionMode from cadCAD.configuration import Experiment from cadCAD.configuration.utils import env_trigger, var_substep_trigger, config_sim, psub_list from cadCAD.types import * import pandas as pd # type: ignore import types import inspect import pytest def describe_or_return(v: object) -> object: """ Thanks @LinuxIsCool! """ if isinstance(v, types.FunctionType): return f'function: {v.__name__}' elif isinstance(v, types.LambdaType) and v.__name__ == '': return f'lambda: {inspect.signature(v)}' else: return v def select_M_dict(M_dict: Dict[str, object], keys: set) -> Dict[str, object]: """ Thanks @LinuxIsCool! """ return {k: describe_or_return(v) for k, v in M_dict.items() if k in keys} def select_config_M_dict(configs: list, i: int, keys: set) -> Dict[str, object]: return select_M_dict(configs[i].sim_config['M'], keys) def drop_substeps(_df): first_ind = (_df.substep == 0) & (_df.timestep == 0) last_ind = _df.substep == max(_df.substep) inds_to_drop = first_ind | last_ind return _df.copy().loc[inds_to_drop].drop(columns=['substep']) def assign_params(_df: pd.DataFrame, configs) -> pd.DataFrame: """ Based on `cadCAD-tools` package codebase, by @danlessa """ M_dict = configs[0].sim_config['M'] params_set = set(M_dict.keys()) selected_params = params_set # Attribute parameters to each row # 1. Assign the parameter set from the first row first, so that # columns are created first_param_dict = select_config_M_dict(configs, 0, selected_params) # 2. Attribute parameter on an (simulation, subset, run) basis df = _df.assign(**first_param_dict).copy() for i, (_, subset_df) in enumerate(df.groupby(['simulation', 'subset', 'run'])): df.loc[subset_df.index] = subset_df.assign(**select_config_M_dict(configs, i, selected_params)) return df SWEEP_PARAMS: Dict[str, List] = { 'alpha': [1], 'beta': [lambda x: 2 * x, lambda x: x], 'gamma': [3, 4], 'omega': [7] } SINGLE_PARAMS: Dict[str, object] = { 'alpha': 1, 'beta': lambda x: x, 'gamma': 3, 'omega': 5 } def create_experiment(N_RUNS=2, N_TIMESTEPS=3, params: dict=SWEEP_PARAMS): psu_steps = ['m1', 'm2', 'm3'] system_substeps = len(psu_steps) var_timestep_trigger = var_substep_trigger([0, system_substeps]) env_timestep_trigger = env_trigger(system_substeps) env_process = {} # ['s1', 's2', 's3', 's4'] # Policies per Mechanism def gamma(params: Parameters, substep: Substep, history: StateHistory, state: State, **kwargs): return {'gamma': params['gamma']} def omega(params: Parameters, substep: Substep, history: StateHistory, state: State, **kwarg): return {'omega': params['omega']} # Internal States per Mechanism def alpha(params: Parameters, substep: Substep, history: StateHistory, state: State, _input: PolicyOutput, **kwargs): return 'alpha_var', params['alpha'] def beta(params: Parameters, substep: Substep, history: StateHistory, state: State, _input: PolicyOutput, **kwargs): return 'beta_var', params['beta'] def gamma_var(params: Parameters, substep: Substep, history: StateHistory, state: State, _input: PolicyOutput, **kwargs): return 'gamma_var', params['gamma'] def omega_var(params: Parameters, substep: Substep, history: StateHistory, state: State, _input: PolicyOutput, **kwargs): return 'omega_var', params['omega'] def policies(params: Parameters, substep: Substep, history: StateHistory, state: State, _input: PolicyOutput, **kwargs): return 'policies', _input def sweeped(params: Parameters, substep: Substep, history: StateHistory, state: State, _input: PolicyOutput, **kwargs): return 'sweeped', {'beta': params['beta'], 'gamma': params['gamma']} psu_block: dict = {k: {"policies": {}, "states": {}} for k in psu_steps} for m in psu_steps: psu_block[m]['policies']['gamma'] = gamma psu_block[m]['policies']['omega'] = omega psu_block[m]["states"]['alpha_var'] = alpha psu_block[m]["states"]['beta_var'] = beta psu_block[m]["states"]['gamma_var'] = gamma_var psu_block[m]["states"]['omega_var'] = omega_var psu_block[m]['states']['policies'] = policies psu_block[m]["states"]['sweeped'] = var_timestep_trigger(y='sweeped', f=sweeped) # Genesis States genesis_states = { 'alpha_var': 0, 'beta_var': 0, 'gamma_var': 0, 'omega_var': 0, 'policies': {}, 'sweeped': {} } # Environment Process env_process['sweeped'] = env_timestep_trigger(trigger_field='timestep', trigger_vals=[5], funct_list=[lambda _g, x: _g['beta']]) sim_config = config_sim( { "N": N_RUNS, "T": range(N_TIMESTEPS), "M": params, # Optional } ) # New Convention partial_state_update_blocks = psub_list(psu_block, psu_steps) exp = Experiment() exp.append_model( sim_configs=sim_config, initial_state=genesis_states, env_processes=env_process, partial_state_update_blocks=partial_state_update_blocks ) return exp def test_deepcopy_off(): exp = create_experiment() mode = ExecutionMode().local_mode exec_context = ExecutionContext(mode, additional_objs={'deepcopy_off': True}) executor = Executor(exec_context=exec_context, configs=exp.configs) (records, tensor_field, _) = executor.execute() df = drop_substeps(assign_params(pd.DataFrame(records), exp.configs)) # XXX: parameters should always be of the same type. Else, the test will fail first_sim_config = exp.configs[0].sim_config['M'] for (i, row) in df.iterrows(): if row.timestep > 0: assert row['alpha_var'] == row['alpha'] assert type(row['alpha_var']) == type(first_sim_config['alpha']) assert row['gamma_var'] == row['gamma'] assert type(row['gamma_var']) == type(first_sim_config['gamma']) assert row['omega_var'] == row['omega'] assert type(row['omega_var']) == type(first_sim_config['omega']) ================================================ FILE: testing/test_arg_count.py ================================================ from typing import Dict, List from cadCAD.engine import Executor, ExecutionContext, ExecutionMode from cadCAD.configuration import Experiment from cadCAD.configuration.utils import env_trigger, var_substep_trigger, config_sim, psub_list from cadCAD.types import * import pandas as pd # type: ignore import types import inspect import pytest def test_sufs(): psubs = [ { 'policies': { 'p_A': lambda _1, _2, _3, _4: {} }, 'variables': { 'v_A': lambda _1, _2, _3, _4, _5: ('a', 1) } } ] initial_state = { 'v_A': None } params = {'p_A': [1]} N_t = 5 N_r = 1 sim_config = config_sim( { "N": N_r, "T": range(N_t), "M": params, # Optional } ) exp = Experiment() exp.append_model( sim_configs=sim_config, initial_state=initial_state, partial_state_update_blocks=psubs ) mode = ExecutionMode().local_mode exec_context = ExecutionContext(mode, additional_objs={'deepcopy_off': True}) executor = Executor(exec_context=exec_context, configs=exp.configs) (records, tensor_field, _) = executor.execute() ================================================ FILE: testing/test_param_count.py ================================================ from cadCAD.configuration import Experiment from cadCAD.configuration.utils import config_sim from cadCAD.engine import Executor, ExecutionContext, ExecutionMode import pytest P_no_lst = {'pA': 1, 'pB': 2, 'pC': 3} P_single_lst = {'pA': [1], 'pB': [1], 'pC': [3]} P_single_swp = {'pA': [4, 5, 6], 'pB': [1], 'pC': [3]} P_all_swp = {'pA': [7, 8, 9], 'pB': [1, 2, 3], 'pC': [1, 2, 3]} P_all_but_one_swp = {'pA': [7, 8, 9], 'pB': [1, 2, 3], 'pC': [1]} Ps = [P_no_lst, P_single_lst, P_single_swp, P_all_swp, P_all_but_one_swp] CONFIG_SIGNATURES_TO_TEST = [(3, 3, 3, 3, 3), (1, 3, 3, 3, 3), (3, 1, 3, 3, 3), (1, 1, 3, 3, 3), (3, 3, 1, 3, 3), (1, 3, 1, 3, 3), (1, 1, 1, 3, 3)] def run_experiment(exp: Experiment, mode: str): exec_context = ExecutionContext(mode) executor = Executor(exec_context=exec_context, configs=exp.configs) (records, tensor_field, _) = executor.execute() return records def param_count_test_suf_generator(provided_params): def s_test_param_count(params, _2, _3, _4, _5): assert params.keys() == provided_params.keys(), 'Params are not matching' return ('varA', None) return s_test_param_count def param_count_test_policy_generator(provided_params): def p_test_param_count(params, _2, _3, _4): assert params.keys() == provided_params.keys(), 'Params are not matching' return {'sigA': None} return p_test_param_count def create_experiments(N_simulations=3, N_sweeps=3, N_runs=3, N_timesteps=3, N_substeps=3, params={}) -> Experiment: INITIAL_STATE = {'varA': None} PSUBs = [{'policies': {'sigA': param_count_test_policy_generator( params)}, 'variables': {'varA': param_count_test_suf_generator(params)}}] * N_substeps SIM_CONFIG = config_sim( { "N": N_runs, "T": range(N_timesteps), "M": params, # Optional } ) exp = Experiment() for i_sim in range(N_simulations): exp.append_model( sim_configs=SIM_CONFIG, initial_state=INITIAL_STATE, partial_state_update_blocks=PSUBs ) return exp def expected_rows(N_simulations, N_sweeps, N_runs, N_timesteps, N_substeps, P) -> int: return N_simulations * N_sweeps * N_runs * (N_timesteps * N_substeps + 1) @pytest.mark.parametrize("N_sim,N_sw,N_r,N_t,N_s", CONFIG_SIGNATURES_TO_TEST) @pytest.mark.parametrize("P", Ps) def test_row_count_single(N_sim, N_sw, N_r, N_t, N_s, P): args = (N_sim, N_sw, N_r, N_t, N_s, P) len(run_experiment(create_experiments(*args), 'single_proc')) @pytest.mark.parametrize("N_sim,N_sw,N_r,N_t,N_s", CONFIG_SIGNATURES_TO_TEST) @pytest.mark.parametrize("P", Ps) def test_row_count_local(N_sim, N_sw, N_r, N_t, N_s, P): args = (N_sim, N_sw, N_r, N_t, N_s, P) len(run_experiment(create_experiments(*args), 'local_proc')) ================================================ FILE: testing/test_print.py ================================================ from cadCAD.configuration import Experiment from cadCAD.configuration.utils import config_sim from cadCAD.engine import Executor, ExecutionContext, ExecutionMode import pytest P_no_lst = {'pA': 1, 'pB': 2, 'pC': 3} P_single_lst = {'pA': [1], 'pB': [1], 'pC': [3]} P_single_swp = {'pA': [4, 5, 6], 'pB': [1], 'pC': [3]} P_all_swp = {'pA': [7, 8, 9], 'pB': [1, 2, 3], 'pC': [1, 2, 3]} P_all_but_one_swp = {'pA': [7, 8, 9], 'pB': [1, 2, 3], 'pC': [1]} Ps = [P_no_lst, P_single_lst, P_single_swp, P_all_swp, P_all_but_one_swp] CONFIG_SIGNATURES_TO_TEST = [(3, 3, 3, 3, 3), (1, 3, 3, 3, 3), (3, 1, 3, 3, 3), (1, 1, 3, 3, 3), (3, 3, 1, 3, 3), (1, 3, 1, 3, 3), (1, 1, 1, 3, 3)] def run_experiment(exp: Experiment, mode: str, supress_print=False): exec_context = ExecutionContext(mode) executor = Executor(exec_context=exec_context, configs=exp.configs, supress_print=supress_print) (records, tensor_field, _) = executor.execute() return records def param_count_test_suf_generator(provided_params): def s_test_param_count(params, _2, _3, _4, _5): assert params.keys() == provided_params.keys(), 'Params are not matching' return ('varA', None) return s_test_param_count def param_count_test_policy_generator(provided_params): def p_test_param_count(params, _2, _3, _4): assert params.keys() == provided_params.keys(), 'Params are not matching' return {'sigA': None} return p_test_param_count def create_experiments(N_simulations=3, N_sweeps=3, N_runs=3, N_timesteps=3, N_substeps=3, params={}) -> Experiment: INITIAL_STATE = {'varA': None} PSUBs = [{'policies': {'sigA': param_count_test_policy_generator( params)}, 'variables': {'varA': param_count_test_suf_generator(params)}}] * N_substeps SIM_CONFIG = config_sim( { "N": N_runs, "T": range(N_timesteps), "M": params, # Optional } ) exp = Experiment() for i_sim in range(N_simulations): exp.append_model( sim_configs=SIM_CONFIG, initial_state=INITIAL_STATE, partial_state_update_blocks=PSUBs ) return exp def test_print(capfd): exp = run_experiment(create_experiments(N_simulations=3, N_sweeps=3, N_runs=3, N_timesteps=3, N_substeps=3, params={'a': 0}), 'single_proc', supress_print=False) out, err = capfd.readouterr() assert " ___________ ____\n ________ __ ___/ / ____/ | / __ \\\n / ___/ __` / __ / / / /| | / / / /\n/ /__/ /_/ / /_/ / /___/ ___ |/ /_/ /\n\\___/\\__,_/\\__,_/\\____/_/ |_/_____/\nby cadCAD" in out assert 'Initializing configurations' in err exp = run_experiment(create_experiments(N_simulations=3, N_sweeps=3, N_runs=3, N_timesteps=3, N_substeps=3, params={'a': 0}), 'single_proc', supress_print=True) out, err = capfd.readouterr() assert out == '' assert err == '' ================================================ FILE: testing/test_results_signature.py ================================================ from cadCAD.configuration import Experiment from cadCAD.configuration.utils import config_sim from cadCAD.engine import Executor, ExecutionContext, ExecutionMode import pytest import pandas as pd # type: ignore from typing import Dict, List # (N_simulations, N_sweeps, N_runs, N_timesteps, N_substeps) CONFIG_SIGNATURES_TO_TEST = [ (1, 20, 5, 10, 5), (3, 3, 3, 3, 3), (1, 3, 3, 3, 3), (3, 1, 3, 3, 3), (1, 1, 3, 3, 3), (3, 3, 1, 3, 3), (1, 3, 1, 3, 3), (1, 1, 1, 3, 3)] def run_experiment(exp: Experiment, mode: str) -> List[Dict]: exec_context = ExecutionContext(mode) executor = Executor(exec_context=exec_context, configs=exp.configs) (records, tensor_field, _) = executor.execute() return records def create_experiments(N_simulations=3, N_sweeps=3, N_runs=3, N_timesteps=3, N_substeps=3) -> Experiment: INITIAL_STATE = {'varA': None} PSUBs = [{'policies': {}, 'variables': {}}] * N_substeps params = {'A': [None] * N_sweeps, 'B': [None]} SIM_CONFIG = config_sim( { "N": N_runs, "T": range(N_timesteps), "M": params, # Optional } ) exp = Experiment() for i_sim in range(N_simulations): exp.append_model( sim_configs=SIM_CONFIG, initial_state=INITIAL_STATE, partial_state_update_blocks=PSUBs ) return exp def expected_rows(N_simulations, N_sweeps, N_runs, N_timesteps, N_substeps) -> int: return N_simulations * N_sweeps * N_runs * (N_timesteps * N_substeps + 1) @pytest.mark.parametrize("N_sim,N_sw,N_r,N_t,N_s", CONFIG_SIGNATURES_TO_TEST) def test_identifiers_value_counts_single(N_sim, N_sw, N_r, N_t, N_s): args = (N_sim, N_sw, N_r, N_t, N_s) results = run_experiment(create_experiments(*args), 'single_proc') df = pd.DataFrame(results).query("timestep > 0") assert len(set(df.timestep.value_counts().values)) == 1 assert len(set(df.subset.value_counts().values)) == 1 assert len(set(df.run.value_counts().values)) == 1 @pytest.mark.parametrize("N_sim,N_sw,N_r,N_t,N_s", CONFIG_SIGNATURES_TO_TEST[:-1]) def test_identifiers_value_counts_multi(N_sim, N_sw, N_r, N_t, N_s): args = (N_sim, N_sw, N_r, N_t, N_s) results = run_experiment(create_experiments(*args), 'multi_proc') df = pd.DataFrame(results).query("timestep > 0") assert len(set(df.timestep.value_counts().values)) == 1 assert len(set(df.subset.value_counts().values)) == 1 assert len(set(df.run.value_counts().values)) == 1 ================================================ FILE: testing/test_row_count.py ================================================ from cadCAD.configuration import Experiment from cadCAD.configuration.utils import config_sim from cadCAD.engine import Executor, ExecutionContext, ExecutionMode import pytest import pandas as pd # type: ignore from typing import Dict, List CONFIG_SIGNATURES_TO_TEST = [(3, 3, 3, 3, 3), (1, 3, 3, 3, 3), (3, 1, 3, 3, 3), (1, 1, 3, 3, 3), (3, 3, 1, 3, 3), (1, 3, 1, 3, 3), (1, 1, 1, 3, 3)] def run_experiment(exp: Experiment, mode: str) -> List[Dict]: exec_context = ExecutionContext(mode) executor = Executor(exec_context=exec_context, configs=exp.configs) (records, tensor_field, _) = executor.execute() return records def create_experiments(N_simulations=3, N_sweeps=3, N_runs=3, N_timesteps=3, N_substeps=3) -> Experiment: INITIAL_STATE = {'varA': None} PSUBs = [{'policies': {}, 'variables': {}}] * N_substeps params = {'A': [None] * N_sweeps, 'B': [None]} SIM_CONFIG = config_sim( { "N": N_runs, "T": range(N_timesteps), "M": params, # Optional } ) exp = Experiment() for i_sim in range(N_simulations): exp.append_model( sim_configs=SIM_CONFIG, initial_state=INITIAL_STATE, partial_state_update_blocks=PSUBs ) return exp def expected_rows(N_simulations, N_sweeps, N_runs, N_timesteps, N_substeps) -> int: return N_simulations * N_sweeps * N_runs * (N_timesteps * N_substeps + 1) @pytest.mark.parametrize("N_sim,N_sw,N_r,N_t,N_s", CONFIG_SIGNATURES_TO_TEST) def test_row_count_single(N_sim, N_sw, N_r, N_t, N_s): args = (N_sim, N_sw, N_r, N_t, N_s) results = run_experiment(create_experiments(*args), 'single_proc') assert len(results) == expected_rows(*args) @pytest.mark.parametrize("N_sim,N_sw,N_r,N_t,N_s", CONFIG_SIGNATURES_TO_TEST) def test_row_count_multi(N_sim, N_sw, N_r, N_t, N_s): args = (N_sim, N_sw, N_r, N_t, N_s) if N_sim == 1 and N_sw == 1 and N_r == 1: with pytest.raises(ValueError) as e_info: assert len(run_experiment(create_experiments(*args), 'multi_proc')) == expected_rows(*args) else: assert len(run_experiment(create_experiments(*args), 'multi_proc')) == expected_rows(*args) @pytest.mark.parametrize("N_sim,N_sw,N_r,N_t,N_s", CONFIG_SIGNATURES_TO_TEST) def test_row_count_local(N_sim, N_sw, N_r, N_t, N_s): args = (N_sim, N_sw, N_r, N_t, N_s) assert len(run_experiment(create_experiments(*args), 'local_proc')) == expected_rows(*args) ================================================ FILE: testing/test_runs.py ================================================ from typing import Dict, List, Optional from cadCAD.engine import Executor, ExecutionContext, ExecutionMode from cadCAD.configuration import Experiment from cadCAD.configuration.utils import env_trigger, var_substep_trigger, config_sim, psub_list from cadCAD.types import * import pandas as pd # type: ignore import types import inspect import pytest from pandas import DataFrame def describe_or_return(v: object) -> object: """ Thanks @LinuxIsCool! """ if isinstance(v, types.FunctionType): return f'function: {v.__name__}' elif isinstance(v, types.LambdaType) and v.__name__ == '': return f'lambda: {inspect.signature(v)}' else: return v def select_M_dict(M_dict: Dict[str, object], keys: set) -> Dict[str, object]: """ Thanks @LinuxIsCool! """ return {k: describe_or_return(v) for k, v in M_dict.items() if k in keys} def select_config_M_dict(configs: list, i: int, keys: set) -> Dict[str, object]: return select_M_dict(configs[i].sim_config['M'], keys) def drop_substeps(_df): first_ind = (_df.substep == 0) & (_df.timestep == 0) last_ind = _df.substep == max(_df.substep) inds_to_drop = first_ind | last_ind return _df.copy().loc[inds_to_drop].drop(columns=['substep']) def assign_params(_df: pd.DataFrame, configs) -> pd.DataFrame: """ Based on `cadCAD-tools` package codebase, by @danlessa """ M_dict = configs[0].sim_config['M'] params_set = set(M_dict.keys()) selected_params = params_set # Attribute parameters to each row # 1. Assign the parameter set from the first row first, so that # columns are created first_param_dict = select_config_M_dict(configs, 0, selected_params) # 2. Attribute parameter on an (simulation, subset, run) basis df = _df.assign(**first_param_dict).copy() for i, (_, subset_df) in enumerate(df.groupby(['simulation', 'subset', 'run'])): df.loc[subset_df.index] = subset_df.assign(**select_config_M_dict(configs, i, selected_params)) return df SWEEP_PARAMS: Dict[str, List] = { 'alpha': [1], 'beta': [lambda x: 2 * x, lambda x: x, lambda x: x / 2], 'gamma': [3, 4, 5], 'omega': [7] } SINGLE_PARAMS: Dict[str, object] = { 'alpha': 1, 'beta': lambda x: x, 'gamma': 3, 'omega': 5 } def create_experiment(N_RUNS=2, N_TIMESTEPS=3, params: dict = SWEEP_PARAMS): psu_steps = ['m1', 'm2', 'm3'] system_substeps = len(psu_steps) var_timestep_trigger = var_substep_trigger([0, system_substeps]) env_timestep_trigger = env_trigger(system_substeps) env_process = {} # ['s1', 's2', 's3', 's4'] # Policies per Mechanism def gamma(params: Parameters, substep: Substep, history: StateHistory, state: State, **kwargs): return {'gamma': params['gamma']} def omega(params: Parameters, substep: Substep, history: StateHistory, state: State, **kwarg): return {'omega': params['omega']} # Internal States per Mechanism def alpha(params: Parameters, substep: Substep, history: StateHistory, state: State, _input: PolicyOutput, **kwargs): return 'alpha_var', params['alpha'] def beta(params: Parameters, substep: Substep, history: StateHistory, state: State, _input: PolicyOutput, **kwargs): return 'beta_var', params['beta'] def gamma_var(params: Parameters, substep: Substep, history: StateHistory, state: State, _input: PolicyOutput, **kwargs): return 'gamma_var', params['gamma'] def omega_var(params: Parameters, substep: Substep, history: StateHistory, state: State, _input: PolicyOutput, **kwargs): return 'omega_var', params['omega'] def policies(params: Parameters, substep: Substep, history: StateHistory, state: State, _input: PolicyOutput, **kwargs): return 'policies', _input def sweeped(params: Parameters, substep: Substep, history: StateHistory, state: State, _input: PolicyOutput, **kwargs): return 'sweeped', {'beta': params['beta'], 'gamma': params['gamma']} psu_block: dict = {k: {"policies": {}, "states": {}} for k in psu_steps} for m in psu_steps: psu_block[m]['policies']['gamma'] = gamma psu_block[m]['policies']['omega'] = omega psu_block[m]["states"]['alpha_var'] = alpha psu_block[m]["states"]['beta_var'] = beta psu_block[m]["states"]['gamma_var'] = gamma_var psu_block[m]["states"]['omega_var'] = omega_var psu_block[m]['states']['policies'] = policies psu_block[m]["states"]['sweeped'] = var_timestep_trigger( y='sweeped', f=sweeped) # Genesis States genesis_states = { 'alpha_var': 0, 'beta_var': 0, 'gamma_var': 0, 'omega_var': 0, 'policies': {}, 'sweeped': {} } # Environment Process env_process['sweeped'] = env_timestep_trigger(trigger_field='timestep', trigger_vals=[ 5], funct_list=[lambda _g, x: _g['beta']]) sim_config = config_sim( { "N": N_RUNS, "T": range(N_TIMESTEPS), "M": params, # Optional } ) # New Convention partial_state_update_blocks = psub_list(psu_block, psu_steps) exp = Experiment() exp.append_model( sim_configs=sim_config, initial_state=genesis_states, env_processes=env_process, partial_state_update_blocks=partial_state_update_blocks ) return exp @pytest.mark.parametrize("mode", ["local_proc", "single_proc", "multi_proc"]) def test_mc_sweep_experiment(mode): experiment_assertions(create_experiment( N_RUNS=2, N_TIMESTEPS=2, params=SWEEP_PARAMS), mode) @pytest.mark.parametrize("mode", ["local_proc", "single_proc", "multi_proc"]) def test_unique_sweep_experiment(mode): experiment_assertions(create_experiment( N_RUNS=1, N_TIMESTEPS=2, params=SWEEP_PARAMS), mode) @pytest.mark.parametrize("mode", ["local_proc", "single_proc", "multi_proc"]) def test_mc_single_experiment(mode): experiment_assertions(create_experiment( N_RUNS=2, N_TIMESTEPS=2, params=SINGLE_PARAMS), mode) @pytest.mark.parametrize("mode", ["local_proc", "single_proc", "multi_proc"]) def test_unique_single_experiment(mode): if mode == "multi_proc": with pytest.raises(ValueError) as e_info: experiment_assertions(create_experiment( N_RUNS=1, N_TIMESTEPS=2, params=SINGLE_PARAMS), mode) else: experiment_assertions(create_experiment( N_RUNS=1, N_TIMESTEPS=2, params=SINGLE_PARAMS), mode) def experiment_assertions(exp: Experiment, mode: Optional[str]=None) -> None: if mode == None: mode = ExecutionMode().local_mode exec_context = ExecutionContext(mode) executor = Executor(exec_context=exec_context, configs=exp.configs) (records, tensor_field, _) = executor.execute() df: DataFrame = assign_params(pd.DataFrame(records), exp.configs) df = drop_substeps(df) # XXX: parameters should always be of the same type. Else, the test will fail first_sim_config = exp.configs[0].sim_config['M'] required_keys = {'simulation': int, 'run': int, 'subset': int, 'timestep': int} for (i, row) in df.iterrows(): if row.timestep > 0: assert row['alpha_var'] == row['alpha'] assert type(row['alpha_var']) == type(first_sim_config['alpha']) assert row['gamma_var'] == row['gamma'] assert type(row['gamma_var']) == type(first_sim_config['gamma']) assert row['omega_var'] == row['omega'] assert type(row['omega_var']) == type(first_sim_config['omega']) for k, v in required_keys.items(): assert k in row assert type(row[k]) == v ================================================ FILE: testing/tests/__init__.py ================================================ ================================================ FILE: testing/tests/a_b_tests/0_4_23_record_count.json ================================================ {"record_count": 74} ================================================ FILE: testing/tests/a_b_tests/multi_model_row_count_0_4_23.py ================================================ import json, pathlib, pandas as pd from cadCAD import configs from cadCAD.configuration import Experiment from cadCAD.engine import ExecutionMode, ExecutionContext, Executor from testing.models import param_sweep, policy_aggregation del configs[:] exp = Experiment() sys_model_A_id = "sys_model_A" exp.append_configs( sim_configs=param_sweep.sim_config, initial_state=param_sweep.genesis_states, env_processes=param_sweep.env_process, partial_state_update_blocks=param_sweep.partial_state_update_blocks ) sys_model_B_id = "sys_model_B" exp.append_configs( sim_configs=param_sweep.sim_config, initial_state=param_sweep.genesis_states, env_processes=param_sweep.env_process, partial_state_update_blocks=param_sweep.partial_state_update_blocks ) sys_model_C_id = "sys_model_C" exp.append_configs( sim_configs=policy_aggregation.sim_config, initial_state=policy_aggregation.genesis_states, partial_state_update_blocks=policy_aggregation.partial_state_update_block, policy_ops=[lambda a, b: a + b, lambda y: y * 2] # Default: lambda a, b: a + b ) exec_mode = ExecutionMode() local_mode_ctx = ExecutionContext(context=exec_mode.local_mode) simulation = Executor(exec_context=local_mode_ctx, configs=configs) raw_results, _, _ = simulation.execute() results_df = pd.DataFrame(raw_results) result_rows = len(results_df.index) file_dir = pathlib.Path(__file__).parent.absolute() file_path = f'{file_dir}/0_4_23_record_count.json' with open(file_path, 'w') as json_file: record_count = {'record_count': result_rows} json.dump(record_count, json_file) ================================================ FILE: testing/tests/append_mod_test.py ================================================ import unittest from copy import deepcopy from testing.models import exp from testing.models.param_sweep import sim_config as sim_config_a from testing.models.param_sweep import genesis_states as genesis_states_a from testing.models.param_sweep import env_process as env_process_a from testing.models.param_sweep import partial_state_update_blocks as psubs_a def append_model_id(model_ids, sim_config, genesis_states, env_process, psubs): exp_copy = deepcopy(exp) for mod_id in model_ids: exp_copy.append_model( model_id=mod_id, sim_configs=sim_config, initial_state=genesis_states, env_processes=env_process, partial_state_update_blocks=psubs, policy_ops=[lambda a, b: a + b] ) return exp_copy class AppendModelTest(unittest.TestCase): def test_index_model_ids(self): no_id_exp = append_model_id( model_ids=[None] * 10, sim_config=sim_config_a, genesis_states=genesis_states_a, env_process=env_process_a, psubs=psubs_a ) expected = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'] self.assertEqual(no_id_exp.model_ids == expected, True, "Incorrect Indexing of System Model IDs") def test_same_model_ids(self): same_id_exp = append_model_id( model_ids=['sys_model'] * 10, sim_config=sim_config_a, genesis_states=genesis_states_a, env_process=env_process_a, psubs=psubs_a ) expected = [ 'sys_model', 'sys_model@1', 'sys_model@2', 'sys_model@3', 'sys_model@4', 'sys_model@5', 'sys_model@6', 'sys_model@7', 'sys_model@8', 'sys_model@9' ] self.assertEqual(same_id_exp.model_ids == expected, True, "Incorrect Duplicate Indexing of System Model IDs") def test_different_model_ids(self): diff_id_exp = append_model_id( model_ids=[f'sys_model_{i}' for i in list(range(10))], sim_config=sim_config_a, genesis_states=genesis_states_a, env_process=env_process_a, psubs=psubs_a ) expected = [ 'sys_model_0', 'sys_model_1', 'sys_model_2', 'sys_model_3', 'sys_model_4', 'sys_model_5', 'sys_model_6', 'sys_model_7', 'sys_model_8', 'sys_model_9' ] self.assertEqual(diff_id_exp.model_ids == expected, True, "Incorrect Unique System Model IDs") def test_mix_model_ids(self): mix_exp = append_model_id( model_ids=[None, 'sys_model_A', None, 'sys_model_B', 'model@3', 'model@3'], sim_config=sim_config_a, genesis_states=genesis_states_a, env_process=env_process_a, psubs=psubs_a ) expected = ['0', 'sys_model_A', '2', 'sys_model_B', 'model@3', 'model@3@5'] self.assertEqual(mix_exp.model_ids == expected, True, "Incorrect System Model ID Mix") if __name__ == '__main__': unittest.main() ================================================ FILE: testing/tests/import_cadCAD.ipynb ================================================ { "cells": [ { "cell_type": "code", "execution_count": 2, "id": "15b9b09a", "metadata": {}, "outputs": [], "source": [ "import cadCAD, os, pathlib, json" ] }, { "cell_type": "code", "execution_count": 3, "id": "1b54b99a", "metadata": {}, "outputs": [], "source": [ "# dunder_file = os.path.abspath('')\n", "# file_path = f'{dunder_file}/expected_results/cadCAD_memory_address.json'\n", "file_path = f'{os.getcwd()}/cadCAD_memory_address.json'\n", "with open(file_path, 'w') as json_file:\n", " memory_address = {'memory_address': hex(id(cadCAD))}\n", " json.dump(memory_address, json_file)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.0" } }, "nbformat": 4, "nbformat_minor": 5 } ================================================ FILE: testing/tests/test_cadCAD_exp.py ================================================ import pandas as pd from tabulate import tabulate from testing.results_comparison import dataframe_difference, compare_results_pytest from cadCAD import configs from cadCAD.engine import ExecutionMode, ExecutionContext, Executor import pytest @pytest.fixture def empty_experiment(): exec_mode = ExecutionMode() exec_ctx = ExecutionContext(context=exec_mode.local_mode) run = Executor(exec_context=exec_ctx, configs=configs) raw_result, _, _ = run.execute() result_df = pd.DataFrame(raw_result) expected_df = pd.read_pickle("expected_results/param_sweep_4.pkl") return dataframe_difference(result_df, expected_df) def test_experiment(empty_experiment): compare_results_pytest(empty_experiment) ================================================ FILE: testing/tests/test_import_cadCAD_test.py ================================================ import os, subprocess, json from testing.utils import assertEqual def test_jupyter_nbconvert_row_count(): command = f'jupyter nbconvert --to=notebook --ExecutePreprocessor.enabled=True {os.getcwd()}/testing/tests/import_cadCAD.ipynb' process = subprocess.Popen(command.split(), stdout=subprocess.PIPE) process.communicate() json_path = f'{os.getcwd()}/testing/tests/cadCAD_memory_address.json' memory_address = json.load(open(json_path))['memory_address'] assertEqual(type(memory_address) == str, True, "cadCAD is not importable by jupyter server") ================================================ FILE: testing/tests/test_multi_model_row_count.py ================================================ import json import os import pandas as pd # type: ignore from cadCAD.configuration import Experiment from cadCAD.engine import ExecutionMode, ExecutionContext, Executor from testing.models import param_sweep, policy_aggregation import pytest from dataclasses import dataclass from testing.utils import assertEqual @dataclass class MultiModelRowCountResults(): expected_rows: object expected_rows_from_api: object result_rows: object param_sweep_df_rows: object policy_agg_df_rows: object sys_model_A_id: object sys_model_B_id: object sys_model_C_id: object model_A_rows: object model_B_rows: object model_C_rows: object @pytest.fixture def multi_model_row_count(): exp = Experiment() sys_model_A_id = "sys_model_A" exp.append_model( model_id=sys_model_A_id, sim_configs=param_sweep.sim_config, initial_state=param_sweep.genesis_states, env_processes=param_sweep.env_process, partial_state_update_blocks=param_sweep.partial_state_update_blocks ) sys_model_B_id = "sys_model_B" exp.append_model( model_id=sys_model_B_id, sim_configs=param_sweep.sim_config, initial_state=param_sweep.genesis_states, env_processes=param_sweep.env_process, partial_state_update_blocks=param_sweep.partial_state_update_blocks ) sys_model_C_id = "sys_model_C" exp.append_model( model_id=sys_model_C_id, sim_configs=policy_aggregation.sim_config, initial_state=policy_aggregation.genesis_states, partial_state_update_blocks=policy_aggregation.partial_state_update_block, policy_ops=[lambda a, b: a + b, lambda y: y * 2] # Default: lambda a, b: a + b ) simulation = 3 model_A_sweeps = len(param_sweep.sim_config) model_B_sweeps = len(param_sweep.sim_config) model_C_sweeps = 1 # total_sweeps = model_A_sweeps + model_B_sweeps model_A_runs = param_sweep.sim_config[0]['N'] model_B_runs = param_sweep.sim_config[0]['N'] model_C_runs = policy_aggregation.sim_config['N'] # total_runs = model_A_runs + model_B_runs model_A_timesteps = len(param_sweep.sim_config[0]['T']) model_B_timesteps = len(param_sweep.sim_config[0]['T']) model_C_timesteps = len(policy_aggregation.sim_config['T']) model_A_substeps = len(param_sweep.partial_state_update_blocks) model_B_substeps = len(param_sweep.partial_state_update_blocks) model_C_substeps = len(policy_aggregation.partial_state_update_block) # total_substeps = model_A_substeps + model_B_substeps model_A_init_rows = model_A_runs * model_A_sweeps model_B_init_rows = model_B_runs * model_B_sweeps model_C_init_rows = model_C_runs * 1 model_A_rows = model_A_init_rows + (model_A_sweeps * (model_A_runs * model_A_timesteps * model_A_substeps)) model_B_rows = model_B_init_rows + (model_B_sweeps * (model_B_runs * model_B_timesteps * model_B_substeps)) model_C_rows = model_C_init_rows + (model_C_sweeps * (model_C_runs * model_C_timesteps * model_C_substeps)) exec_mode = ExecutionMode() local_mode_ctx = ExecutionContext(context=exec_mode.local_mode) simulation = Executor(exec_context=local_mode_ctx, configs=exp.configs) raw_results, _, _ = simulation.execute() results_df = pd.DataFrame(raw_results) param_sweep_df = pd.read_pickle("expected_results/param_sweep_4.pkl") policy_agg_df = pd.read_pickle("expected_results/policy_agg_4.pkl") param_sweep_df_rows = len(param_sweep_df.index) policy_agg_df_rows = len(policy_agg_df.index) expected_rows = param_sweep_df_rows + param_sweep_df_rows + policy_agg_df_rows expected_rows_from_api = model_A_rows + model_B_rows + model_C_rows result_rows = len(results_df.index) return MultiModelRowCountResults(expected_rows, expected_rows_from_api, result_rows, param_sweep_df_rows, policy_agg_df_rows, sys_model_A_id, sys_model_B_id, sys_model_C_id, model_A_rows, model_B_rows, model_C_rows) def test_row_count(multi_model_row_count: MultiModelRowCountResults): equal_row_count = multi_model_row_count.expected_rows == multi_model_row_count.expected_rows_from_api == multi_model_row_count.result_rows assertEqual(equal_row_count, True, "Row Count Mismatch between Expected and Multi-Model simulation results") def test_row_count_from_api(multi_model_row_count: MultiModelRowCountResults): assertEqual(multi_model_row_count.expected_rows == multi_model_row_count.expected_rows_from_api, True, "API not producing Expected simulation results") def test_row_count_from_results(multi_model_row_count: MultiModelRowCountResults): assertEqual(multi_model_row_count.expected_rows == multi_model_row_count.result_rows, True, "Engine not producing Expected simulation results") def test_row_count_from_sys_model_A(multi_model_row_count: MultiModelRowCountResults): assertEqual(multi_model_row_count.model_A_rows == multi_model_row_count.param_sweep_df_rows, True, f"{multi_model_row_count.sys_model_A_id}: Row Count Mismatch with Expected results") def test_row_count_from_sys_model_B(multi_model_row_count: MultiModelRowCountResults): assertEqual(multi_model_row_count.model_B_rows == multi_model_row_count.param_sweep_df_rows, True, f"{multi_model_row_count.sys_model_B_id}: Row Count Mismatch with Expected results") def test_row_count_from_sys_model_C(multi_model_row_count: MultiModelRowCountResults): assertEqual(multi_model_row_count.model_C_rows == multi_model_row_count.policy_agg_df_rows, True, f"{multi_model_row_count.sys_model_C_id}: Row Count Mismatch with Expected results") def test_a_b_row_count(multi_model_row_count: MultiModelRowCountResults): file_path = f'{os.getcwd()}/testing/tests/a_b_tests/0_4_23_record_count.json' record_count_0_4_23 = json.load(open(file_path))['record_count'] record_count_current = multi_model_row_count.result_rows assertEqual(record_count_current > record_count_0_4_23, True, "Invalid Row Count for current version") ================================================ FILE: testing/tests/test_param_sweep.py ================================================ from testing.models import param_sweep from cadCAD.engine import ExecutionMode, ExecutionContext, Executor import pandas as pd # type: ignore from testing.results_comparison import dataframe_difference, compare_results_pytest import pytest @pytest.fixture def ParamSweep(): exec_mode = ExecutionMode() exec_ctx = ExecutionContext(context=exec_mode.local_mode) run = Executor(exec_context=exec_ctx, configs=param_sweep.exp.configs) raw_result, _, _ = run.execute() result_df = pd.DataFrame(raw_result) expected_df = pd.read_pickle("expected_results/param_sweep_4.pkl") result_diff = dataframe_difference(result_df, expected_df) return result_diff def test_pytest_compare_results(ParamSweep): compare_results_pytest(ParamSweep) ================================================ FILE: testing/tests/test_policy_aggregation.py ================================================ import pandas as pd # type: ignore from testing.models import policy_aggregation as policy_agg from testing.results_comparison import dataframe_difference from cadCAD.engine import ExecutionMode, ExecutionContext, Executor from testing.results_comparison import dataframe_difference, compare_results_pytest import pytest @pytest.fixture def PolicyAggregation(): exec_mode = ExecutionMode() exec_ctx = ExecutionContext(context=exec_mode.local_mode) run = Executor(exec_context=exec_ctx, configs=policy_agg.exp.configs) raw_result, _, _ = run.execute() result_df = pd.DataFrame(raw_result) expected_df = pd.read_pickle("expected_results/policy_agg_4.pkl") result_diff = dataframe_difference(result_df, expected_df) return result_diff def test_pytest_compare_results(PolicyAggregation): compare_results_pytest(PolicyAggregation) ================================================ FILE: testing/tests/test_run1psub0.py ================================================ import pandas as pd # type: ignore from testing.results_comparison import dataframe_difference, compare_results_pytest import pytest @pytest.fixture def Run1Psub0(): expected_df = pd.read_pickle("expected_results/param_sweep_psub0_4.pkl") param_sweep_df = pd.read_pickle("expected_results/param_sweep_4.pkl") result_df = param_sweep_df[ (param_sweep_df.index > 0) & (param_sweep_df['subset'] < 1) & (param_sweep_df['run'] == 1) ] result_diff = dataframe_difference(result_df, expected_df) return result_diff def test_pytest_compare_results(Run1Psub0): compare_results_pytest(Run1Psub0) ================================================ FILE: testing/tests/test_runs_not_zero.py ================================================ from cadCAD.configuration.utils import config_sim from testing.utils import assertEqual def test_runs_not_zero(): val_error_indicator = False try: sim_config = config_sim( { "N": 0, "T": range(5) } ) except ValueError: val_error_indicator = True assertEqual(val_error_indicator, True, "ValueError raised when runs (N) < 1") ================================================ FILE: testing/tests/test_timestep1psub0.py ================================================ import pandas as pd from testing.results_comparison import dataframe_difference, compare_results_pytest import pytest @pytest.fixture def Timestep1Psub0(): expected_df = pd.read_pickle("expected_results/param_sweep_timestep1_4.pkl") param_sweep_df = pd.read_pickle("expected_results/param_sweep_4.pkl") result_df = param_sweep_df[ (param_sweep_df.index > 0) & (param_sweep_df['subset'] < 1) & (param_sweep_df['timestep'] < 2) & (param_sweep_df['run'] == 1) ] return dataframe_difference(result_df, expected_df) def test_timestep1psub0(Timestep1Psub0): compare_results_pytest(Timestep1Psub0) ================================================ FILE: testing/tools/test_tools.py ================================================ from cadCAD.tools.execution import easy_run # def test_empty_easy_run(): # state_variables = { # } # # params = { # } # # psubs = [ # { # 'policies': {}, # 'variables': {}, # }, # ] # # N_timesteps = 2 # # N_samples = 1 # # results = easy_run( # state_variables, # params, # psubs, # N_timesteps, # N_samples, # ) # print(results) def test_easy_run(): state_variables = { 'a':0.5, } params = { 'c':[1, 2], 'd':[1, 2], } def p(params, substep, state_history, previous_state): a_delta = 1 - params['c'] * previous_state['a'] return {'a_delta': a_delta} def s(params, substep, state_history, previous_state, policy_input): return 'a', previous_state['a'] + policy_input['a_delta'] psubs = [ { 'policies': {'p': p}, 'variables': {'a': s}, }, ] N_timesteps = 2 N_samples = 1 results = easy_run( state_variables, params, psubs, N_timesteps, N_samples, ) ================================================ FILE: testing/utils.py ================================================ # # def record_generator(row, cols): # return {col: row[col] for col in cols} def gen_metric_row(row, cols): return ((row['run'], row['timestep'], row['substep']), {col: row[col] for col in cols}) # def gen_metric_row(row): # return ((row['run'], row['timestep'], row['substep']), {'s1': row['s1'], 'policies': row['policies']}) # def gen_metric_row(row): # return { # 'run': row['run'], # 'timestep': row['timestep'], # 'substep': row['substep'], # 's1': row['s1'], # 'policies': row['policies'] # } def gen_metric_dict(df, cols): return dict([gen_metric_row(row, cols) for index, row in df.iterrows()]) def assertEqual(_1, _2, _3=None): if _3 == None: assert _1 == _2 else: assert _1 == _2, _3