Simulating a Process
Overview
In order to understand the distribution of the amount of time a typical process may take, it is often useful
to simulate the process several times and average the results.
For the purposes of this page, a process
is a series of steps, each that takes an amount of time. Each step may have dependencies on other steps, and
the amount of time taken to complete a step can be random.
The simplified api method we will use assumes that a tasks can start as soon as all the tasks that it depends on are complete.
If no depdencies are specified, the process length will be the length of the longest task.
simulations
Building a Process Tree
In the following code, we begin to set up a process tree for a
project. Here we populate a dictionary named tasks with a set of
task objects, each with a start time and a length.
Notice that the second task sets its start date as the start date of
the first task plus its length (which should be the end date of the task)
let tasks = {};
tasks['set up database'] = {
start: 0,
length: 10
};
tasks['populate database'] = {
start: tasks['set up database'].start + tasks['set up database'].length,
length: 20
};
Once we have this information, we can then easily compute various stats
from the data structure. For instance, we can calculate the end date
of the project as well as total number hours worked.
let end = Math.max(...Object.keys(tasks).map(p => tasks[p].start + tasks[p].length));
let total = $list(Object.keys(tasks).map(p => tasks[p].length)).sum();
Setting the Distribution Functions
tasks['set up database'] = {
start: 0,
length: 10*Math.random()
};
Typically you will want to provide a function has some randomness and has an average and standard deviation that matches
what you expect for the given step. For example, you could choose a Guassian (normal or bell curve) distribution with the
appropriate mean and standard deviation. There are some downsides to using the normal, i.e., the normal distribution can
go negative. This means you could generate steps with a negative amount of time. This may not be much of problem, as it may
be unllikely, and as you will average the statistics over a largen number of samples, this ill defined samples may not influence
the result that much. However, you could choose a better suited distribution, such as the
lognormal distribution.
let ln = await import('/lib/statistics/distributions/lognormal/v1.0.0/lognormal.js');
tasks['set up database'] = {
start: 0,
length: ln.generate(1,1)
};
Other distributions can be found:
distribution.
Running Simulations
let simulate = function(){
let tasks = {};
tasks['set up database'] = {
start: 0,
length: 10
};
tasks['populate database'] = {
start: tasks['set up database'].start + tasks['set up database'].length,
length: 20
};
let end = Math.max(...Object.keys(tasks).map(p => tasks[p].start + tasks[p].length));
return end
}
let sims = [];
for(let i=0;i<100;i++){
sims.push(simulate());
}
Try it!