Add your description here
Project description
kansim
Monte Carlo simulations as code. Free, open, and AI-ready.
Why simulation software should be free and open
Simulation models inform some of the most consequential decisions in engineering, finance, environment, and public health. Yet the tools used to build them are often expensive, proprietary, and locked behind GUIs that make models opaque and hard to reproduce.
This creates a problem: a model you cannot read is a model you cannot trust.
When simulation is code:
- It is auditable. Anyone can read, review, and challenge the assumptions.
- It is reproducible. Run the same model anywhere, any time, and get the same results.
- It can be version-controlled. Every change is tracked. You can see who changed what and why.
- It is composable. Models can import each other, share logic, and be tested like software.
- It is free. No license fees. No vendor lock-in. No expiry dates.
Science and engineering move faster when knowledge is shared. Simulation tooling should be no different.
Why code beats a GUI
GUI simulation tools are approachable but they impose a ceiling. As models grow in complexity, the visual interface becomes the bottleneck: hard to navigate, impossible to diff, and painful to automate.
Code has no such ceiling.
from kansim import Simulation, Normal, Triangular, LogNormal, Boolean
class StartupRunway(Simulation):
def __init__(self):
self.monthly_burn = Normal(mean=45_000, std=8_000)
self.monthly_revenue = LogNormal(mean=20_000, std=12_000)
self.raised_bridge = Boolean(p=0.3)
self.bridge_amount = Normal(mean=150_000, std=50_000) if self.raised_bridge else 0
net_burn = self.monthly_burn - self.monthly_revenue
self.runway_months = (500_000 + self.bridge_amount) / net_burn if net_burn > 0 else 999
self.default_risk = self.runway_months < 12
result = StartupRunway.run(n=10_000, seed=42)
print(result.df.describe())
result.plot_tornado(target="runway_months")
This is the entire model. It fits in a code review. It runs in CI. It can be parameterized, tested, and shipped as a package.
Installation
pip install kansim
Or
uv add kansim
Or clone and run examples directly with uv:
git clone https://github.com/kansim/kansim
cd kansim
uv run examples/startup_runway.py
How it works
Subclass Simulation. Assign inputs using distribution functions and compute outputs — all inside __init__. Call .run(n=) to get a SimulationResult.
from kansim import Simulation, Triangular, Normal
class BridgeFatigue(Simulation):
def __init__(self):
self.daily_load = Normal(mean=500, std=80) # tonnes
self.material_life = Triangular(min=40, most_likely=60, max=90) # years
self.cycles = self.daily_load * 365
self.failure_risk = self.cycles > self.material_life * 150_000
result = BridgeFatigue.run(n=10_000, seed=42)
result.plot_histogram("material_life")
result.plot_tornado(target="failure_risk")
All results write to results/<timestamp>/. Pass save="file.png" to any plot to save instead of show.
result.result_id # "2024-03-10_143022"
result.df # pandas DataFrame — filter and pass back to any plot
result.save_csv()
result.save_parquet()
result.plot_histogram("col", save="hist.png")
result.plot_cdf("col")
result.plot_scatter("x", "y")
result.plot_tornado(target="col")
# filtered plots
passing = result.df[result.df.failure_risk == False]
result.plot_histogram("material_life", df=passing, save="safe_only.png")
Distributions
| Function | Parameters |
|---|---|
Normal |
mean, std, min=None, max=None |
LogNormal |
mean, std, min=None, max=None |
Uniform |
min, max, log=False |
Triangular |
min, most_likely, max |
BetaPERT |
min, most_likely, max |
Beta |
successes, failures → 0–1 range |
GeneralizedBeta |
mean, std, min, max |
Exponential |
mean |
Gamma |
mean, std, min=None, max=None |
Weibull |
scale, shape, min=0, max=None |
Pareto |
shape, mode, max=None |
Poisson |
expected |
Binomial |
n, p |
NegativeBinomial |
successes, p |
StudentT |
df |
PearsonIII |
location, scale, shape |
ExtremeValue |
location, scale |
Discrete |
values=[], probs=[] |
Cumulative |
values=[], probs=[] |
SampledResults |
values=[] |
Boolean |
p |
Using AI to generate simulations
kansim is designed to be written by humans or AI agents. The model structure is simple enough that a language model can draft a complete, runnable simulation from a plain English description.
Instructions for an AI agent
Paste the following into your system prompt or alongside your request:
Use the kansim framework by subclassing
Simulationand assigning all variables in__init__. Inputs use distribution functions, outputs are computed from them. Everything assigned toselfbecomes a DataFrame column.from kansim import Simulation, Normal, Triangular, Beta class MyModel(Simulation): def __init__(self): self.input_a = Normal(mean=100, std=10) self.input_b = Triangular(min=1, most_likely=2, max=5) self.output_x = self.input_a * self.input_b result = MyModel.run(n=10_000, seed=42)
run()returns aSimulationResultwith:
result.result_id— human readable timestamp e.g."2024-03-10_143022"result.df— pandas DataFrame of all runsresult.save_csv(),result.save_parquet()— saves toresults/<result_id>/result.plot_histogram(col, df=None, save=None)result.plot_cdf(col, df=None, save=None)result.plot_scatter(x, y, df=None, save=None)result.plot_tornado(target, df=None, save=None)All plots accept an optional
dfargument for filtered/modified DataFrames. All saves write toresults/<result_id>/— passsave="filename.png"to save instead of show.Available distributions:
Normal(mean, std, min=None, max=None),LogNormal(mean, std, min=None, max=None),Uniform(min, max, log=False),Triangular(min, most_likely, max),BetaPERT(min, most_likely, max),Beta(successes, failures),GeneralizedBeta(mean, std, min, max),Exponential(mean),Gamma(mean, std, min=None, max=None),Weibull(scale, shape, min=0, max=None),Pareto(shape, mode, max=None),Poisson(expected),Binomial(n, p),NegativeBinomial(successes, p),StudentT(df),PearsonIII(location, scale, shape),ExtremeValue(location, scale),Discrete(values=[], probs=[]),Cumulative(values=[], probs=[]),SampledResults(values=[]),Boolean(p).
Example prompt
Using kansim, simulate the cost overrun risk for a construction project. Inputs should include labor cost, material cost, and weather delay days. Output should include total cost and whether the project exceeds budget.
The AI will return a complete, runnable Python file.
Examples
| File | Description |
|---|---|
examples/startup_runway.py |
Startup cash runway under uncertain growth and events |
examples/poker_hand_equity.py |
Heads-up poker equity over 10,000 deals |
examples/water_treatment_plant.py |
Water treatment plant throughput and cost |
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file kansim-0.1.0.tar.gz.
File metadata
- Download URL: kansim-0.1.0.tar.gz
- Upload date:
- Size: 20.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.17 {"installer":{"name":"uv","version":"0.9.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d05e52bd3ee81ef936f6bf033edd9b645d83d0cf9e2920938b022df72177e511
|
|
| MD5 |
5d2d640768334c3a6d1f6b7617680fb2
|
|
| BLAKE2b-256 |
a4f4d6aeceb4b224c84c38f6452f96494d98893f638c0ee3803b0e2a6c123360
|
File details
Details for the file kansim-0.1.0-py3-none-any.whl.
File metadata
- Download URL: kansim-0.1.0-py3-none-any.whl
- Upload date:
- Size: 7.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.17 {"installer":{"name":"uv","version":"0.9.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"13","id":"trixie","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3e476c312acd5e214187da00587c556cb1f1f3b7b3a27c1d2460084f17c7b63e
|
|
| MD5 |
0eeb0b75b56ab1a6a1687852800aacf7
|
|
| BLAKE2b-256 |
4e924d1aea9a3718adccb67be2b2b8c96e9cfc8abdb16fe0427b3d3bdaf0ae60
|