Probabilistic Project Planning with Monte Carlo Simulation
Why Planaco? • Features • Installation • Quick Start • Monte Carlo • CLI • Distributions • Contributing
Estimating the time it takes to complete a task or project is hard. Traditional approaches use fixed estimates, but this ignores any uncertainty and life often gets in the way.
Planaco helps you make better estimates by modeling tasks as random processes, accounting for uncertainty and task dependencies through Monte Carlo simulation.
Status: Planaco is in alpha (v0.3.0). The public API may still change between releases.
- Probabilistic Task Modeling - Define tasks with min/max/mode duration ranges
- 6 Distribution Types - Triangular, PERT, Uniform, Normal, LogNormal, and Beta distributions
- Task Dependencies - Support for parallel and sequential task execution
- Monte Carlo Simulation - Run thousands of simulations to estimate project completion
- Statistical Analysis - Get percentiles, confidence intervals, and key metrics
- Visualization - Generate histogram and cumulative distribution plots
- Export Results - Save results to JSON or CSV for further analysis
pip install planacoOr install from source:
git clone https://github.com/sepam/planaco.git
cd planaco
pip install .Instead of saying "this task takes 5 days", Planaco lets you model uncertainty:
from planaco import Task
task = Task(
name='Develop Feature',
min_duration=3,
mode_duration=5, # most likely estimate
max_duration=9,
estimator='triangular'
)Create complex project workflows with parallel and sequential task execution:
from planaco import Task, Project
# Create a project
project = Project(name='Web App Development', unit='days')
# Define tasks
design_ui = Task(name='Design UI', min_duration=2, mode_duration=3, max_duration=5, estimator='triangular')
develop_frontend = Task(name='Develop Frontend', min_duration=5, mode_duration=7, max_duration=10, estimator='triangular')
develop_backend = Task(name='Develop Backend', min_duration=4, mode_duration=6, max_duration=9, estimator='triangular')
testing = Task(name='Testing', min_duration=2, mode_duration=3, max_duration=5, estimator='triangular')
deploy = Task(name='Deploy', min_duration=1, max_duration=2, estimator='uniform')
# Add tasks with dependencies
project.add_task(design_ui)
project.add_task(develop_frontend, depends_on=[design_ui]) # Sequential: frontend needs UI design
project.add_task(develop_backend) # Parallel: backend runs independently
project.add_task(testing, depends_on=[develop_frontend, develop_backend]) # Waits for both tracks
project.add_task(deploy, depends_on=[testing])Planaco uses Monte Carlo simulation to estimate project completion time. By running thousands of simulations, it leverages the Central Limit Theorem to provide probabilistic estimates for the completion of tasks and projects.
# Get comprehensive statistics of the simulation
stats = project.statistics(n=10000)
print(f"Median completion time: {stats['median']:.1f} days")
print(f"90% confidence: {stats['percentiles']['p90']:.1f} days")
print(f"95% confidence: {stats['percentiles']['p95']:.1f} days")statistics() returns a dictionary with the full distribution summary:
{
'n_simulations': 10000,
'unit': 'days',
'mean': 18.4,
'median': 18.1,
'std_dev': 2.7,
'min': 11.2,
'max': 29.8,
'percentiles': {'p50': 18.1, 'p75': 20.1, 'p85': 21.3, 'p90': 22.1, 'p95': 23.4, 'p99': 25.6},
'confidence_intervals': {'95%': (13.5, 24.2)},
}# Generate histogram
project.plot(n=10000, hist=True)Read the likelihood of completing your project by a given date:
# Generate cumulative distribution
project.plot(n=10000, hist=False)The cumulative distribution shows the probability of completing the project within a given timeframe, accounting for both parallel and sequential task execution.
# Export to JSON
project.export_results(n=10000, format='json', output='results.json')
# Export to CSV
project.export_results(n=10000, format='csv', output='results.csv')Planaco supports six probability distributions, each suited for different estimation scenarios:
Best for three-point estimates where you can identify optimistic, most likely, and pessimistic values.
task = Task(
name="Development",
min_duration=5, # Best case
mode_duration=8, # Most likely
max_duration=15, # Worst case
estimator="triangular"
)When to use: Most common choice. Use when you have a clear "most likely" estimate and can define reasonable bounds.
A smoother alternative to triangular that weights the mode more heavily (by default, 4x). Widely used in project management.
task = Task(
name="Testing",
min_duration=2,
mode_duration=4,
max_duration=10,
estimator="pert"
)When to use: Industry standard for project estimation. Produces more realistic results than triangular by reducing the influence of extreme values.
All values between min and max are equally likely. No mode required.
task = Task(
name="Deployment",
min_duration=1,
max_duration=3,
estimator="uniform"
)When to use: When you genuinely don't know the most likely duration, only the range. Good for tasks with high uncertainty.
Classic bell curve centered on the mean. Best for well-understood, repeatable tasks.
from planaco import Task, NormalDistribution
task = Task(
name="Code Review",
distribution=NormalDistribution(
mean=2.0,
std_dev=0.5,
min_value=0.5, # Optional lower bound
max_value=4.0 # Optional upper bound
)
)When to use: Tasks you've done many times before with predictable variability. The optional bounds prevent unrealistic negative or extreme values.
Right-skewed distribution where delays are more likely than early completion. Realistic for many real-world tasks.
from planaco import Task, LogNormalDistribution
task = Task(
name="Integration",
distribution=LogNormalDistribution(
mean=5.0,
std_dev=2.0
)
)When to use: Tasks with potential for unexpected delays (debugging, third-party dependencies, approvals). Models the common pattern where things take longer than expected more often than they finish early.
Most flexible distribution with customizable shape via alpha and beta parameters.
from planaco import Task, BetaDistribution
task = Task(
name="Research",
distribution=BetaDistribution(
alpha=2.0,
beta=5.0,
min_value=1.0,
max_value=10.0
)
)When to use: When you need fine-grained control over the distribution shape:
alpha < beta: Right-skewed (more likely to finish early)alpha > beta: Left-skewed (more likely to finish late)alpha = beta: Symmetric
| Scenario | Recommended Distribution |
|---|---|
| Standard 3-point estimate | PERT or Triangular |
| Well-understood, repeatable task | Normal |
| High uncertainty, unknown mode | Uniform |
| Risk of delays/blockers | LogNormal |
| Custom uncertainty profile | Beta |
New to Monte Carlo? Start with PERT - it's the industry standard and works well for most project estimation tasks.
Planaco also ships with a planaco CLI that runs simulations from a YAML project file — useful for CI pipelines, shared team configs, and version-controlled estimates.
planaco init project.yaml # Create a template config
planaco stats project.yaml -n 10000 # Print formatted statistics
planaco run project.yaml -o results.json # Export results (json or csv)
planaco plot project.yaml -o chart.png # Histogram or cumulative plot
planaco graph project.yaml # Visualize the task dependency graphCharts render as crisp, on-brand SVG (or PNG) — see the brand & style guide.
Example YAML config:
project:
name: Website Redesign
unit: days
seed: 42 # optional, for reproducible runs
tasks:
design:
name: Design
estimator: pert
min_duration: 5
mode_duration: 7
max_duration: 14
development:
name: Development
estimator: triangular
min_duration: 10
mode_duration: 15
max_duration: 25
depends_on: [design]Run planaco --help or planaco <command> --help to see all available options, including --seed for reproducible results and -p/--percentile markers for plots.
A complete, runnable example lives in example/example_project.py, with an annotated walkthrough in example/example.ipynb.
python example/example_project.pyContributions are welcome! To set up a development environment:
git clone https://github.com/sepam/planaco.git
cd planaco
pip install -e ".[dev]"Run the checks before submitting a PR:
pytest # run the test suite
ruff check . # lint
black . # format
mypy src # type-checkPlease open an issue to discuss larger changes before starting work.
This project is licensed under the MIT License - see the LICENSE.md file for details.




