# `simulation` - Simulation and modeling for Node and the browser
`simulation` is a multi-method simulation package for Node or the browser. Use it to create models for the environment, business, or other areas. For example, it can be used to create models of disease spread, population growth, or the adoption of a product in the marketplace.
`simulation` support differential equation models (also called System Dynamics models) in addition to Agent Based Models, or any mixture of the two techniques.
In addition to building models directly with the package, `simulation` also supports importing and running models built with [Insight Maker](https://insightmaker.com).
## Installing the package
### Installation with NPM
Node installation:
```shell
npm install --save simulation
```
The rest of this README will assume you are using `simulation` in Node with ES6 module syntax.
In the README, we will also be using the optional `simulation-viz-console` package to visualize results in a console. It may be installed with:
```shell
npm install --save simulation-viz-console
```
### Directly importing the modules
You can also import `simulation` ES6 modules directly from the source code without using NPM:
```javascript
import { Model } from "simulation/src/api/Model.js";
```
The code will work without transpilation in modern browsers.
## Example usage
### Our first simulation model
Let's create a simulation model of the world population over the next 100 years. Start by importing the `simulation` and `simulation-viz-console` packages.
```javascript
import { Model } from "simulation";
import { table, plot } from "simulation-viz-console";
```
**Tip: If you get the error `SyntaxError: Cannot use import statement outside a module` when running this in Node, add `"type": "module"` to your `package.json` or change your file extension from `.js` to `.mjs`. See [here](https://nodejs.org/api/esm.html#enabling) for more information.**
Next, we initialize a model:
```javascript
let m = new Model({
timeStart: 2020,
timeLength: 100,
timeUnits: "Years"
});
```
**Tip: Use VSCode or another editor that supports JSDoc type annotations. `simulation` makes extensive use of type annotations to indicate available options. Add `// @ts-check` to the top of a JavaScript file in VSCode to enable automatic type checking of the code, this will help catch errors.**
This creates a model that will simulate 100 years starting at the year 2020.
`simulation` models are composed out of building blocks called "primitives" In this model we're going to use three primitives:
* A **Stock** to store the number of people in the world population. Generally, stocks store things like people, dollars, water, or anything else
* A **Flow** to define the change in the population stock. Flows model the movement of material between stocks.
* A **Variable** to define the net growth rate for the population. In this model, that will be a constant value, but it could also be a dynamic equation.
```javascript
// Start with 7 billion people in the "people" stock
let people = m.Stock({
name: "People",
initial: 7e9
});
// Use a net growth rate of 2% a year
let growthRate = m.Variable({
name: "Growth Rate",
value: 0.02
});
// The population growth each year is the number of people times the growth rate
// Please note that we refer to the value of other primitives in the model with the
// [name] syntax.
let netGrowth = m.Flow(null, people, {
rate: "[People] * [Growth Rate]"
});
// For the netGrowth flow to be able to reference the growthRate, we need to link the primitives
m.Link(growthRate, netGrowth);
```
We've set up our model, now take a look at the results:
```javascript
let results = m.simulate();
table(results, people);
plot(results, people);
```
Which outputs:
```
╔══════════════╤════════════════╗
║ Time [years] │ People ║
╟──────────────┼────────────────╢
║ 2020 │ 7000000000.00 ║
║ 2021 │ 7140000000.00 ║
║ 2022 │ 7282800000.00 ║
...
║ 2118 │ 48743293759.87 ║
║ 2119 │ 49718159635.07 ║
║ 2120 │ 50712522827.77 ║
╚══════════════╧════════════════╝
```
![Population Growth Image](docs/images/pop_growth.png)
### Modeling the spread of a disease
Let's now look at a more complex model: disease spread. One simple way to model the spread of a disease is to assume there are three categories of people:
* **Susceptible** people who are healthy and can be infected,
* **Infected** people who are sick and spreading the disease,
* and, **Recovered** people who were infected but are now better. We'll also assume recovered people and are now immune to the disease.
We'll use three stocks to represent these categories, and we'll use flows to move people between them.
```javascript
let m = new Model();
// Start with 1,000 healthy, susceptible people
let s = m.Stock({
name: "Susceptible",
initial: 1000
});
// One infected person
let i = m.Stock({
name: "Infected",
initial: 1
});
// And no recovered people
let r = m.Stock({
name: "Recovered",
initial: 0
});
// The number of people becoming sick is the product of the
// healthy and sick people times a constant.
m.Flow(s, i, {
name: "Infection",
rate: "[Susceptible] * [Infected] * 0.0003"
});
// People recover at a fixed rate
m.Flow(i, r, {
name: "Recovery",
rate: "[Infected] * 0.015"
});
```
Let's take a look at the results for this model. We can see there is an initial spike in infections that declines as people move to the *Recovered*, immune state.
```javascript
plot(m.simulate(), [s, i, r]);
```
![Disease Dynamics Image](docs/images/sir_disease.png)
### Modeling disease with agents
The models we have looked at so far are System Dynamics differential equation models. They assume average changes across a continuous population. In reality though, when looking at the spread of disease you have many distinct individuals and interactions.
The `simulation` package supports Agent Based Modeling for cases where you want to simulate events at the level of an individual rather than in aggregate.
For this model, we're going to use a couple new types of primitives:
* **Agent** We'll use an Agent primitive to define what a "person" is in our model. When the model runs, a separate agent will be created for each person, and it will contain all the properties for that person.
* **Population** A population represents a collection of agents with a given Agent definition. We'll have a population of 20 people in this example.
* **State** A State represents a boolean condition. For example sick/not-sick, employed/not-employed, etc. We'll use these to represent whether our agents are healthy or sick.
* **Transition** A Transition moves agents between states. For example, you could have a model with "Employed" and "Unemployed" states. When a person is hired, they are transitioned from the unemployed to the employed states. We'll use a transition to move agents between health states.
```javascript
let m = new Model();
// Define the person agent for our model
let person = m.Agent({
name: "Person"
});
// Add a healthy state to the person agent, our agents
// will all start healthy.
//
// Note we use `person.State` rather than `m.State` to add the state
// to the agent definition, not to the model in general.
let healthyState = person.State({
name: "Healthy",
startActive: true
});
// Add an infected state to our person agent. For each agent
// it will start with the opposite value of that agent's healthy
// state.
let infectedState = person.State({
name: "Infected",
startActive: "not [Healthy]"
});
// Since the Infected state uses the Healthy state in its equation,
// we need to explicitly link them
person.Link(he
用于运行模拟的节点和浏览器包。___下载.zip
版权申诉
129 浏览量
2023-04-16
20:09:33
上传
评论
收藏 352KB ZIP 举报
快撑死的鱼
- 粉丝: 1w+
- 资源: 9154
最新资源
- 写入三菱plcD位寄存器的值
- 确保你的操作系统符合Docker的要求 Docker支持的操作系统包括Ubuntu、Debian、CentOS、Fedora和m
- 确保你的操作系统符合Docker的要求 Docker支持的操作系统包括Ubuntu、Debian、CentOS、Fedora和m
- HDMI 虚拟软件欺骗器
- 确保你的操作系统符合Docker的要求 Docker支持的操作系统包括Ubuntu、Debian、CentOS、Fedora和m
- 读取三菱PLC D位寄存器
- HDMI edid 编辑工具
- 要在你的计算机上安装Docker,你可以按照以下步骤进行:
- 要在你的计算机上安装Docker,你可以按照以下步骤进行:
- html加JavaScript进行表单验证
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈