Skip to main content

Worst case analysis and sensitivity studies using Extreme Value and/or Monte Carlo methods.

Project description

worstcase

Overview

pip install worstcase

Worst case analysis and sensitivity studies using Extreme Value and/or Monte Carlo methods.

This package coexists alongside far more capable uncertainty analysis and error propagation packages such as uncertainties (first-order propagation), soerp (second-order propagation), and mcerp (Monte Carlo propagation).

This package is designed for engineering applications where worst case analysis computations are often done using the Extreme Value method over single-valued functions while falling back to the Monte Carlo method when the worst case is known to not exist at the extremes. The Extreme Value method is implemented as a brute-force search; the Monte Carlo method is implemented with Latin Hypercube Sampling over a uniform distribution.

This package does not transparently handle parameter covariance across functions. Instead, the graph of parameter dependence must be a tree (and therefore acyclic). Constructing a worst case analysis requires explicit definition of what the underlying parameter dependencies are.

Usage

import worstcase as wca
import numpy as np

wca.config.n = 2000  # Number of Monte Carlo runs. (default: 5000)
wca.config.sigfig = 4  # Number of significant firues to print. (default: 3)

The primitive varying parameter is a Param. Params are constructed either by tolerance (absolute or relative) or by range. Params may be given units from the default unit registry of Pint (default is unitless). A tag for printing is also optional (default is an empty string). A Param has the fields nom (nominal value), lb (lower bound), and ub (upper bound).

spd_initial = wca.param.bytol(nom=2, tol=0.1, rel=True, unit=wca.unit("m/s"), tag="v0")
accel = wca.param.byrange(nom=0.2, lb=0.1, ub=0.5, unit=wca.unit("m/s**2"), tag="a")
distance = wca.param.byrange(nom=1, lb=0.8, ub=1.1, unit=wca.unit.km, tag="x")

print([spd_initial, accel, distance])
[v0: 2 m/s (nom), 1.8 m/s (lb), 2.2 m/s (ub),
 a: 200 mm/s² (nom), 100 mm/s² (lb), 500 mm/s² (ub),
 x: 1 km (nom), 800 m (lb), 1.1 km (ub)]

A more complex parameter is built up as a ParamBuilder. ParamBuilders are constructed by decorating single-valued functions by ev (Extreme Value) or mc (Monte Carlo). The arguments passed to the ParamBuilder are partially bound to the underlying function. A parameter dependency tree can be drawn using the assigned tags; ParamBuilder will assume a tag corresponding to the function name as a default.

@wca.param.ev(spd_initial, accel, distance)
def spd_final(v, a, x):
    return np.sqrt(v ** 2 + 2 * a * x)


print(spd_final)
spd_final (ev)
├── a
├── v0
└── x

ParamBuilder is a callable and the returned value depends on the arguments supplied. If no arguments are supplied, the parameter is built and a Param is returned.

print(spd_final())
spd_final: 20.1 m/s (nom), 12.78 m/s (lb), 33.24 m/s (ub)

Alternatively, the ParamBuilder binding to the underlying function can be updated and a new ParamBuilder is returned.

spd_final_noaccel = spd_final(a=0 * wca.unit("m/s**2"), tag="spd_noaccel")
print(spd_final_noaccel)
spd_noaccel (ev)
├── v0
└── x

Finally, if the ParamBuilder binding is updated such that no arguments are varying parameters then the underlying function will be called to return a single value.

result = spd_final_noaccel(3 * wca.unit("m/s"), x=10 * wca.unit.m)
print(result)
3.0 meter / second

ParamBuilders can be used to construct other ParamBuilders.

spd_rel = wca.param.bytol(nom=20, tol=1, rel=False, unit=wca.unit("mi/hr"), tag="vrel")


@wca.param.mc(spd_final, spd_rel)
def spd_total(vf, vr):
    return vf + vr


print(spd_total)
print(spd_total())
spd_total (mc)
├── spd_final (ev)
│   ├── a
│   ├── v0
│   └── x
└── vrel

spd_total: 29.04 m/s (nom), 21.36 m/s (lb), 42.52 m/s (ub)

ParamBuilders can be modified with the ss method to perform a sensitivity study. By supplying a Param or ParamBuilder (or a list of them), a new ParamBuilder is returned where all other varying parameters are set to their nominal value. A few examples below.

accel_sens = spd_total.ss(accel, tag="accel-sens")
print(accel_sens)
print(accel_sens())
accel-sens (mc)
└── spd_final (ev)
    └── a

accel-sens: 29.04 m/s (nom), 23.23 m/s (lb), 40.62 m/s (ub)
accel_distance_sens = spd_total.ss([accel, distance], tag="accel/distance-sens")
print(accel_distance_sens)
print(accel_distance_sens())
accel/distance-sens (mc)
└── spd_final (ev)
    ├── a
    └── x

accel/distance-sens: 29.04 m/s (nom), 21.75 m/s (lb), 42.16 m/s (ub)
finalspd_sens = spd_total.ss(spd_final, tag="finalspd-sens")
print(finalspd_sens)
print(finalspd_sens())
finalspd-sens (mc)
└── spd_final (ev)
    ├── a
    ├── v0
    └── x

finalspd-sens: 29.04 m/s (nom), 21.73 m/s (lb), 42.18 m/s (ub)
relspd_sens = spd_total.ss(spd_rel, tag="relspd-sens")
print(relspd_sens)
print(relspd_sens())

relspd-sens (mc)
└── vrel

relspd-sens: 29.04 m/s (nom), 28.59 m/s (lb), 29.49 m/s (ub)

Params implement a few of the Pint Quantity methods for usability.

assert spd_total.check("[length]/[time]")
# also try: spd_total.dimensionality

print(spd_total.units)  # meter / second
# also try: spd_total.u

print(spd_total().ito(wca.unit("km/hr")))  # spd_total: 104.5 km/hr (nom)...
# also try: spd_total().ito_base_units()
#           spd_total().ito_reduced_units()
#           spd_total().ito_root_units()

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

worstcase-0.2.2.tar.gz (7.3 kB view details)

Uploaded Source

Built Distribution

worstcase-0.2.2-py3-none-any.whl (6.5 kB view details)

Uploaded Python 3

File details

Details for the file worstcase-0.2.2.tar.gz.

File metadata

  • Download URL: worstcase-0.2.2.tar.gz
  • Upload date:
  • Size: 7.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.1.6 CPython/3.9.4 Windows/10

File hashes

Hashes for worstcase-0.2.2.tar.gz
Algorithm Hash digest
SHA256 cd8a5460ba0e5b795660eccc22cbfa75969bfa6098ecb96f18b0b9e90ab526a3
MD5 55f72ec835b9c66d2bb51d4c5620cb6f
BLAKE2b-256 c1a058a2b6a971f84b6612d7c833a295e9217e73a80598afcb886b0885824a0b

See more details on using hashes here.

File details

Details for the file worstcase-0.2.2-py3-none-any.whl.

File metadata

  • Download URL: worstcase-0.2.2-py3-none-any.whl
  • Upload date:
  • Size: 6.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.1.6 CPython/3.9.4 Windows/10

File hashes

Hashes for worstcase-0.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 3a3c3560a2e6ba058c06e57d92a9c4b5f8a1d486df051de409408c52c90c460a
MD5 1bb95f0d44565095ed0f41a06bb66d6e
BLAKE2b-256 80f492fc1fdfce08a4e260b044564b9db332a6f5cb9e0c6cfa2be5d17ed5ab97

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page