Skip to content
Industrial Engineering and Supply Chain

industrial-engineering-ai999x

Inventory policies (EOQ, reorder point, safety stock, newsvendor), statistical process control, reliability, queueing, scheduling, forecasting accuracy, line balancing, learning curves and facility location.

94capabilities
11topics
94formulas typeset
4ways to run: desktop app, command line, browser, Python
1.0.0version
What it does

What Industrial Engineering and Supply Chain does

Industrial Engineering and Supply Chain (industrial-engineering-ai999x) is an offline Python package for industrial engineering and supply chain. It covers inventory policies (EOQ, reorder point, safety stock, newsvendor), statistical process control, reliability, queueing, scheduling, forecasting accuracy, line balancing, learning curves and facility location.

It has 94 capabilities — 94 computational procedures — in 11 topics, the largest being Inventory, Statistical process control, Reliability, Forecasting, Queueing and Scheduling. Ask a question in words with ask(), or call a capability by name with typed inputs with solve(). Every answer carries its value and unit, the steps that produced it and the formula in LaTeX.

When a question is not determined — a value is missing, an input is out of range, or the request is outside the package — it says so and names what it needs, instead of guessing. It runs on an ordinary CPU without a network connection (Python >=3.10), and the same question always gets the same answer.

What it covers

Get it

Use Industrial Engineering and Supply Chain your way

The AI999X desktop app and the command-line program industrial-engineering run on Windows and Linux; together with the browser they run the same compiled program on your own device: offline, with no Python and nothing sent anywhere. The Python package gives the same capabilities in your own code. Or compute in your browser, with nothing to install.

Desktop app

Desktop app for Industrial Engineering and Supply Chain: this model in its own app, with search, ask in words, input forms, live figures and explanations. Version 1.2.0.

All models in one app · every AI999X model, this one included

Install guide · Quick start · All models: quick start

Command line

Every model's program in one download, for terminals and scripts. This model's program is industrial-engineering.

Linux commands · Windows commands · Usage

Python

The Python package, for notebooks and your own programs (Python 3.10 or newer).

pip install industrial-engineering-ai999x

Examples · Python guide

Version 1.2.0 · SHA-256 checksums · Latest downloads · Desktop & command-line guide: downloads, installing, asking and searching, figures, offline use, versions and checksums

From download to first answer

Every command can be copied.

Windows

Download ai999x-industrial-engineering-1.2.0-windows-x86_64.zip, right-click it → Extract All, then open the folder and start ai999x-industrial-engineering.exe. If Windows SmartScreen asks, choose More info → Run anyway.

Linux
curl -LO https://www.ai999x.com/downloads/desktop/1.2.0/ai999x-industrial-engineering-1.2.0-linux-x86_64.tar.gz
curl -LO https://www.ai999x.com/downloads/desktop/1.2.0/SHA256SUMS
sha256sum -c --ignore-missing SHA256SUMS
tar xzf ai999x-industrial-engineering-1.2.0-linux-x86_64.tar.gz
./ai999x-industrial-engineering-1.2.0-linux-x86_64/ai999x-industrial-engineering
Then
  1. Start the app: it opens on Industrial Engineering and Supply Chain.
  2. Type a question in words, or search for a capability and fill in its form.
  3. Press Compute: the answer, its explanation and live figures appear; change an input and they follow.
In your browser

Compute something now

Ask a question in words, or choose a capability and open its calculator: the inputs come filled in with a worked example; change any of them (any unit of the right kind) and press Compute. It runs on your device; nothing is sent anywhere.

The same capabilities as the desktop app and the command line, as WebAssembly in this page. Every capability below also has its own Compute in your browser button.

Worked examples

One example, every way to run it

Each worked example with its answer, then the same question on the command line, from Python and in your browser. A command-line output is exactly what the program printed for that command.

Inventory

Economic order quantity with annual demand = 1200, ordering cost = 100, holding cost = 6.

Q^* = \sqrt{\frac{2DS}{H}},\quad TC^* = \sqrt{2DSH}
Q = 200
orders_per_year = 6
cycle_time = 0.1666666667
ordering_cost = 600
holding_cost_per_year = 600
total_cost = 1200
How it was worked out
  1. Economic order quantity (EOQ)
    Q^* = \sqrt{\frac{2DS}{H}},\quad TC^* = \sqrt{2DSH}
    with demand = 1200, order_cost = 100, holding_cost = 6
    → Q = 200, orders_per_year = 6, cycle_time = 0.1666666667, ordering_cost = 600, holding_cost_per_year = 600, total_cost = 1200
Terminal
$ industrial-engineering solve ie_eoq demand=1200 order_cost=100 holding_cost=6
Q = 200
orders_per_year = 6
cycle_time = 0.1666666667
ordering_cost = 600
holding_cost_per_year = 600
total_cost = 1200
  by: Economic order quantity (EOQ)  (Q* = sqrt(2 D S / H); TC = D S / Q + H Q / 2 = sqrt(2 D S H))
  demand = 1200
  order_cost = 100
  holding_cost = 6
  assumes: demand > 0; order_cost > 0; holding_cost > 0 (per unit per year)
Queueing

M/M/c queue with arrival rate = 10, service rate = 4, servers = 3.

C(c,a) = \frac{\frac{a^c}{c!(1-\rho)}}{\sum_{k=0}^{c-1}\frac{a^k}{k!} + \frac{a^c}{c!(1-\rho)}},\quad L_q = C\frac{\rho}{1-\rho}
utilization = 0.8333333333
p_wait = 0.702247191
Lq = 3.511235955
Wq = 0.3511235955
W = 0.6011235955
L = 6.011235955
How it was worked out
  1. M/M/c queue (Erlang C)
    C(c,a) = \frac{\frac{a^c}{c!(1-\rho)}}{\sum_{k=0}^{c-1}\frac{a^k}{k!} + \frac{a^c}{c!(1-\rho)}},\quad L_q = C\frac{\rho}{1-\rho}
    with arrival_rate = 10, service_rate = 4, servers = 3
    → utilization = 0.8333333333, p_wait = 0.702247191, Lq = 3.511235955, Wq = 0.3511235955, W = 0.6011235955, L = 6.011235955, p0 = 0.04494382022
Terminal
$ industrial-engineering solve ie_mmc_queue arrival_rate=10 service_rate=4 servers=3
utilization = 0.8333333333
p_wait = 0.702247191
Lq = 3.511235955
Wq = 0.3511235955
W = 0.6011235955
L = 6.011235955
p0 = 0.04494382022
  by: M/M/c queue (Erlang C)  (a = lambda/mu, P0 = [sum_{k<c} a^k/k! + a^c/(c!(1-rho))]^-1, C = a^c P0/(c!(1-rho)), Lq = C rho/(1-rho))
  arrival_rate = 10
  service_rate = 4
  assumes: arrival_rate < servers x service_rate; 1 <= servers <= 500
Statistical process control

X-bar and R chart limits with grand mean = 50, average range = 2, subgroup size = 5.

UCL_{\bar x} = \bar{\bar x} + A_2\bar R,\quad UCL_R = D_4\bar R,\quad LCL_R = D_3\bar R
xbar_ucl = 51.154
xbar_lcl = 48.846
center = 50
r_ucl = 4.228
r_lcl = 0
A2 = 0.577
How it was worked out
  1. X-bar and R chart control limits
    UCL_{\bar x} = \bar{\bar x} + A_2\bar R,\quad UCL_R = D_4\bar R,\quad LCL_R = D_3\bar R
    with grand_mean = 50, mean_range = 2, subgroup_size = 5
    → xbar_ucl = 51.154, xbar_lcl = 48.846, center = 50, r_ucl = 4.228, r_lcl = 0, A2 = 0.577, D3 = 0, D4 = 2.114
Terminal
$ industrial-engineering solve ie_xbar_r_limits grand_mean=50 mean_range=2 subgroup_size=5
xbar_ucl = 51.154
xbar_lcl = 48.846
center = 50
r_ucl = 4.228
r_lcl = 0
A2 = 0.577
D3 = 0
D4 = 2.114
  by: X-bar and R chart control limits  (UCL/LCL = x-double-bar +/- A2 R-bar; R chart D3 R-bar, D4 R-bar)
  grand_mean = 50
  mean_range = 2
  assumes: mean_range > 0; subgroup size 2 to 10; standard 3-decimal constants
Inventory

Newsvendor order quantity with selling price = 10, unit cost = 6, mean demand = 500, sd demand = 100, salvage value = 2.

F(Q^*) = \frac{C_u}{C_u + C_o},\quad Q^* = \mu + z\sigma
Q = 500
critical_ratio = 0.5
z = 0
expected_sales = 460.105772
expected_leftover = 39.89422804
expected_shortage = 39.89422804
How it was worked out
  1. Newsvendor order quantity (normal demand)
    F(Q^*) = \frac{C_u}{C_u + C_o},\quad Q^* = \mu + z\sigma
    with price = 10, cost = 6, mean_demand = 500, sd_demand = 100, salvage = 2
    → Q = 500, critical_ratio = 0.5, z = 0, expected_sales = 460.105772, expected_leftover = 39.89422804, expected_shortage = 39.89422804, expected_profit = 1680.846176
Terminal
$ industrial-engineering solve ie_newsvendor_normal price=10 cost=6 mean_demand=500 sd_demand=100 salvage=2
Q = 500
critical_ratio = 0.5
z = 0
expected_sales = 460.105772
expected_leftover = 39.89422804
expected_shortage = 39.89422804
expected_profit = 1680.846176
  by: Newsvendor order quantity (normal demand)  (Cu = p - c, Co = c - v, CR = Cu/(Cu+Co), Q = mu + Phi^-1(CR) sigma; E[sales] = mu - sigma L(z))
  price = 10
  cost = 6
  mean_demand = 500
  sd_demand = 100
  salvage = 2
  assumes: salvage < cost < price; sd_demand > 0; demand normal
Scheduling

Johnson's rule (two machines)

\min(a_{1i}, a_{2j}) \le \min(a_{1j}, a_{2i}) \Rightarrow i \text{ before } j
sequence = [3, 2, 4, 5, 1]
makespan = 23
idle_time_machine2 = 5
How it was worked out
  1. Johnson's rule (two machines)
    \min(a_{1i}, a_{2j}) \le \min(a_{1j}, a_{2i}) \Rightarrow i \text{ before } j
    with machine1_times = [5, 2, 1, 7, 6], machine2_times = [2, 6, 2, 5, 3]
    → sequence = [3, 2, 4, 5, 1], makespan = 23, idle_time_machine2 = 5
Terminal
$ industrial-engineering solve ie_johnson_two_machine "machine1_times=[5, 2, 1, 7, 6]" "machine2_times=[2, 6, 2, 5, 3]"
sequence = [3,2,4,5,1]
makespan = 23
idle_time_machine2 = 5
  by: Johnson's rule (two machines)  (Johnson: front set (a1 <= a2) by a1 ascending, back set by a2 descending)
  assumes: times >= 0; jobs with a1 <= a2 go first by increasing a1, the others last by decreasing a2; ties by the lower job number
Break-even analysis

Break-even point with fixed costs = 10000, selling price = 25, variable cost per unit = 15.

Q_{BE} = \frac{F}{p – v},\quad R_{BE} = p\,Q_{BE}
break_even_units = 1000
break_even_revenue = 25000
contribution_margin = 10
contribution_margin_ratio = 0.4
How it was worked out
  1. Break-even point
    Q_{BE} = \frac{F}{p – v},\quad R_{BE} = p\,Q_{BE}
    with fixed_cost = 10000, price = 25, variable_cost = 15
    → break_even_units = 1000, break_even_revenue = 25000, contribution_margin = 10, contribution_margin_ratio = 0.4
Terminal
$ industrial-engineering solve ie_break_even fixed_cost=10000 price=25 variable_cost=15
break_even_units = 1000
break_even_revenue = 25000
contribution_margin = 10
contribution_margin_ratio = 0.4
  by: Break-even point  (Q_BE = F / (p - v))
  fixed_cost = 10000
  price = 25
  variable_cost = 15
  assumes: fixed_cost >= 0; price > variable_cost >= 0
Facility location

Centre-of-gravity location with x coordinates = [30, 90, 130, 60], y coordinates = [120, 110, 130, 40], loads = [2000, 1000, 1000, 2000].

x^* = \frac{\sum w_i x_i}{\sum w_i},\quad y^* = \frac{\sum w_i y_i}{\sum w_i}
x = 66.66666667
y = 93.33333333
total_weight = 6000
How it was worked out
  1. Centre-of-gravity location
    x^* = \frac{\sum w_i x_i}{\sum w_i},\quad y^* = \frac{\sum w_i y_i}{\sum w_i}
    with x = [30, 90, 130, 60], y = [120, 110, 130, 40], weights = [2000, 1000, 1000, 2000]
    → x = 66.66666667, y = 93.33333333, total_weight = 6000
Terminal
$ industrial-engineering solve ie_center_of_gravity "x=[30, 90, 130, 60]" "y=[120, 110, 130, 40]" "weights=[2000, 1000, 1000, 2000]"
x = 66.66666667
y = 93.33333333
total_weight = 6000
  by: Centre-of-gravity location  (x* = sum w_i x_i / sum w_i, y* = sum w_i y_i / sum w_i)
  assumes: equal lengths; weights >= 0, not all 0
Forecasting

Exponential smoothing forecast with demand = [142, 153, 136, 150], smoothing constant = 0.2, first forecast = 140.

F_{t+1} = F_t + \alpha\,(A_t – F_t)
forecast = 143.2288
forecasts = [140, 140.4, 142.92, 141.536, 143.2288]
How it was worked out
  1. Simple exponential smoothing forecast
    F_{t+1} = F_t + \alpha\,(A_t – F_t)
    with data = [142, 153, 136, 150], alpha = 0.2, initial_forecast = 140
    → forecast = 143.2288, forecasts = [140, 140.4, 142.92, 141.536, 143.2288]
Terminal
$ industrial-engineering solve ie_exponential_smoothing "data=[142, 153, 136, 150]" alpha=0.2 initial_forecast=140
forecast = 143.2288
forecasts = [140.0,140.4,142.92,141.536,143.2288]
  by: Simple exponential smoothing forecast  (F_1 given (or A_1); F_(t+1) = alpha A_t + (1 - alpha) F_t)
  alpha = 0.2
  initial_forecast = 140
  assumes: 0 < alpha <= 1
Command line

Use it from the command line

Every command below was run as shown, and the text under it is exactly what industrial-engineering printed. The same commands work in a Linux terminal and in Windows PowerShell. Install it in a minute. The user guide covers install, inputs, outcomes, scripting, and every capability with a command and what it printed: PDF · text.

1

Check the install

Prints the model, its version and that this is the Rust build.

Terminal
$ industrial-engineering --version
industrial-engineering-ai999x 1.0.0 (Rust build, ax-engine 0.1.0)
2

Find a capability

Search the capabilities by what you want to know; the first column is the id to pass to info and solve.

Terminal
$ industrial-engineering search "economic order quantity (eoq)"
ie_eoq                               Economic order quantity (EOQ)  (inventory / EOQ)
ie_epq                               Economic production quantity (EPQ)  (inventory / EOQ)
ie_eoq_quantity_discount             EOQ with all-units quantity discounts  (inventory / EOQ)
ie_inventory_total_cost              Annual inventory cost of an order quantity  (inventory / EOQ)
ie_eoq_backorders                    EOQ with planned backorders  (inventory / EOQ)
ie_newsvendor_normal                 Newsvendor order quantity (normal demand)  (inventory / newsvendor)
ie_newsvendor_poisson                Newsvendor order quantity (Poisson demand)  (inventory / newsvendor)
ie_newsvendor_uniform                Newsvendor order quantity (uniform demand)  (inventory / newsvendor)
… 12 more
3

List the capabilities

Every capability the program answers: its id (what you pass to solve) and its name.

Terminal
$ industrial-engineering list
ie_abc_classification                    ABC inventory classification
ie_acceptance_sampling                   Single sampling plan: OC, AOQ and ATI
ie_arl_shewhart                          Average run length of a Shewhart X-bar chart
ie_availability                          Inherent availability from MTBF and MTTR
ie_break_even                            Break-even point
ie_c_chart_limits                        c chart control limits
ie_capacity_utilization                  Capacity utilisation and efficiency
ie_center_of_gravity                     Centre-of-gravity location
… 86 more
4

What a capability needs

The equation or method, every input and output with its SI unit. Read this before solve: it tells you the input names.

Terminal
$ industrial-engineering info ie_eoq
Economic order quantity (EOQ)
  Q* = sqrt(2 D S / H); TC = D S / Q + H Q / 2 = sqrt(2 D S H)
  in   demand   demand per year (units) []
  in   order_cost fixed cost per order or setup []
  in   holding_cost holding cost per unit per year []
  out  Q        economic order quantity Q* []
  out  orders_per_year orders per year D/Q* []
  out  cycle_time time between orders Q*/D (years) []
  out  ordering_cost annual ordering cost DS/Q* []
  out  holding_cost_per_year annual holding cost HQ*/2 []
  out  total_cost annual ordering plus holding cost []
5

Solve

Inputs as name=value, each with any unit of the right kind. The answer lists every output, the method used, each input converted to SI, and the conditions the answer assumes.

Terminal
$ industrial-engineering solve ie_eoq demand=1200.0 order_cost=100.0 holding_cost=6.0
Q = 200
orders_per_year = 6
cycle_time = 0.1666666667
ordering_cost = 600
holding_cost_per_year = 600
total_cost = 1200
  by: Economic order quantity (EOQ)  (Q* = sqrt(2 D S / H); TC = D S / Q + H Q / 2 = sqrt(2 D S H))
  demand = 1200
  order_cost = 100
  holding_cost = 6
  assumes: demand > 0; order_cost > 0; holding_cost > 0 (per unit per year)
6

Machine-readable answer

–json prints the same answer as one line of JSON (values in SI): for scripts and other programs.

Terminal
$ industrial-engineering solve ie_eoq demand=1200.0 order_cost=100.0 holding_cost=6.0 --json
{"outcome":"SOLVED","message":"","value":200.0,"unit":"","solved_for":"Q","si":[["demand",1200.0],["order_cost",100.0],["holding_cost",6.0]],"values":[["Q",200.0,""],["orders_per_year",6.0,""],["cycle_time",0.166666666667,""],["ordering_cost",600.0,""],["holding_cost_per_year",600.0,""],["total_cost",1200.0,""]],"target":"Q","phrase":"economic order quantity Q*","assumptions":["demand > 0","order_cost > 0","holding_cost > 0 (per unit per year)"],"name":"Economic order quantity (EOQ)","equation":"Q* = sqrt(2 D S / H); TC = D S / Q + H Q / 2 = sqrt(2 D S H)"}
7

When an input is missing

No number is guessed: the answer names what is missing, shows a complete call, and the program exits with status 1.

Terminal
$ industrial-engineering solve ie_eoq demand=1200.0 order_cost=100.0
NEEDS_INPUT: ie_eoq needs holding_cost (holding cost per unit per year). Example: solve('ie_eoq', demand=1200, order_cost=100, holding_cost=6).
8

Many questions at once

One JSON request per line in, one JSON answer per line out, in order: for scripts, notebooks and agents (the program starts once). In PowerShell: Get-Content cases.jsonl | industrial-engineering batch

Terminal
cases.jsonl
{"key": "ie_eoq", "inputs": {"demand": 1200.0, "order_cost": 100.0, "holding_cost": 6.0}}
{"key": "ie_mmc_queue", "inputs": {"arrival_rate": 10.0, "service_rate": 4.0, "servers": "3"}}
$ industrial-engineering batch < cases.jsonl
{"outcome":"SOLVED","message":"","value":200.0,"unit":"","solved_for":"Q","si":[["demand",1200.0],["order_cost",100.0],["holding_cost",6.0]],"values":[["Q",200.0,""],["orders_per_year",6.0,""],["cycle_time",0.166666666667,""],["ordering_cost",600.0,""],["holding_cost_per_year",600.0,""],["total_cost",1200.0,""]],"target":"Q","phrase":"economic order quantity Q*","assumptions":["demand > 0","order_cost > 0","holding_cost > 0 (per unit per year)"],"name":"Economic order quantity (EOQ)","equation":"Q* = sqrt(2 D S / H); TC = D S / Q + H Q / 2 = sqrt(2 D S H)"}
{"outcome":"SOLVED","message":"","value":3.51123595506,"unit":"","solved_for":"Lq","si":[["arrival_rate",10.0],["service_rate",4.0]],"values":[["utilization",0.833333333333,""],["p_wait",0.702247191011,""],["Lq",3.51123595506,""],["Wq",0.351123595506,""],["W",0.601123595506,""],["L",6.01123595506,""],["p0",0.0449438202247,""]],"target":"Lq","phrase":"rho = lambda/(c mu)","assumptions":["arrival_rate < servers x service_rate","1 <= servers <= 500"],"name":"M/M/c queue (Erlang C)","equation":"a = lambda/mu, P0 = [sum_{k<c} a^k/k! + a^c/(c!(1-rho))]^-1, C = a^c P0/(c!(1-rho)), Lq = C rho/(1-rho)"}

All commands

CommandWhat it does
industrial-engineering search "<words>"find the capabilities that match
industrial-engineering listevery capability: its id and name
industrial-engineering info <capability>the equation or method, its inputs and outputs with their units
industrial-engineering solve <capability> name=value …the answer; add –target X to solve an equation for X, –json for JSON
industrial-engineering figures <capability> name=value … --out DIRthe live figures for those inputs, as SVG files in DIR
industrial-engineering batch < requests.jsonlone JSON answer per line, for scripts and agents
industrial-engineering catalogevery capability with its inputs, as JSON
industrial-engineering --versionthe model and its version

Exit status: 0 when the question was answered, 1 when it was not (the message says why: a missing input, an invalid value, a question outside the model), 2 for a command it does not know.

Python

Use it from Python

After pip install industrial-engineering-ai999x, ask in words or call a capability. Every snippet was run as shown; the output under it is what it printed. The Python guide covers ask in words, solve, and every capability with a Python example: PDF · text.

import industrial_engineering_ai999x as m

a = m.ask("Economic order quantity with annual demand = 1200, ordering cost = 100, holding cost = 6.")
print(a.outcome)
print(a.values)
for step in a.steps:
    print(step["name"])
Output
SOLVED
{'Q': 200.0, 'orders_per_year': 6.0, 'cycle_time': 0.166666666667, 'ordering_cost': 600.0, 'holding_cost_per_year': 600.0, 'total_cost': 1200.0}
Economic order quantity (EOQ)
Capabilities

Every capability, explained

Search by name, formula, input or topic. Each capability opens to say what it does, what it needs, what it gives back and why, with its worked example, how to run it (on the command line, from Python, in your browser) and its figures.

94 capabilities

Break-even analysis 2

Break-even point1 fig.ie_break_even

Volume (and revenue) at which revenue equals fixed plus variable cost, and the volume for a target profit.

Q_{BE} = \frac{F}{p – v},\quad R_{BE} = p\,Q_{BE}

You give

MeaningUnitExample
\text{fixed\_cost}
Fixed cost per period—10000
\text{price}
Selling price per unit—25
\text{variable\_cost}
Variable cost per unit—15
\text{target\_profit}
Target profit (optional) optional—

You get

MeaningUnitExample
\text{break\_even\_units}
F / (p – v)—1000
\text{break\_even\_revenue}
p F / (p – v)—25000
\text{contribution\_margin}
p – v—10
\text{contribution\_margin\_ratio}
(p – v)/p—0.4
\text{units\_for\_target\_profit}
(F + target)/(p – v)—

An optional input can be left out: a stated default is used.

Applies when

  • fixed_cost >= 0
  • price > variable_cost >= 0

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Break-even point with fixed costs = 10000, selling price = 25, variable cost per unit = 15.
break_even_units = 1000
break_even_revenue = 25000
contribution_margin = 10
contribution_margin_ratio = 0.4

Run it

Terminal
$ industrial-engineering solve ie_break_even fixed_cost=10000 price=25 variable_cost=15
break_even_units = 1000
break_even_revenue = 25000
contribution_margin = 10
contribution_margin_ratio = 0.4
  by: Break-even point  (Q_BE = F / (p - v))
  fixed_cost = 10000
  price = 25
  variable_cost = 15
  assumes: fixed_cost >= 0; price > variable_cost >= 0

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Multiproduct break-even (sales-mix weighted)2 fig.ie_multiproduct_break_even

Break-even revenue of several products sold in a fixed revenue mix: F / sum (1 – v_i/p_i) w_i.

BEP_{\$} = \frac{F}{\sum_i\left(1 – \frac{V_i}{P_i}\right)W_i}

You give

MeaningUnitExample
\text{fixed\_cost}
Fixed cost per period—3000
\text{prices}
Selling price of each product vector—[2.95, 1.25, 0.8]
\text{variable\_costs}
Variable cost per unit of each product vector—[1.25, 0.3, 0.2]
\text{sales\_mix}
Share of revenue of each product (sum 1) vector—[0.5, 0.3, 0.2]

You get

MeaningUnitExample
\text{break\_even\_revenue}
F / sum (1 – v_i/p_i) w_i—4503.587604
\text{weighted\_contribution\_ratio}
sum (1 – v_i/p_i) w_i—0.6661355932
\text{revenue\_by\_product}
Break-even revenue of each product—[2251.793802, 1351.076281, 900.7175207]
\text{units\_by\_product}
Break-even units of each product—[763.3199328, 1080.861025, 1125.896901]

Applies when

  • fixed_cost >= 0
  • prices > 0
  • mix fractions of revenue adding to 1

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Multiproduct break-even with fixed costs = 3000, selling prices = [2.95, 1.25, 0.8], variable cost per unit = [1.25, 0.3, 0.2], revenue mix = [0.5, 0.3, 0.2].
break_even_revenue = 4503.587604
weighted_contribution_ratio = 0.6661355932
revenue_by_product = [2251.793802, 1351.076281, 900.7175207]
units_by_product = [763.3199328, 1080.861025, 1125.896901]

Run it

Terminal
$ industrial-engineering solve ie_multiproduct_break_even fixed_cost=3000 "prices=[2.95, 1.25, 0.8]" "variable_costs=[1.25, 0.3, 0.2]" "sales_mix=[0.5, 0.3, 0.2]"
break_even_revenue = 4503.587604
weighted_contribution_ratio = 0.6661355932
revenue_by_product = [2251.79380184,1351.07628111,900.717520737]
units_by_product = [763.319932828,1080.86102488,1125.89690092]
  by: Multiproduct break-even (sales-mix weighted)  (BEP($) = F / sum [(1 - V_i/P_i) W_i])
  fixed_cost = 3000
  assumes: fixed_cost >= 0; prices > 0; mix fractions of revenue adding to 1

Figures

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Facility location 5

Centre-of-gravity location1 fig.ie_center_of_gravity

Location of a facility at the load-weighted average of the demand points' coordinates.

x^* = \frac{\sum w_i x_i}{\sum w_i},\quad y^* = \frac{\sum w_i y_i}{\sum w_i}

You give

MeaningUnitExample
x
x coordinate of each demand point vector—[30, 90, 130, 60]
y
y coordinate of each demand point vector—[120, 110, 130, 40]
\text{weights}
Load or volume of each point vector—[2000, 1000, 1000, 2000]

You get

MeaningUnitExample
x
sum w x / sum w—66.66666667
y
sum w y / sum w—93.33333333
\text{total\_weight}
Sum of loads—6000

Applies when

  • equal lengths
  • weights >= 0, not all 0

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Centre-of-gravity location with x coordinates = [30, 90, 130, 60], y coordinates = [120, 110, 130, 40], loads = [2000, 1000, 1000, 2000].
x = 66.66666667
y = 93.33333333
total_weight = 6000

Run it

Terminal
$ industrial-engineering solve ie_center_of_gravity "x=[30, 90, 130, 60]" "y=[120, 110, 130, 40]" "weights=[2000, 1000, 1000, 2000]"
x = 66.66666667
y = 93.33333333
total_weight = 6000
  by: Centre-of-gravity location  (x* = sum w_i x_i / sum w_i, y* = sum w_i y_i / sum w_i)
  assumes: equal lengths; weights >= 0, not all 0

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Factor-rating method for site selection1 fig.ie_factor_rating

Weighted score of each candidate site (sum of factor weight x score) and the best site.

S_i = \sum_j w_j\,s_{ij}

You give

MeaningUnitExample
\text{weights}
Weight of each factor vector—[0.25, 0.45, 0.3]
\text{scores}
Matrix: one row per site, one score per factor matrix—[70 60 90; 85 80 60]

You get

MeaningUnitExample
\text{weighted\_scores}
Weighted score of each site—[71.5, 75.25]
\text{best\_site}
Site with the highest score—2
\text{best\_score}
Highest weighted score—75.25

Applies when

  • weights >= 0
  • one score per factor in every row
  • ties go to the lower site number

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Factor rating with factor weights = [0.25, 0.45, 0.3], site scores = [[70, 60, 90], [85, 80, 60]].
weighted_scores = [71.5, 75.25]
best_site = 2
best_score = 75.25

Run it

Terminal
$ industrial-engineering solve ie_factor_rating "weights=[0.25, 0.45, 0.3]" "scores=[[70, 60, 90], [85, 80, 60]]"
weighted_scores = [71.5,75.25]
best_site = 2
best_score = 75.25
  by: Factor-rating method for site selection  (score_i = sum_j w_j s_ij)
  assumes: weights >= 0; one score per factor in every row; ties go to the lower site number

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Locational cost-volume (break-even) analysis2 fig.ie_location_cost_volume

Total annual cost of each candidate site at an expected volume (fixed + variable x volume) and the cheapest site.

TC_i(Q) = F_i + v_i\,Q

You give

MeaningUnitExample
\text{fixed\_costs}
Annual fixed cost of each site vector—[30000, 60000, 110000]
\text{variable\_costs}
Variable cost per unit at each site vector—[75, 45, 25]
\text{volume}
Expected annual volume—2000

You get

MeaningUnitExample
\text{total\_costs}
F_i + v_i Q for each site—[180000, 150000, 160000]
\text{best\_site}
Cheapest site—2
\text{best\_cost}
Its total cost—150000

Applies when

  • costs >= 0
  • volume >= 0
  • ties go to the lower site number

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Locational cost-volume analysis with fixed cost = [30000, 60000, 110000], variable cost = [75, 45, 25], expected volume = 2000.
total_costs = [180000, 150000, 160000]
best_site = 2
best_cost = 150000

Run it

Terminal
$ industrial-engineering solve ie_location_cost_volume "fixed_costs=[30000, 60000, 110000]" "variable_costs=[75, 45, 25]" volume=2000
total_costs = [180000.0,150000.0,160000.0]
best_site = 2
best_cost = 150000
  by: Locational cost-volume (break-even) analysis  (TC_i = F_i + v_i Q; the minimum wins)
  volume = 2000
  assumes: costs >= 0; volume >= 0; ties go to the lower site number

Figures

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Minimum rectilinear-distance location (weighted median)1 fig.ie_rectilinear_location

Location minimising the sum of load x rectilinear (city-block) distance: the weighted median of x and of y.

\min_{x,y}\sum_i w_i\,(|x-x_i| + |y-y_i|)

You give

MeaningUnitExample
x
x coordinate of each demand point vector—[3, 8, 5, 1]
y
y coordinate of each demand point vector—[2, 6, 9, 4]
\text{weights}
Load or volume of each point vector—[5, 2, 3, 1]

You get

MeaningUnitExample
x
Weighted median of x—3
y
Weighted median of y—4
\text{total\_weighted\_distance}
sum w_i (|x – x_i| + |y – y_i|)—47

Applies when

  • weights >= 0, not all 0
  • refused when the optimum is a whole interval (cumulative weight exactly half)

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Rectilinear distance location with x coordinates = [3, 8, 5, 1], y coordinates = [2, 6, 9, 4], loads = [5, 2, 3, 1].
x = 3
y = 4
total_weighted_distance = 47

Run it

Terminal
$ industrial-engineering solve ie_rectilinear_location "x=[3, 8, 5, 1]" "y=[2, 6, 9, 4]" "weights=[5, 2, 3, 1]"
x = 3
y = 4
total_weighted_distance = 47
  by: Minimum rectilinear-distance location (weighted median)  (sort by coordinate; the first point where cumulative weight reaches half the total)
  assumes: weights >= 0, not all 0; refused when the optimum is a whole interval (cumulative weight exactly half)

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Minimum weighted-distance location (Weber problem)1 fig.ie_weber_location

Location that minimises the sum of load x straight-line distance to the demand points (Weiszfeld's algorithm; a demand point when it is optimal).

\min_{x,y}\sum_i w_i\sqrt{(x-x_i)^2+(y-y_i)^2}

You give

MeaningUnitExample
x
x coordinate of each demand point vector—[0, 10, 5, 2]
y
y coordinate of each demand point vector—[0, 0, 8, 6]
\text{weights}
Load or volume of each point vector—[1, 1, 1, 1]

You get

MeaningUnitExample
x
Optimal x—3.191489362
y
Optimal y—5.106382979
\text{total\_weighted\_distance}
sum w_i distance_i at the optimum—19.43398113

Applies when

  • at least 2 distinct points
  • weights >= 0, not all 0
  • Euclidean distance

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Weber problem location with x coordinates = [0, 10, 5, 2], y coordinates = [0, 0, 8, 6], loads = [1, 1, 1, 1].
x = 3.191489362
y = 5.106382979
total_weighted_distance = 19.43398113

Run it

Terminal
$ industrial-engineering solve ie_weber_location "x=[0, 10, 5, 2]" "y=[0, 0, 8, 6]" "weights=[1, 1, 1, 1]"
x = 3.191489362
y = 5.106382979
total_weighted_distance = 19.43398113
  by: Minimum weighted-distance location (Weber problem)  (Weiszfeld: x <- sum (w_i x_i / d_i) / sum (w_i / d_i) until it settles; a demand point i is optimal when |sum_{j != i} w_j (p_i - p_j)/d_ij| <= w_i)
  assumes: at least 2 distinct points; weights >= 0, not all 0; Euclidean distance

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Forecasting 9

Associative forecast by simple linear regression1 fig.ie_regression_forecast

Least-squares line y = a + b x of demand on a driver, its correlation and standard error of estimate, and the forecast at a new x.

\hat y = a + bx,\quad S_{y,x} = \sqrt{\frac{\sum (y-\hat y)^2}{n-2}}

You give

MeaningUnitExample
x
Values of the driver (independent variable) vector—[1, 3, 4, 2, 1, 7]
y
Values of demand (dependent variable) vector—[2, 3, 2.5, 2, 2, 3.5]
x_{\mathrm{new}}
Driver value to forecast at (optional) optional—6

You get

MeaningUnitExample
\text{intercept}
a—1.75
\text{slope}
b—0.25
r
Correlation coefficient—0.9013878189
r_{\mathrm{squared}}
Coefficient of determination—0.8125
\text{standard\_error}
Standard error of the estimate sqrt(SSE/(n – 2))—0.3061862178
\text{forecast}
a + b x_new—3.25

An optional input can be left out: a stated default is used.

Applies when

  • at least 3 pairs
  • x and y vary

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Regression forecast with driver = [1, 3, 4, 2, 1, 7], dependent variable = [2, 3, 2.5, 2, 2, 3.5], new x = 6.
intercept = 1.75
slope = 0.25
r = 0.9013878189
r_squared = 0.8125
standard_error = 0.3061862178
forecast = 3.25

Run it

Terminal
$ industrial-engineering solve ie_regression_forecast "x=[1, 3, 4, 2, 1, 7]" "y=[2, 3, 2.5, 2, 2, 3.5]" x_new=6
intercept = 1.75
slope = 0.25
r = 0.9013878189
r_squared = 0.8125
standard_error = 0.3061862178
forecast = 3.25
  by: Associative forecast by simple linear regression  (ordinary least squares; S_yx = sqrt(sum (y - y_hat)^2 / (n - 2)))
  x_new = 6
  assumes: at least 3 pairs; x and y vary

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Forecast accuracy: MAD, MSE, RMSE, MAPE, bias, tracking signal1 fig.ie_forecast_errors

Standard accuracy measures of a forecast against actual values (error = actual – forecast).

MAD = \frac{\sum|e_t|}{n},\ MSE = \frac{\sum e_t^2}{n},\ MAPE = \frac{100}{n}\sum\left|\frac{e_t}{A_t}\right|,\ TS = \frac{\sum e_t}{MAD}

You give

MeaningUnitExample
\text{actual}
Actual values vector—[100, 110, 120, 130]
\text{forecast}
Forecast values (same periods) vector—[105, 108, 125, 126]

You get

MeaningUnitExample
\text{mad}
Mean absolute deviation—4
\text{mse}
Mean squared error—17.5
\text{rmse}
Root mean squared error—4.183300133
\text{mape}
Mean absolute percentage error, in percent (when no actual is 0)—3.51544289
\text{bias}
Mean error (positive: forecasts too low)—-1
\text{running\_sum\_of\_errors}
Sum of errors—-4
\text{tracking\_signal}
Running sum of errors / MAD—-1

Applies when

  • equal lengths
  • error = actual – forecast
  • MAPE only if no actual value is 0

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Forecast accuracy with actual = [100, 110, 120, 130], forecasts = [105, 108, 125, 126].
mad = 4
mse = 17.5
rmse = 4.183300133
bias = -1
running_sum_of_errors = -4
mape = 3.51544289

Run it

Terminal
$ industrial-engineering solve ie_forecast_errors "actual=[100, 110, 120, 130]" "forecast=[105, 108, 125, 126]"
mad = 4
mse = 17.5
rmse = 4.183300133
bias = -1
running_sum_of_errors = -4
mape = 3.51544289
tracking_signal = -1
  by: Forecast accuracy: MAD, MSE, RMSE, MAPE, bias, tracking signal  (e_t = A_t - F_t; MAD = mean |e|; MSE = mean e^2; MAPE = 100 mean |e/A|; TS = sum e / MAD)
  assumes: equal lengths; error = actual - forecast; MAPE only if no actual value is 0

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Holt's linear trend (double exponential smoothing)1 fig.ie_holt_trend

Trend-adjusted exponential smoothing: level and trend updated each period; the forecast h periods ahead is level + h x trend.

L_t = \alpha A_t + (1-\alpha)(L_{t-1}+T_{t-1}),\quad T_t = \beta(L_t – L_{t-1}) + (1-\beta)T_{t-1}

You give

MeaningUnitExample
\text{data}
Observations in time order (oldest first) vector—[12, 17, 20, 19, 24, 27]
\alpha
Level smoothing constant—0.2
\beta
Trend smoothing constant—0.4
\text{initial\_level}
Level before the first observation—11
\text{initial\_trend}
Trend before the first observation—2
\text{horizon}
Periods ahead (default 1) optional—

You get

MeaningUnitExample
\text{forecast}
Level + horizon x trend—27.85924608
\text{level}
Final level—25.31331578
\text{trend}
Final trend—2.545930297

An optional input can be left out: a stated default is used.

Applies when

  • 0 < alpha, beta <= 1
  • 1 <= horizon <= 1000

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Holt's linear trend forecast with demand = [12, 17, 20, 19, 24, 27], level smoothing = 0.2, trend smoothing = 0.4, starting level = 11, starting trend = 2.
forecast = 27.85924608
level = 25.31331578
trend = 2.545930297

Run it

Terminal
$ industrial-engineering solve ie_holt_trend "data=[12, 17, 20, 19, 24, 27]" alpha=0.2 beta=0.4 initial_level=11 initial_trend=2
forecast = 27.85924608
level = 25.31331578
trend = 2.545930297
  by: Holt's linear trend (double exponential smoothing)  (L_t = alpha A_t + (1 - alpha)(L_(t-1) + T_(t-1)); T_t = beta (L_t - L_(t-1)) + (1 - beta) T_(t-1); F_(t+h) = L_t + h T_t)
  alpha = 0.2
  beta = 0.4
  initial_level = 11
  initial_trend = 2
  assumes: 0 < alpha, beta <= 1; 1 <= horizon <= 1000

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Linear trend projection (least squares)1 fig.ie_linear_trend_forecast

Least-squares trend line y = a + b t through the data at periods t = 1, …, n, projected h periods ahead.

b = \frac{\sum (t-\bar t)(y-\bar y)}{\sum (t-\bar t)^2},\quad a = \bar y – b\bar t

You give

MeaningUnitExample
\text{data}
Observations in time order (oldest first) vector—[74, 79, 80, 90, 105, 142, 122]
\text{horizon}
Periods beyond the last observation (default 1) optional—

You get

MeaningUnitExample
\text{forecast}
a + b (n + h)—141
\text{intercept}
a—56.71428571
\text{slope}
b, change per period—10.53571429

An optional input can be left out: a stated default is used.

Applies when

  • at least 2 observations
  • periods numbered 1, 2, …, n

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Linear trend projection with demand = [74, 79, 80, 90, 105, 142, 122].
forecast = 141
intercept = 56.71428571
slope = 10.53571429

Run it

Terminal
$ industrial-engineering solve ie_linear_trend_forecast "data=[74, 79, 80, 90, 105, 142, 122]"
forecast = 141
intercept = 56.71428571
slope = 10.53571429
  by: Linear trend projection (least squares)  (b = sum (t - t_bar)(y - y_bar) / sum (t - t_bar)^2, a = y_bar - b t_bar)
  assumes: at least 2 observations; periods numbered 1, 2, ..., n

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Moving average forecast2 fig.ie_moving_average_forecast

Next-period forecast as the average of the last n observations (and the forecast each period would have had).

F_{t+1} = \frac{1}{n}\sum_{i=0}^{n-1} A_{t-i}

You give

MeaningUnitExample
\text{data}
Observations in time order (oldest first) vector—[120, 135, 128, 142, 150, 147]
\text{periods}
Number of periods averaged n—3

You get

MeaningUnitExample
\text{forecast}
Forecast for the next period—146.3333333
\text{forecasts}
Moving averages: forecast for periods n+1, …, (last period + 1)—[127.6666667, 135, 140, 146.3333333]

Applies when

  • 1 ≤ periods ≤ number of observations

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Moving average forecast with demand = [120, 135, 128, 142, 150, 147], window = 3.
forecast = 146.3333333
forecasts = [127.6666667, 135, 140, 146.3333333]

Run it

Terminal
$ industrial-engineering solve ie_moving_average_forecast "data=[120, 135, 128, 142, 150, 147]" periods=3
forecast = 146.3333333
forecasts = [127.666666667,135.0,140.0,146.333333333]
  by: Moving average forecast  (F_(t+1) = (A_t + ... + A_(t-n+1)) / n)
  assumes: 1 <= periods <= number of observations

Figures

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Seasonal indices (average method)2 fig.ie_seasonal_index

Seasonal index of each season = average demand in that season / average demand over all seasons; with an expected annual total, the seasonal forecasts.

S_k = \frac{\bar A_k}{\bar A},\quad F_k = \frac{T}{s}\,S_k

You give

MeaningUnitExample
\text{data}
Matrix: one row per year, one column per season (month, quarter) matrix—[80 85 105 110; 70 85 85 120; 80 93 82 98]
\text{next\_year\_total}
Expected total demand next year (optional) optional—1200

You get

MeaningUnitExample
\text{indices}
Seasonal index of each season—[0.8417200366, 0.9624885636, 0.9954254346, 1.200365965]
\text{season\_averages}
Average of each season—[76.66666667, 87.66666667, 90.66666667, 109.3333333]
\text{overall\_average}
Average over all seasons and years—91.08333333
\text{forecasts}
Next-year forecast of each season (annual total / seasons x index)—[252.516011, 288.7465691, 298.6276304, 360.1097896]

An optional input can be left out: a stated default is used.

Applies when

  • rows of equal length (at least 2 seasons)
  • positive average

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Seasonal indices with demand table = [[80, 85, 105, 110], [70, 85, 85, 120], [80, 93, 82, 98]], annual forecast = 1200.
indices = [0.8417200366, 0.9624885636, 0.9954254346, 1.200365965]
season_averages = [76.66666667, 87.66666667, 90.66666667, 109.3333333]
overall_average = 91.08333333
forecasts = [252.516011, 288.7465691, 298.6276304, 360.1097896]

Run it

Terminal
$ industrial-engineering solve ie_seasonal_index "data=[[80, 85, 105, 110], [70, 85, 85, 120], [80, 93, 82, 98]]" next_year_total=1200
indices = [0.841720036597,0.962488563586,0.995425434584,1.20036596523]
season_averages = [76.6666666667,87.6666666667,90.6666666667,109.333333333]
overall_average = 91.08333333
forecasts = [252.516010979,288.746569076,298.627630375,360.10978957]
  by: Seasonal indices (average method)  (index_k = mean of season k / overall mean; forecast_k = (annual total / s) index_k)
  next_year_total = 1200
  assumes: rows of equal length (at least 2 seasons); positive average

Figures

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Simple exponential smoothing forecast3 fig.ie_exponential_smoothing

Exponentially smoothed forecasts F_(t+1) = F_t + alpha (A_t – F_t), starting from a given first forecast (default: the first observation).

F_{t+1} = F_t + \alpha\,(A_t – F_t)

You give

MeaningUnitExample
\text{data}
Observations in time order (oldest first) vector—[142, 153, 136, 150]
\alpha
Smoothing constant (0 < alpha <= 1)—0.2
\text{initial\_forecast}
Forecast for period 1 (default: the first observation) optional—140

You get

MeaningUnitExample
\text{forecast}
Forecast for the next period—143.2288
\text{forecasts}
Forecasts for periods 1, …, n + 1—[140, 140.4, 142.92, 141.536, 143.2288]

An optional input can be left out: a stated default is used.

Applies when

  • 0 < alpha <= 1

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Exponential smoothing forecast with demand = [142, 153, 136, 150], smoothing constant = 0.2, first forecast = 140.
forecast = 143.2288
forecasts = [140, 140.4, 142.92, 141.536, 143.2288]

Run it

Terminal
$ industrial-engineering solve ie_exponential_smoothing "data=[142, 153, 136, 150]" alpha=0.2 initial_forecast=140
forecast = 143.2288
forecasts = [140.0,140.4,142.92,141.536,143.2288]
  by: Simple exponential smoothing forecast  (F_1 given (or A_1); F_(t+1) = alpha A_t + (1 - alpha) F_t)
  alpha = 0.2
  initial_forecast = 140
  assumes: 0 < alpha <= 1

Figures

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Tracking signal over time1 fig.ie_tracking_signal

Tracking signal each period (running sum of errors / running MAD) and the first period it leaves the +/- limit.

TS_t = \frac{\sum_{i\le t} e_i}{MAD_t}

You give

MeaningUnitExample
\text{actual}
Actual values vector—[90, 95, 115, 100, 125, 140]
\text{forecast}
Forecast values (same periods) vector—[100, 100, 100, 110, 110, 110]
\text{limit}
Control limit in MADs (default 4) optional—

You get

MeaningUnitExample
\text{final\_signal}
Tracking signal in the last period—2.470588235
\text{signals}
Tracking signal of each period—[-1, -2, 0, -1, 0.4545454545, 2.470588235]
\text{first\_out\_of\_control}
First period with |TS| > limit (0 = never)—0

An optional input can be left out: a stated default is used.

Applies when

  • equal lengths
  • running MAD uses all periods so far

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Tracking signal with actual = [90, 95, 115, 100, 125, 140], forecasts = [100, 100, 100, 110, 110, 110].
final_signal = 2.470588235
signals = [-1, -2, 0, -1, 0.4545454545, 2.470588235]
first_out_of_control = 0

Run it

Terminal
$ industrial-engineering solve ie_tracking_signal "actual=[90, 95, 115, 100, 125, 140]" "forecast=[100, 100, 100, 110, 110, 110]"
final_signal = 2.470588235
signals = [-1.0,-2.0,0.0,-1.0,0.454545454545,2.47058823529]
first_out_of_control = 0
  by: Tracking signal over time  (TS_t = (sum_{i<=t} e_i) / (sum_{i<=t} |e_i| / t))
  assumes: equal lengths; running MAD uses all periods so far

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Weighted moving average forecast1 fig.ie_weighted_moving_average

Next-period forecast as a weighted average of the most recent observations (weights listed oldest to newest, divided by their sum).

F_{t+1} = \frac{\sum_{i=1}^{k} w_i A_{t-k+i}}{\sum w_i}

You give

MeaningUnitExample
\text{data}
Observations in time order (oldest first) vector—[100, 110, 105, 120]
\text{weights}
Weights for the last k observations, oldest first vector—[1, 2, 3]

You get

MeaningUnitExample
\text{forecast}
sum w_i A_i / sum w_i—113.3333333
\text{weight\_sum}
Sum of the weights—6

Applies when

  • weights >= 0, not all 0
  • at least as many observations as weights
  • the last weight applies to the most recent observation

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Weighted moving average forecast with demand = [100, 110, 105, 120], weights = [1, 2, 3].
forecast = 113.3333333
weight_sum = 6

Run it

Terminal
$ industrial-engineering solve ie_weighted_moving_average "data=[100, 110, 105, 120]" "weights=[1, 2, 3]"
forecast = 113.3333333
weight_sum = 6
  by: Weighted moving average forecast  (F = sum w_i A_i / sum w_i over the last k observations)
  assumes: weights >= 0, not all 0; at least as many observations as weights; the last weight applies to the most recent observation

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Inventory 18

(R, Q) reorder point for a target fill rate1 fig.ie_rq_fill_rate

Reorder point of a continuous-review (R, Q) policy that meets a fill rate (fraction of demand met from stock) with normal lead-time demand.

\sigma_L\,L(z) = (1-\beta)\,Q,\quad R = \mu_L + z\,\sigma_L

You give

MeaningUnitExample
\text{mean\_ltd}
Mean demand during the lead time—500
\text{sd\_ltd}
Standard deviation of lead-time demand—100
\text{order\_quantity}
Order quantity Q—1000
\text{fill\_rate}
Target fill rate (decimal)—0.99

You get

MeaningUnitExample
\text{reorder\_point}
Reorder point R—590.2346348
\text{safety\_stock}
Safety stock R – mu—90.23463475
z
Service factor—0.9023463475
\text{expected\_shortage\_per\_cycle}
Expected units short per cycle (1 – beta) Q—10
\text{cycle\_service\_level}
Probability of no stock-out per cycle—0.8165635438

Applies when

  • sd_ltd, order_quantity > 0
  • 0 < fill_rate < 1
  • lead-time demand normal

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Reorder point for a fill rate with mean lead time demand = 500, standard deviation of lead time demand = 100, lot size = 1000, beta = 0.99.
reorder_point = 590.2346348
safety_stock = 90.23463475
z = 0.9023463475
expected_shortage_per_cycle = 10
cycle_service_level = 0.8165635438

Run it

Terminal
$ industrial-engineering solve ie_rq_fill_rate mean_ltd=500 sd_ltd=100 order_quantity=1000 fill_rate=0.99
reorder_point = 590.2346348
safety_stock = 90.23463475
z = 0.9023463475
expected_shortage_per_cycle = 10
cycle_service_level = 0.8165635438
  by: (R, Q) reorder point for a target fill rate  (solve sigma L(z) = (1 - beta) Q for z (L the standard normal loss function); R = mu + z sigma)
  mean_ltd = 500
  sd_ltd = 100
  order_quantity = 1000
  fill_rate = 0.99
  assumes: sd_ltd, order_quantity > 0; 0 < fill_rate < 1; lead-time demand normal

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

ABC inventory classification1 fig.ie_abc_classification

Classify items by annual usage value: A items make up the first ~80 % of value, B the next ~15 %, C the rest.

\text{class}(k) = A \text{ if } \frac{\sum_{j \prec k} v_j}{\sum v} < 0.8,\ B \text{ if } < 0.95,\ C

You give

MeaningUnitExample
\text{annual\_values}
Annual usage value of each item (annual demand x unit cost) vector—[90000, 15000, 4000, 60000, 2500, 12000, 1500, 800, 30000, 6000]
a_{\mathrm{share}}
Cumulative value share closing class A (default 80%) optional—
b_{\mathrm{share}}
Cumulative value share closing class B (default 95%) optional—

You get

MeaningUnitExample
\text{classes}
Class of each item, in input order—[A, B, C, A, C, B, C, C, A, B]
\text{count\_a}
Number of A items—3
\text{count\_b}
Number of B items—3
\text{count\_c}
Number of C items—4
\text{share\_a}
Share of total value in class A—0.8115419297
\text{share\_b}
Share of total value in class B—0.1487826871

An optional input can be left out: a stated default is used.

Applies when

  • values >= 0, not all 0
  • 0 < a_share < b_share < 1
  • items ranked by value (ties by item number); an item belongs to A while the value ranked above it is below a_share of the total (so the item crossing the threshold is still A), likewise B

Outside these conditions it says what is wrong instead of returning a number.

Worked example

ABC classification with values = [90000, 15000, 4000, 60000, 2500, 12000, 1500, 800, 30000, 6000].
classes = [A, B, C, A, C, B, C, C, A, B]
count_a = 3
count_b = 3
count_c = 4
share_a = 0.8115419297
share_b = 0.1487826871

Run it

Terminal
$ industrial-engineering solve ie_abc_classification "annual_values=[90000, 15000, 4000, 60000, 2500, 12000, 1500, 800, 30000, 6000]"
classes = ["A","B","C","A","C","B","C","C","A","B"]
count_a = 3
count_b = 3
count_c = 4
share_a = 0.8115419297
share_b = 0.1487826871
  by: ABC inventory classification  (rank by value; cumulative share before each item decides its class)
  assumes: values >= 0, not all 0; 0 < a_share < b_share < 1; items ranked by value (ties by item number); an item belongs to A while the value ranked above it is below a_share of the total (so the item crossing the threshold is still A), likewise B

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Annual inventory cost of an order quantity1 fig.ie_inventory_total_cost

Annual ordering, holding and purchase cost of ordering a given quantity Q each time (constant demand).

TC(Q) = \frac{D}{Q}S + \frac{Q}{2}H + Dc

You give

MeaningUnitExample
\text{demand}
Demand per year (units)—1200
\text{order\_cost}
Fixed cost per order or setup—100
\text{holding\_cost}
Holding cost per unit per year—6
\text{order\_quantity}
Quantity ordered each time—300
\text{unit\_cost}
Purchase price per unit (optional, default 0) optional—

You get

MeaningUnitExample
\text{total\_cost}
Annual total cost DS/Q + HQ/2 + Dc—1300
\text{ordering\_cost}
Annual ordering cost—400
\text{holding\_cost\_per\_year}
Annual holding cost—900
\text{purchase\_cost}
Annual purchase cost—0
\text{average\_inventory}
Average inventory Q/2—150

An optional input can be left out: a stated default is used.

Applies when

  • demand, order_cost, holding_cost, order_quantity > 0
  • unit_cost >= 0

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Total annual inventory cost with annual demand = 1200, ordering cost = 100, carrying cost = 6, lot size = 300.
total_cost = 1300
ordering_cost = 400
holding_cost_per_year = 900
purchase_cost = 0
average_inventory = 150

Run it

Terminal
$ industrial-engineering solve ie_inventory_total_cost demand=1200 order_cost=100 holding_cost=6 order_quantity=300
total_cost = 1300
ordering_cost = 400
holding_cost_per_year = 900
purchase_cost = 0
average_inventory = 150
  by: Annual inventory cost of an order quantity  (TC = D S / Q + H Q / 2 + D c)
  demand = 1200
  order_cost = 100
  holding_cost = 6
  order_quantity = 300
  assumes: demand, order_cost, holding_cost, order_quantity > 0; unit_cost >= 0

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Economic order quantity (EOQ)2 fig.ie_eoq

The order quantity that minimises annual ordering plus holding cost for constant demand: Q* = sqrt(2DS/H).

Q^* = \sqrt{\frac{2DS}{H}},\quad TC^* = \sqrt{2DSH}

You give

MeaningUnitExample
\text{demand}
Demand per year (units)—1200
\text{order\_cost}
Fixed cost per order or setup—100
\text{holding\_cost}
Holding cost per unit per year—6

You get

MeaningUnitExample
Q
Economic order quantity Q*—200
\text{orders\_per\_year}
Orders per year D/Q*—6
\text{cycle\_time}
Time between orders Q*/D (years)—0.1666666667
\text{ordering\_cost}
Annual ordering cost DS/Q*—600
\text{holding\_cost\_per\_year}
Annual holding cost HQ*/2—600
\text{total\_cost}
Annual ordering plus holding cost—1200

Applies when

  • demand > 0
  • order_cost > 0
  • holding_cost > 0 (per unit per year)

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Economic order quantity with annual demand = 1200, ordering cost = 100, carrying cost = 6.
Q = 200
orders_per_year = 6
cycle_time = 0.1666666667
ordering_cost = 600
holding_cost_per_year = 600
total_cost = 1200

Run it

Terminal
$ industrial-engineering solve ie_eoq demand=1200 order_cost=100 holding_cost=6
Q = 200
orders_per_year = 6
cycle_time = 0.1666666667
ordering_cost = 600
holding_cost_per_year = 600
total_cost = 1200
  by: Economic order quantity (EOQ)  (Q* = sqrt(2 D S / H); TC = D S / Q + H Q / 2 = sqrt(2 D S H))
  demand = 1200
  order_cost = 100
  holding_cost = 6
  assumes: demand > 0; order_cost > 0; holding_cost > 0 (per unit per year)

Figures

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Economic production quantity (EPQ)1 fig.ie_epq

Production lot size minimising setup plus holding cost when stock builds up gradually at a finite production rate.

Q^* = \sqrt{\frac{2DS}{H\,(1 – D/P)}}

You give

MeaningUnitExample
\text{demand}
Demand per year (units)—12000
\text{production\_rate}
Production rate per year (same units as demand)—48000
\text{order\_cost}
Fixed cost per order or setup—400
\text{holding\_cost}
Holding cost per unit per year—3

You get

MeaningUnitExample
Q
Economic production quantity—2065.591118
\text{max\_inventory}
Maximum inventory Q(1 – D/P)—1549.193338
\text{production\_run\_time}
Length of a production run Q/P (years)—0.04303314829
\text{cycle\_time}
Cycle Q/D (years)—0.1721325932
\text{runs\_per\_year}
Production runs per year—5.809475019
\text{total\_cost}
Annual setup plus holding cost—4647.580015

Applies when

  • all inputs > 0
  • production_rate > demand

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Economic production quantity with annual demand = 12000, annual production rate = 48000, ordering cost = 400, carrying cost = 3.
Q = 2065.591118
max_inventory = 1549.193338
production_run_time = 0.04303314829
cycle_time = 0.1721325932
runs_per_year = 5.809475019
total_cost = 4647.580015

Run it

Terminal
$ industrial-engineering solve ie_epq demand=12000 production_rate=48000 order_cost=400 holding_cost=3
Q = 2065.591118
max_inventory = 1549.193338
production_run_time = 0.04303314829
cycle_time = 0.1721325932
runs_per_year = 5.809475019
total_cost = 4647.580015
  by: Economic production quantity (EPQ)  (Q* = sqrt(2DS / (H (1 - D/P))), I_max = Q*(1 - D/P))
  demand = 12000
  production_rate = 48000
  order_cost = 400
  holding_cost = 3
  assumes: all inputs > 0; production_rate > demand

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

EOQ with all-units quantity discounts1 fig.ie_eoq_quantity_discount

Best order quantity when the unit price falls at quantity breaks (all-units discount) and holding cost is a fraction of the unit price.

TC_k(Q) = \frac{D}{Q}S + \frac{Q}{2}\,i\,p_k + D p_k

You give

MeaningUnitExample
\text{demand}
Demand per year (units)—5000
\text{order\_cost}
Fixed cost per order or setup—49
\text{holding\_rate}
Annual holding cost as a fraction of the unit price (decimal; 20% = 0.2)—0.2
\text{break\_quantities}
Minimum quantity of each price tier, starting with 0 vector—[0, 1000, 2000]
\text{unit\_prices}
Unit price of each tier (falling) vector—[5, 4.8, 4.75]

You get

MeaningUnitExample
Q
Best order quantity—1000
\text{unit\_price}
Unit price paid—4.8
\text{total\_cost}
Annual ordering + holding + purchase cost—24725
\text{tier}
Price tier chosen (1 = first)—2
\text{ordering\_cost}
Annual ordering cost—245
\text{holding\_cost\_per\_year}
Annual holding cost—480
\text{purchase\_cost}
Annual purchase cost—24000

Applies when

  • break_quantities start at 0 and increase
  • unit_prices fall tier by tier
  • 0 < holding_rate < 10

Outside these conditions it says what is wrong instead of returning a number.

Worked example

EOQ with quantity discounts with annual demand = 5000, ordering cost = 49, holding cost rate = 0.2, breaks = [0, 1000, 2000], prices = [5, 4.8, 4.75].
Q = 1000
unit_price = 4.8
total_cost = 24725
tier = 2
ordering_cost = 245
holding_cost_per_year = 480

Run it

Terminal
$ industrial-engineering solve ie_eoq_quantity_discount demand=5000 order_cost=49 holding_rate=0.2 "break_quantities=[0, 1000, 2000]" "unit_prices=[5, 4.8, 4.75]"
Q = 1000
unit_price = 4.8
total_cost = 24725
tier = 2
ordering_cost = 245
holding_cost_per_year = 480
purchase_cost = 24000
  by: EOQ with all-units quantity discounts  (for each tier: EOQ at its price, raised to the tier's minimum if below it (skipped if above the next break); the lowest total cost D S/Q + i p Q/2 + D p wins)
  demand = 5000
  order_cost = 49
  holding_rate = 0.2
  assumes: break_quantities start at 0 and increase; unit_prices fall tier by tier; 0 < holding_rate < 10

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

EOQ with planned backorders1 fig.ie_eoq_backorders

Order quantity and maximum backorder level minimising ordering, holding and backorder cost when shortages are allowed and fully backordered.

Q^*=\sqrt{\frac{2DS}{H}\cdot\frac{H+B}{B}},\quad b^*=Q^*\frac{H}{H+B}

You give

MeaningUnitExample
\text{demand}
Demand per year (units)—1200
\text{order\_cost}
Fixed cost per order or setup—100
\text{holding\_cost}
Holding cost per unit per year—6
\text{backorder\_cost}
Backorder (shortage) cost per unit per year—18

You get

MeaningUnitExample
Q
Optimal order quantity—230.9401077
\text{max\_backorder}
Maximum backorder level b*—57.73502692
\text{max\_inventory}
Maximum inventory Q* – b*—173.2050808
\text{total\_cost}
Minimum annual cost—1039.230485
\text{orders\_per\_year}
Orders per year—5.196152423
\text{fraction\_backordered\_time}
Fraction of time out of stock H/(H+B)—0.25

Applies when

  • all inputs > 0
  • every shortage is backordered

Outside these conditions it says what is wrong instead of returning a number.

Worked example

EOQ with planned backorders with annual demand = 1200, ordering cost = 100, carrying cost = 6, shortage cost = 18.
Q = 230.9401077
max_backorder = 57.73502692
max_inventory = 173.2050808
total_cost = 1039.230485
orders_per_year = 5.196152423
fraction_backordered_time = 0.25

Run it

Terminal
$ industrial-engineering solve ie_eoq_backorders demand=1200 order_cost=100 holding_cost=6 backorder_cost=18
Q = 230.9401077
max_backorder = 57.73502692
max_inventory = 173.2050808
total_cost = 1039.230485
orders_per_year = 5.196152423
fraction_backordered_time = 0.25
  by: EOQ with planned backorders  (Q* = sqrt(2DS/H (H+B)/B), b* = Q* H/(H+B), TC* = sqrt(2DSH B/(H+B)))
  demand = 1200
  order_cost = 100
  holding_cost = 6
  backorder_cost = 18
  assumes: all inputs > 0; every shortage is backordered

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Inventory turnover and days of supply2 fig.ie_inventory_turnover

How many times a year inventory turns over and how many days (weeks) of supply it holds.

\text{turns} = \frac{\text{COGS}}{\bar I},\quad \text{days of supply} = \frac{365}{\text{turns}}

You give

MeaningUnitExample
\text{cost\_of\_goods\_sold}
Annual cost of goods sold—1200000
\text{average\_inventory}
Average inventory value (at cost)—150000
\text{days\_per\_year}
Days in the year used (default 365) optional—

You get

MeaningUnitExample
\text{turnover}
Inventory turns per year COGS / average inventory—8
\text{days\_of\_supply}
Days of supply—45.625
\text{weeks\_of\_supply}
Weeks of supply—6.5

An optional input can be left out: a stated default is used.

Applies when

  • all inputs > 0

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Inventory turnover with cogs = 1200000, inventory = 150000.
turnover = 8
days_of_supply = 45.625
weeks_of_supply = 6.5

Run it

Terminal
$ industrial-engineering solve ie_inventory_turnover cost_of_goods_sold=1200000 average_inventory=150000
turnover = 8
days_of_supply = 45.625
weeks_of_supply = 6.5
  by: Inventory turnover and days of supply  (turnover = COGS / average inventory; days = days per year / turnover)
  cost_of_goods_sold = 1200000
  average_inventory = 150000
  assumes: all inputs > 0

Figures

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Newsvendor order quantity (discrete demand table)2 fig.ie_newsvendor_discrete

Best single-period order quantity among the listed demand values, given their probabilities.

Q^* = \min\{d_k : F(d_k) \ge \tfrac{C_u}{C_u+C_o}\}

You give

MeaningUnitExample
\text{price}
Selling price per unit—10
\text{cost}
Purchase cost per unit—4
\text{demands}
Possible demand values (increasing) vector—[20, 30, 40, 50]
\text{probabilities}
Probability of each demand value (sum 1) vector—[0.2, 0.3, 0.3, 0.2]
\text{salvage}
Salvage value per unsold unit (optional, default 0) optional—

You get

MeaningUnitExample
Q
Optimal order quantity (one of the demand values)—40
\text{critical\_ratio}
Critical ratio—0.6
\text{expected\_sales}
Expected units sold—33
\text{expected\_profit}
Expected profit—170

An optional input can be left out: a stated default is used.

Applies when

  • salvage < cost < price
  • demands increasing
  • probabilities add to 1
  • refused when two quantities are equally good

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Newsvendor with discrete demand with selling price = 10, unit cost = 4, demand values = [20, 30, 40, 50], probs = [0.2, 0.3, 0.3, 0.2].
Q = 40
critical_ratio = 0.6
expected_sales = 33
expected_profit = 170

Run it

Terminal
$ industrial-engineering solve ie_newsvendor_discrete price=10 cost=4 "demands=[20, 30, 40, 50]" "probabilities=[0.2, 0.3, 0.3, 0.2]"
Q = 40
critical_ratio = 0.6
expected_sales = 33
expected_profit = 170
  by: Newsvendor order quantity (discrete demand table)  (smallest demand value whose cumulative probability exceeds Cu/(Cu+Co); expected profit sum p_k profit(Q, d_k))
  price = 10
  cost = 4
  assumes: salvage < cost < price; demands increasing; probabilities add to 1; refused when two quantities are equally good

Figures

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Newsvendor order quantity (normal demand)1 fig.ie_newsvendor_normal

Single-period order quantity that maximises expected profit when demand is normal: the critical ratio Cu/(Cu + Co).

F(Q^*) = \frac{C_u}{C_u + C_o},\quad Q^* = \mu + z\sigma

You give

MeaningUnitExample
\text{price}
Selling price per unit—10
\text{cost}
Purchase cost per unit—6
\text{mean\_demand}
Mean demand per period (per day, say)—500
\text{sd\_demand}
Standard deviation of demand per period—100
\text{salvage}
Salvage value per unsold unit (optional, default 0) optional—2

You get

MeaningUnitExample
Q
Optimal order quantity mu + z sigma—500
\text{critical\_ratio}
Critical ratio Cu/(Cu+Co)—0.5
z
z of the critical ratio—0
\text{expected\_sales}
Expected units sold—460.105772
\text{expected\_leftover}
Expected units left over—39.89422804
\text{expected\_shortage}
Expected unmet demand—39.89422804
\text{expected\_profit}
Expected profit—1680.846176

An optional input can be left out: a stated default is used.

Applies when

  • salvage < cost < price
  • sd_demand > 0
  • demand normal

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Newsvendor order quantity with selling price = 10, unit cost = 6, average daily demand = 500, standard deviation of daily demand = 100, salvage value = 2.
Q = 500
critical_ratio = 0.5
z = 0
expected_sales = 460.105772
expected_leftover = 39.89422804
expected_shortage = 39.89422804

Run it

Terminal
$ industrial-engineering solve ie_newsvendor_normal price=10 cost=6 mean_demand=500 sd_demand=100 salvage=2
Q = 500
critical_ratio = 0.5
z = 0
expected_sales = 460.105772
expected_leftover = 39.89422804
expected_shortage = 39.89422804
expected_profit = 1680.846176
  by: Newsvendor order quantity (normal demand)  (Cu = p - c, Co = c - v, CR = Cu/(Cu+Co), Q = mu + Phi^-1(CR) sigma; E[sales] = mu - sigma L(z))
  price = 10
  cost = 6
  mean_demand = 500
  sd_demand = 100
  salvage = 2
  assumes: salvage < cost < price; sd_demand > 0; demand normal

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Newsvendor order quantity (Poisson demand)1 fig.ie_newsvendor_poisson

Whole-unit single-period order quantity when demand is Poisson: the smallest Q with F(Q) ≥ critical ratio.

Q^* = \min\{Q : F(Q) \ge \tfrac{C_u}{C_u+C_o}\}

You give

MeaningUnitExample
\text{price}
Selling price per unit—20
\text{cost}
Purchase cost per unit—8
\text{mean\_demand}
Mean (Poisson) demand—12
\text{salvage}
Salvage value per unsold unit (optional, default 0) optional—

You get

MeaningUnitExample
Q
Optimal whole order quantity—13
\text{critical\_ratio}
Critical ratio—0.6
\text{expected\_sales}
Expected units sold—11.05161977
\text{expected\_leftover}
Expected units left over—1.948380235
\text{expected\_profit}
Expected profit—117.0323953
\text{stockout\_probability}
Probability demand exceeds Q—0.3184643679

An optional input can be left out: a stated default is used.

Applies when

  • salvage < cost < price
  • 0 < mean_demand <= 500
  • demand Poisson

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Newsvendor with Poisson demand with selling price = 20, unit cost = 8, average demand = 12.
Q = 13
critical_ratio = 0.6
expected_sales = 11.05161977
expected_leftover = 1.948380235
expected_profit = 117.0323953
stockout_probability = 0.3184643679

Run it

Terminal
$ industrial-engineering solve ie_newsvendor_poisson price=20 cost=8 mean_demand=12
Q = 13
critical_ratio = 0.6
expected_sales = 11.05161977
expected_leftover = 1.948380235
expected_profit = 117.0323953
stockout_probability = 0.3184643679
  by: Newsvendor order quantity (Poisson demand)  (smallest Q with P(D <= Q) >= Cu/(Cu+Co); E[leftover] = sum_{k<Q} (Q - k) P(D = k))
  price = 20
  cost = 8
  mean_demand = 12
  assumes: salvage < cost < price; 0 < mean_demand <= 500; demand Poisson

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Newsvendor order quantity (uniform demand)1 fig.ie_newsvendor_uniform

Single-period order quantity and expected profit when demand is uniform between two bounds.

Q^* = a + \frac{C_u}{C_u + C_o}(b – a)

You give

MeaningUnitExample
\text{price}
Selling price per unit—12
\text{cost}
Purchase cost per unit—7
\text{low}
Lowest possible demand—100
\text{high}
Highest possible demand—300
\text{salvage}
Salvage value per unsold unit (optional, default 0) optional—3

You get

MeaningUnitExample
Q
Optimal order quantity a + CR (b – a)—211.1111111
\text{critical\_ratio}
Critical ratio—0.5555555556
\text{expected\_sales}
Expected units sold—180.2469136
\text{expected\_leftover}
Expected units left over—30.86419753
\text{expected\_profit}
Expected profit—777.7777778

An optional input can be left out: a stated default is used.

Applies when

  • salvage < cost < price
  • high > low
  • demand uniform on [low, high]

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Newsvendor with uniform demand with selling price = 12, unit cost = 7, minimum demand = 100, maximum demand = 300, salvage value = 3.
Q = 211.1111111
critical_ratio = 0.5555555556
expected_sales = 180.2469136
expected_leftover = 30.86419753
expected_profit = 777.7777778

Run it

Terminal
$ industrial-engineering solve ie_newsvendor_uniform price=12 cost=7 low=100 high=300 salvage=3
Q = 211.1111111
critical_ratio = 0.5555555556
expected_sales = 180.2469136
expected_leftover = 30.86419753
expected_profit = 777.7777778
  by: Newsvendor order quantity (uniform demand)  (Q = a + CR (b - a), E[sales] = Q - (Q - a)^2 / (2 (b - a)))
  price = 12
  cost = 7
  low = 100
  high = 300
  salvage = 3
  assumes: salvage < cost < price; high > low; demand uniform on [low, high]

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Number of kanbans1 fig.ie_kanban_count

Number of kanban containers needed to cover demand during the replenishment lead time plus a safety factor.

N = \left\lceil \frac{d\,L\,(1+\alpha)}{C} \right\rceil

You give

MeaningUnitExample
\text{demand\_rate}
Demand per time unit (per hour, say)—100
\text{lead\_time}
Replenishment lead time in the same time unit (waiting + processing)—2
\text{container\_size}
Parts per container—20
\text{safety\_factor}
Safety factor (decimal; default 0) optional—0.1

You get

MeaningUnitExample
\text{kanbans}
Number of kanbans (rounded up)—11
\text{exact}
d L (1 + alpha) / C before rounding—11
\text{max\_inventory}
Maximum inventory N C—220

An optional input can be left out: a stated default is used.

Applies when

  • demand_rate, lead_time, container_size > 0
  • safety_factor >= 0

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Number of kanbans with demand = 100, replenishment time = 2, container capacity = 20, alpha = 0.1.
kanbans = 11
exact = 11
max_inventory = 220

Run it

Terminal
$ industrial-engineering solve ie_kanban_count demand_rate=100 lead_time=2 container_size=20 safety_factor=0.1
kanbans = 11
exact = 11
max_inventory = 220
  by: Number of kanbans  (N = ceil(d L (1 + alpha) / C))
  demand_rate = 100
  lead_time = 2
  container_size = 20
  safety_factor = 0.1
  assumes: demand_rate, lead_time, container_size > 0; safety_factor >= 0

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Periodic review order-up-to level1 fig.ie_order_up_to_level

Order-up-to level (and order size) of a periodic-review policy that protects against demand over the review period plus the lead time.

S = \bar d\,(T+L) + z\,\sigma_d\sqrt{T+L}

You give

MeaningUnitExample
\text{mean\_demand}
Mean demand per period (per day, say)—20
\text{sd\_demand}
Standard deviation of demand per period—4
\text{review\_period}
Periods between reviews—14
\text{lead\_time}
Lead time in periods—7
\text{service\_level}
Cycle service level: probability of no stock-out per cycle (decimal)—0.95
\text{inventory\_position}
Current inventory position: on hand + on order – backorders (optional) optional—150

You get

MeaningUnitExample
\text{order\_up\_to\_level}
Order-up-to level S = d(T+L) + z sigma sqrt(T+L)—450.150665
\text{safety\_stock}
Safety stock—30.15066501
z
Service factor—1.644853627
\text{sd\_protection\_demand}
Standard deviation of demand over T + L—18.33030278
\text{order\_quantity}
Order size S – inventory position (when given)—300.150665

An optional input can be left out: a stated default is used.

Applies when

  • mean_demand, sd_demand, review_period > 0
  • lead_time >= 0
  • 0.5 < service_level < 1

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Order-up-to level with average daily demand = 20, standard deviation of daily demand = 4, review interval = 14, lead time in days = 7, cycle service level = 0.95, on hand = 150.
order_up_to_level = 450.150665
safety_stock = 30.15066501
z = 1.644853627
sd_protection_demand = 18.33030278
order_quantity = 300.150665

Run it

Terminal
$ industrial-engineering solve ie_order_up_to_level mean_demand=20 sd_demand=4 review_period=14 lead_time=7 service_level=0.95 inventory_position=150
order_up_to_level = 450.150665
safety_stock = 30.15066501
z = 1.644853627
sd_protection_demand = 18.33030278
order_quantity = 300.150665
  by: Periodic review order-up-to level  (S = d (T + L) + z sigma_d sqrt(T + L); order S - IP)
  mean_demand = 20
  sd_demand = 4
  review_period = 14
  lead_time = 7
  service_level = 0.95
  inventory_position = 150
  assumes: mean_demand, sd_demand, review_period > 0; lead_time >= 0; 0.5 < service_level < 1

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Reorder point (constant demand)2 fig.ie_reorder_point

Inventory level at which to reorder: demand during the lead time plus any safety stock.

ROP = d\,L + SS

You give

MeaningUnitExample
\text{demand\_rate}
Demand per period (per day, say)—40
\text{lead\_time}
Lead time in the same periods—5
\text{safety\_stock}
Safety stock (optional, default 0) optional—

You get

MeaningUnitExample
\text{reorder\_point}
Reorder point d L + SS—200
\text{lead\_time\_demand}
Demand during the lead time d L—200

An optional input can be left out: a stated default is used.

Applies when

  • demand_rate > 0
  • lead_time >= 0
  • safety_stock >= 0

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Reorder point with daily demand = 40, lead time in days = 5.
reorder_point = 200
lead_time_demand = 200

Run it

Terminal
$ industrial-engineering solve ie_reorder_point demand_rate=40 lead_time=5
reorder_point = 200
lead_time_demand = 200
  by: Reorder point (constant demand)  (ROP = d L + SS)
  demand_rate = 40
  lead_time = 5
  assumes: demand_rate > 0; lead_time >= 0; safety_stock >= 0

Figures

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Safety stock and reorder point (normal demand)1 fig.ie_safety_stock

Safety stock and reorder point for a cycle service level when demand per period is normal and the lead time is fixed.

SS = z\,\sigma_d\sqrt{L},\quad ROP = \bar d L + SS

You give

MeaningUnitExample
\text{mean\_demand}
Mean demand per period (per day, say)—50
\text{sd\_demand}
Standard deviation of demand per period—12
\text{lead\_time}
Lead time in periods—9
\text{service\_level}
Cycle service level: probability of no stock-out per cycle (decimal)—0.95

You get

MeaningUnitExample
\text{safety\_stock}
Safety stock z sigma sqrt(L)—59.21473057
\text{reorder\_point}
Reorder point d L + SS—509.2147306
z
Service factor z—1.644853627
\text{sd\_lead\_time\_demand}
Standard deviation of lead-time demand—36
\text{lead\_time\_demand}
Mean lead-time demand—450

Applies when

  • mean_demand, sd_demand, lead_time > 0
  • 0.5 < service_level < 1
  • demand per period independent and normal

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Safety stock with average daily demand = 50, standard deviation of daily demand = 12, lead time in days = 9, cycle service level = 0.95.
safety_stock = 59.21473057
reorder_point = 509.2147306
z = 1.644853627
sd_lead_time_demand = 36
lead_time_demand = 450

Run it

Terminal
$ industrial-engineering solve ie_safety_stock mean_demand=50 sd_demand=12 lead_time=9 service_level=0.95
safety_stock = 59.21473057
reorder_point = 509.2147306
z = 1.644853627
sd_lead_time_demand = 36
lead_time_demand = 450
  by: Safety stock and reorder point (normal demand)  (sigma_L = sigma_d sqrt(L), z = Phi^-1(CSL), SS = z sigma_L, ROP = d L + SS)
  mean_demand = 50
  sd_demand = 12
  lead_time = 9
  service_level = 0.95
  assumes: mean_demand, sd_demand, lead_time > 0; 0.5 < service_level < 1; demand per period independent and normal

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Safety stock with variable demand and lead time1 fig.ie_safety_stock_variable_lead_time

Safety stock and reorder point when both the demand per period and the lead time vary.

\sigma_{DL} = \sqrt{\bar L\,\sigma_d^2 + \bar d^{\,2}\sigma_L^2},\quad SS = z\,\sigma_{DL}

You give

MeaningUnitExample
\text{mean\_demand}
Mean demand per period (per day, say)—100
\text{sd\_demand}
Standard deviation of demand per period—20
\text{mean\_lead\_time}
Mean lead time in periods—6
\text{sd\_lead\_time}
Standard deviation of the lead time—2
\text{service\_level}
Cycle service level: probability of no stock-out per cycle (decimal)—0.95

You get

MeaningUnitExample
\text{safety\_stock}
Safety stock z sigma_DL—338.6960916
\text{reorder\_point}
Reorder point d L + SS—938.6960916
\text{sd\_lead\_time\_demand}
sigma_DL = sqrt(L sigma_d^2 + d^2 sigma_L^2)—205.9126028
z
Service factor—1.644853627

Applies when

  • mean_demand, mean_lead_time > 0
  • standard deviations >= 0, not both 0
  • 0.5 < service_level < 1
  • demand and lead time independent; lead-time demand treated as normal

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Safety stock with variable lead time with average daily demand = 100, standard deviation of daily demand = 20, average lead time = 6, standard deviation of lead time = 2, cycle service level = 0.95.
safety_stock = 338.6960916
reorder_point = 938.6960916
sd_lead_time_demand = 205.9126028
z = 1.644853627

Run it

Terminal
$ industrial-engineering solve ie_safety_stock_variable_lead_time mean_demand=100 sd_demand=20 mean_lead_time=6 sd_lead_time=2 service_level=0.95
safety_stock = 338.6960916
reorder_point = 938.6960916
sd_lead_time_demand = 205.9126028
z = 1.644853627
  by: Safety stock with variable demand and lead time  (sigma_DL = sqrt(L sigma_d^2 + d^2 sigma_L^2), SS = z sigma_DL)
  mean_demand = 100
  sd_demand = 20
  mean_lead_time = 6
  sd_lead_time = 2
  service_level = 0.95
  assumes: mean_demand, mean_lead_time > 0; standard deviations >= 0, not both 0; 0.5 < service_level < 1; demand and lead time independent; lead-time demand treated as normal

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Service level of a reorder point1 fig.ie_service_level_from_reorder_point

Cycle service level, expected shortage per cycle and fill rate achieved by a given reorder point with normal lead-time demand.

CSL = \Phi(z),\quad ESC = \sigma_L\,L(z),\quad \beta = 1 – \frac{ESC}{Q}

You give

MeaningUnitExample
\text{mean\_ltd}
Mean demand during the lead time—500
\text{sd\_ltd}
Standard deviation of lead-time demand—100
\text{reorder\_point}
Reorder point R—650
\text{order\_quantity}
Order quantity Q (optional; gives the fill rate) optional—1000

You get

MeaningUnitExample
\text{cycle\_service\_level}
P(no stock-out in a cycle) = Phi(z)—0.9331927987
z
Service factor (R – mu)/sigma—1.5
\text{safety\_stock}
Safety stock R – mu—150
\text{expected\_shortage\_per\_cycle}
sigma L(z)—2.930679376
\text{fill\_rate}
Fill rate 1 – ESC/Q (when Q is given)—0.9970693206

An optional input can be left out: a stated default is used.

Applies when

  • sd_ltd > 0
  • order_quantity > 0 when given

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Service level of a reorder point with mean lead time demand = 500, standard deviation of lead time demand = 100, reorder point = 650, lot size = 1000.
cycle_service_level = 0.9331927987
z = 1.5
safety_stock = 150
expected_shortage_per_cycle = 2.930679376
fill_rate = 0.9970693206

Run it

Terminal
$ industrial-engineering solve ie_service_level_from_reorder_point mean_ltd=500 sd_ltd=100 reorder_point=650 order_quantity=1000
cycle_service_level = 0.9331927987
z = 1.5
safety_stock = 150
expected_shortage_per_cycle = 2.930679376
fill_rate = 0.9970693206
  by: Service level of a reorder point  (z = (R - mu)/sigma, CSL = Phi(z), ESC = sigma L(z), fill rate = 1 - ESC/Q)
  mean_ltd = 500
  sd_ltd = 100
  reorder_point = 650
  order_quantity = 1000
  assumes: sd_ltd > 0; order_quantity > 0 when given

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Learning curves 5

Cumulative-average learning curve (Wright)1 fig.ie_learning_curve_cumulative_average

Wright's model, where the cumulative AVERAGE time falls by the learning rate at each doubling: average, total and N-th unit time.

\bar T_N = T_1 N^{b},\quad \text{total}_N = T_1 N^{b+1}

You give

MeaningUnitExample
\text{first\_unit\_time}
Time (or cost) of the first unit—100
\text{learning\_rate}
Learning rate (decimal; 80% = 0.8)—0.8
\text{units}
Cumulative units N—4

You get

MeaningUnitExample
\text{cumulative\_average\_time}
T_1 N^b—64
\text{total\_time}
T_1 N^(b+1)—256
\text{unit\_time}
Time of unit N: total(N) – total(N – 1)—45.36888917

Applies when

  • first_unit_time > 0
  • 0 < learning_rate <= 1
  • units >= 1

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Cumulative average learning curve with first unit time = 100, learning curve rate = 0.8, number of units = 4.
cumulative_average_time = 64
total_time = 256
unit_time = 45.36888917

Run it

Terminal
$ industrial-engineering solve ie_learning_curve_cumulative_average first_unit_time=100 learning_rate=0.8 units=4
cumulative_average_time = 64
total_time = 256
unit_time = 45.36888917
  by: Cumulative-average learning curve (Wright)  (average(N) = T_1 N^b; total = N average; unit N = total(N) - total(N - 1))
  first_unit_time = 100
  learning_rate = 0.8
  assumes: first_unit_time > 0; 0 < learning_rate <= 1; units >= 1

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Fit a learning curve to data (log-log regression)1 fig.ie_learning_curve_fit

Learning rate and first-unit time estimated by least squares on log(time) against log(unit number).

\ln T_n = \ln T_1 + b\ln n

You give

MeaningUnitExample
\text{units}
Unit numbers observed vector—[1, 2, 4, 8, 16]
\text{times}
Time of each observed unit vector—[100, 82, 63, 52, 40]

You get

MeaningUnitExample
\text{learning\_rate}
2^b—0.7954830815
\text{exponent}
Slope b of the log-log fit—-0.3300968476
\text{first\_unit\_time}
exp(intercept)—101.1536719
r_{\mathrm{squared}}
Coefficient of determination—0.997447163

Applies when

  • positive values
  • at least 2 different unit numbers

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Fit a learning curve with unit numbers = [1, 2, 4, 8, 16], unit times = [100, 82, 63, 52, 40].
learning_rate = 0.7954830815
exponent = -0.3300968476
first_unit_time = 101.1536719
r_squared = 0.997447163

Run it

Terminal
$ industrial-engineering solve ie_learning_curve_fit "units=[1, 2, 4, 8, 16]" "times=[100, 82, 63, 52, 40]"
learning_rate = 0.7954830815
exponent = -0.3300968476
first_unit_time = 101.1536719
r_squared = 0.997447163
  by: Fit a learning curve to data (log-log regression)  (regress ln T on ln n: ln T = ln T_1 + b ln n; r = 2^b)
  assumes: positive values; at least 2 different unit numbers

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Learning curve: time of the n-th unit1 fig.ie_learning_curve_unit

Time of the n-th unit on a learning curve: each doubling of output multiplies the unit time by the learning rate (T_n = T_1 n^b, b = log2 r).

T_n = T_1\,n^{b},\quad b = \frac{\ln r}{\ln 2}

You give

MeaningUnitExample
\text{first\_unit\_time}
Time (or cost) of the first unit—100
\text{learning\_rate}
Learning rate (decimal; 80% = 0.8)—0.8
\text{unit}
Unit number n—8

You get

MeaningUnitExample
\text{unit\_time}
T_1 n^b—51.2
\text{exponent}
b = log2(learning rate)—-0.3219280949

Applies when

  • first_unit_time > 0
  • 0 < learning_rate <= 1
  • unit >= 1

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Learning curve unit time with first unit time = 100, learning curve rate = 0.8, unit number = 8.
unit_time = 51.2
exponent = -0.3219280949

Run it

Terminal
$ industrial-engineering solve ie_learning_curve_unit first_unit_time=100 learning_rate=0.8 unit=8
unit_time = 51.2
exponent = -0.3219280949
  by: Learning curve: time of the n-th unit  (T_n = T_1 n^(log2 r))
  first_unit_time = 100
  learning_rate = 0.8
  assumes: first_unit_time > 0; 0 < learning_rate <= 1; unit >= 1

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Learning curve: total and average time of N units1 fig.ie_learning_curve_total

Total and average time to make units 1 to N on a unit learning curve (sum of T_1 i^b).

\sum_{i=1}^{N} T_1\,i^{b}

You give

MeaningUnitExample
\text{first\_unit\_time}
Time (or cost) of the first unit—100
\text{learning\_rate}
Learning rate (decimal; 80% = 0.8)—0.8
\text{units}
Number of units N—8

You get

MeaningUnitExample
\text{total\_time}
sum_{i=1}^{N} T_1 i^b—534.5913533
\text{average\_time}
Total / N—66.82391917
\text{last\_unit\_time}
T_1 N^b—51.2

Applies when

  • first_unit_time > 0
  • 0 < learning_rate <= 1
  • 1 <= units <= 200000

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Learning curve total time with first unit time = 100, learning curve rate = 0.8, number of units = 8.
total_time = 534.5913533
average_time = 66.82391917
last_unit_time = 51.2

Run it

Terminal
$ industrial-engineering solve ie_learning_curve_total first_unit_time=100 learning_rate=0.8 units=8
total_time = 534.5913533
average_time = 66.82391917
last_unit_time = 51.2
  by: Learning curve: total and average time of N units  (total = T_1 sum_{i=1}^{N} i^b)
  first_unit_time = 100
  learning_rate = 0.8
  assumes: first_unit_time > 0; 0 < learning_rate <= 1; 1 <= units <= 200000

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Learning rate from two unit times1 fig.ie_learning_rate_from_two_units

Learning rate, exponent and first-unit time of a unit learning curve through two observed (unit, time) points.

b = \frac{\ln(t_2/t_1)}{\ln(n_2/n_1)},\quad r = 2^{b}

You give

MeaningUnitExample
\text{unit1}
First unit number—1
\text{time1}
Time of that unit—100
\text{unit2}
Second unit number—8
\text{time2}
Time of that unit—51.2

You get

MeaningUnitExample
\text{learning\_rate}
2^b—0.8
\text{exponent}
b = ln(t2/t1)/ln(n2/n1)—-0.3219280949
\text{first\_unit\_time}
t1 / n1^b—100

Applies when

  • units and times > 0
  • unit numbers differ

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Learning rate from two units with first unit = 1, time a = 100, second unit = 8, time b = 51.2.
learning_rate = 0.8
exponent = -0.3219280949
first_unit_time = 100

Run it

Terminal
$ industrial-engineering solve ie_learning_rate_from_two_units unit1=1 time1=100 unit2=8 time2=51.2
learning_rate = 0.8
exponent = -0.3219280949
first_unit_time = 100
  by: Learning rate from two unit times  (b = ln(t2/t1) / ln(n2/n1), r = 2^b, T_1 = t1 / n1^b)
  unit1 = 1
  time1 = 100
  unit2 = 8
  time2 = 51.2
  assumes: units and times > 0; unit numbers differ

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Line balancing 4

Line balance efficiency, balance delay and idle time1 fig.ie_line_efficiency

Efficiency of a balanced line: total task time / (stations x cycle time), the balance delay and the idle time per cycle.

E = \frac{\sum t_i}{N\,C},\quad \text{balance delay} = 1 – E

You give

MeaningUnitExample
\text{task\_times}
Time of each task vector—[0.5, 1.2, 0.8, 0.4, 1, 0.6]
\text{cycle\_time}
Cycle time—1.5
\text{stations}
Number of workstations used—4

You get

MeaningUnitExample
\text{efficiency}
sum t / (N C)—0.75
\text{balance\_delay}
1 – efficiency—0.25
\text{idle\_time}
N C – sum t per cycle—1.5
\text{total\_task\_time}
Sum of task times—4.5
\text{minimum\_stations}
Theoretical minimum stations—3

Applies when

  • task times > 0
  • each task ≤ cycle time
  • sum t <= N C

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Line efficiency with task times = [0.5, 1.2, 0.8, 0.4, 1, 0.6], cycle time = 1.5, workstations = 4.
efficiency = 0.75
balance_delay = 0.25
idle_time = 1.5
total_task_time = 4.5
minimum_stations = 3

Run it

Terminal
$ industrial-engineering solve ie_line_efficiency "task_times=[0.5, 1.2, 0.8, 0.4, 1, 0.6]" cycle_time=1.5 stations=4
efficiency = 0.75
balance_delay = 0.25
idle_time = 1.5
total_task_time = 4.5
minimum_stations = 3
  by: Line balance efficiency, balance delay and idle time  (E = sum t / (N C); idle = N C - sum t)
  cycle_time = 1.5
  assumes: task times > 0; each task <= cycle time; sum t <= N C

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Line balancing by ranked positional weight2 fig.ie_ranked_positional_weight

Helgeson-Birnie method: rank tasks by positional weight (own time + times of all following tasks) and fill stations in that order.

RPW_j = t_j + \sum_{k \in S(j)} t_k

You give

MeaningUnitExample
\text{task\_times}
Time of each task (tasks numbered 1, 2, …) vector—[2, 3, 4, 3, 6, 4, 2, 3]
\text{precedence}
Precedence rows [a, b]: task a must be done before task b matrix—[1 2; 1 3; 2 4; 3 5; 4 6; 5 6; 6 7; 7 8]
\text{cycle\_time}
Cycle time—10

You get

MeaningUnitExample
\text{stations}
Number of stations—3
\text{assignment}
Station number of each task—[1, 1, 1, 2, 2, 3, 3, 3]
\text{station\_times}
Work assigned to each station—[9, 9, 9]
\text{efficiency}
sum t / (N C)—0.9
\text{idle\_time}
N C – sum t—3
\text{minimum\_stations}
Theoretical minimum stations—3
\text{positional\_weights}
Positional weight of each task—[27, 15, 19, 12, 15, 9, 5, 3]

Applies when

  • task times > 0 and ≤ cycle time
  • precedence acyclic
  • ties go to the lower task number

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Line balancing by ranked positional weight with task times = [2, 3, 4, 3, 6, 4, 2, 3], precedence relations = [[1, 2], [1, 3], [2, 4], [3, 5], [4, 6], [5, 6], [6, 7], [7, 8]], takt time = 10.
stations = 3
assignment = [1, 1, 1, 2, 2, 3, 3, 3]
station_times = [9, 9, 9]
efficiency = 0.9
idle_time = 3
minimum_stations = 3

Run it

Terminal
$ industrial-engineering solve ie_ranked_positional_weight "task_times=[2, 3, 4, 3, 6, 4, 2, 3]" "precedence=[[1, 2], [1, 3], [2, 4], [3, 5], [4, 6], [5, 6], [6, 7], [7, 8]]" cycle_time=10
stations = 3
assignment = [1,1,1,2,2,3,3,3]
station_times = [9.0,9.0,9.0]
efficiency = 0.9
idle_time = 3
minimum_stations = 3
positional_weights = [27.0,15.0,19.0,12.0,15.0,9.0,5.0,3.0]
  by: Line balancing by ranked positional weight  (RPW_j = t_j + sum of t over all successors of j; assign the eligible task with the highest RPW that fits)
  cycle_time = 10
  assumes: task times > 0 and <= cycle time; precedence acyclic; ties go to the lower task number

Figures

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Line balancing by the largest candidate rule2 fig.ie_largest_candidate_rule

Assign tasks to stations: fill each station with the longest eligible task that still fits (all predecessors assigned), then open the next station.

E = \frac{\sum t_i}{N\,C}

You give

MeaningUnitExample
\text{task\_times}
Time of each task (tasks numbered 1, 2, …) vector—[2, 3, 4, 3, 6, 4, 2, 3]
\text{precedence}
Precedence rows [a, b]: task a must be done before task b matrix—[1 2; 1 3; 2 4; 3 5; 4 6; 5 6; 6 7; 7 8]
\text{cycle\_time}
Cycle time—10

You get

MeaningUnitExample
\text{stations}
Number of stations—3
\text{assignment}
Station number of each task—[1, 1, 1, 2, 2, 3, 3, 3]
\text{station\_times}
Work assigned to each station—[9, 9, 9]
\text{efficiency}
sum t / (N C)—0.9
\text{idle\_time}
N C – sum t—3
\text{minimum\_stations}
Theoretical minimum stations—3

Applies when

  • task times > 0 and ≤ cycle time
  • precedence acyclic
  • ties go to the lower task number

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Line balancing by the largest candidate rule with task times = [2, 3, 4, 3, 6, 4, 2, 3], precedence relations = [[1, 2], [1, 3], [2, 4], [3, 5], [4, 6], [5, 6], [6, 7], [7, 8]], takt time = 10.
stations = 3
assignment = [1, 1, 1, 2, 2, 3, 3, 3]
station_times = [9, 9, 9]
efficiency = 0.9
idle_time = 3
minimum_stations = 3

Run it

Terminal
$ industrial-engineering solve ie_largest_candidate_rule "task_times=[2, 3, 4, 3, 6, 4, 2, 3]" "precedence=[[1, 2], [1, 3], [2, 4], [3, 5], [4, 6], [5, 6], [6, 7], [7, 8]]" cycle_time=10
stations = 3
assignment = [1,1,1,2,2,3,3,3]
station_times = [9.0,9.0,9.0]
efficiency = 0.9
idle_time = 3
minimum_stations = 3
  by: Line balancing by the largest candidate rule  (largest candidate rule: at each station repeatedly add the eligible task with the largest time that fits)
  cycle_time = 10
  assumes: task times > 0 and <= cycle time; precedence acyclic; ties go to the lower task number

Figures

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Takt (cycle) time and minimum stations1 fig.ie_takt_time

Cycle time that meets demand (available production time / demand) and, with the total task time, the theoretical minimum number of stations.

C = \frac{\text{available time}}{\text{demand}},\quad N_{min} = \left\lceil\frac{\sum t_i}{C}\right\rceil

You give

MeaningUnitExample
\text{available\_time}
Production time available per period (minutes, say)—480
\text{demand}
Units required per period—60
\text{total\_task\_time}
Sum of all task times (same time unit), optional optional—30

You get

MeaningUnitExample
\text{cycle\_time}
Takt time = available time / demand—8
\text{output\_rate}
Units per time unit—0.125
\text{minimum\_stations}
Theoretical minimum stations ceil(total task time / cycle time)—4
\text{exact\_stations}
Total task time / cycle time—3.75

An optional input can be left out: a stated default is used.

Applies when

  • inputs > 0
  • consistent time units

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Takt time with available production time = 480, required output = 60, sum of task times = 30.
cycle_time = 8
output_rate = 0.125
minimum_stations = 4
exact_stations = 3.75

Run it

Terminal
$ industrial-engineering solve ie_takt_time available_time=480 demand=60 total_task_time=30
cycle_time = 8
output_rate = 0.125
minimum_stations = 4
exact_stations = 3.75
  by: Takt (cycle) time and minimum stations  (C = available time / demand; N_min = ceil(sum t / C))
  available_time = 480
  demand = 60
  total_task_time = 30
  assumes: inputs > 0; consistent time units

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Queueing 8

Cost-optimal number of servers1 fig.ie_queue_server_cost

Number of servers of an M/M/c queue that minimises server cost plus the cost of customers waiting in the system per time unit.

TC(c) = c\,C_s + C_w\,L(c)

You give

MeaningUnitExample
\text{arrival\_rate}
Mean arrival rate lambda (per time unit)—20
\text{service\_rate}
Mean service rate mu of one server (per time unit)—6
\text{server\_cost\_rate}
Cost of one server per time unit—25
\text{waiting\_cost\_rate}
Cost of one customer in the system per time unit—40
\text{max\_servers}
Largest number of servers considered (default 50) optional—

You get

MeaningUnitExample
\text{servers}
Cost-minimising number of servers—5
\text{total\_cost}
c C_s + C_w L at that number—284.4668757
L
Mean number in system at that number—3.986671893

An optional input can be left out: a stated default is used.

Applies when

  • arrival_rate, service_rate > 0
  • costs >= 0
  • ties go to fewer servers

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Optimal number of servers with lambda = 20, service rate = 6, server cost = 25, waiting cost = 40.
servers = 5
total_cost = 284.4668757
L = 3.986671893

Run it

Terminal
$ industrial-engineering solve ie_queue_server_cost arrival_rate=20 service_rate=6 server_cost_rate=25 waiting_cost_rate=40
servers = 5
total_cost = 284.4668757
L = 3.986671893
  by: Cost-optimal number of servers  (for each stable c: L from Erlang C; total cost c C_s + C_w L; the smallest wins)
  arrival_rate = 20
  service_rate = 6
  server_cost_rate = 25
  waiting_cost_rate = 40
  assumes: arrival_rate, service_rate > 0; costs >= 0; ties go to fewer servers

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Little's law2 fig.ie_littles_law

L = lambda W: the average number in a system equals the arrival rate times the average time spent; give any two to get the third.

L = \lambda W

You give

MeaningUnitExample
\text{arrival\_rate}
Average arrival (throughput) rate optional—12
\text{number\_in\_system}
Average number in the system (WIP) optional—
\text{time\_in\_system}
Average time in the system (flow time) optional—0.5

You get

MeaningUnitExample
\text{arrival\_rate}
lambda—12
\text{number\_in\_system}
L = lambda W—6
\text{time\_in\_system}
W = L/lambda—0.5

An optional input can be left out: a stated default is used.

Applies when

  • exactly two of the three given
  • consistent time units
  • steady state

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Little's law with lambda = 12, average time in system = 0.5.
arrival_rate = 12
number_in_system = 6
time_in_system = 0.5

Run it

Terminal
$ industrial-engineering solve ie_littles_law arrival_rate=12 time_in_system=0.5
arrival_rate = 12
number_in_system = 6
time_in_system = 0.5
  by: Little's law  (L = lambda W)
  arrival_rate = 12
  time_in_system = 0.5
  assumes: exactly two of the three given; consistent time units; steady state

Figures

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

M/D/1 queue (constant service time)2 fig.ie_md1_queue

Mean queue length and waits of a single-server queue with Poisson arrivals and a constant service time.

L_q = \frac{\rho^2}{2(1-\rho)}

You give

MeaningUnitExample
\text{arrival\_rate}
Mean arrival rate lambda (per time unit)—2
\text{service\_rate}
Mean service rate mu of one server (per time unit)—3

You get

MeaningUnitExample
\text{utilization}
rho = lambda/mu—0.6666666667
\text{Lq}
Mean number waiting rho^2/(2(1 – rho))—0.6666666667
\text{Wq}
Mean wait in queue Lq/lambda—0.3333333333
W
Mean time in system Wq + 1/mu—0.6666666667
L
Mean number in system Lq + rho—1.333333333

Applies when

  • arrival_rate < service_rate
  • constant service time 1/mu

Outside these conditions it says what is wrong instead of returning a number.

Worked example

M/D/1 queue with lambda = 2, service rate = 3.
utilization = 0.6666666667
Lq = 0.6666666667
Wq = 0.3333333333
W = 0.6666666667
L = 1.333333333

Run it

Terminal
$ industrial-engineering solve ie_md1_queue arrival_rate=2 service_rate=3
utilization = 0.6666666667
Lq = 0.6666666667
Wq = 0.3333333333
W = 0.6666666667
L = 1.333333333
  by: M/D/1 queue (constant service time)  (Lq = rho^2 / (2 (1 - rho)), Wq = Lq/lambda)
  arrival_rate = 2
  service_rate = 3
  assumes: arrival_rate < service_rate; constant service time 1/mu

Figures

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

M/G/1 queue (Pollaczek-Khinchine)1 fig.ie_mg1_queue

Mean queue length and waits of a single-server queue with Poisson arrivals and a general service time of given mean and standard deviation.

L_q = \frac{\lambda^2\sigma^2 + \rho^2}{2(1-\rho)}

You give

MeaningUnitExample
\text{arrival\_rate}
Mean arrival rate lambda (per time unit)—0.5
\text{mean\_service\_time}
Mean service time E[S]—1.5
\text{sd\_service\_time}
Standard deviation of the service time—1

You get

MeaningUnitExample
\text{utilization}
rho = lambda E[S]—0.75
\text{Lq}
Lq = lambda^2 (sigma^2 + E[S]^2)/(2(1 – rho))—1.625
\text{Wq}
Mean wait in queue—3.25
W
Mean time in system—4.75
L
Mean number in system—2.375

Applies when

  • lambda E[S] < 1
  • sd_service_time >= 0

Outside these conditions it says what is wrong instead of returning a number.

Worked example

M/G/1 queue with lambda = 0.5, mean service time = 1.5, standard deviation of service time = 1.
utilization = 0.75
Lq = 1.625
Wq = 3.25
W = 4.75
L = 2.375

Run it

Terminal
$ industrial-engineering solve ie_mg1_queue arrival_rate=0.5 mean_service_time=1.5 sd_service_time=1
utilization = 0.75
Lq = 1.625
Wq = 3.25
W = 4.75
L = 2.375
  by: M/G/1 queue (Pollaczek-Khinchine)  (Pollaczek-Khinchine: Lq = (lambda^2 sigma^2 + rho^2)/(2(1 - rho)), Wq = Lq/lambda, W = Wq + E[S])
  arrival_rate = 0.5
  mean_service_time = 1.5
  sd_service_time = 1
  assumes: lambda E[S] < 1; sd_service_time >= 0

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

M/M/1 queue2 fig.ie_mm1_queue

Utilisation, mean numbers in system and in queue, and mean times of a single-server queue with Poisson arrivals and exponential service.

\rho = \frac{\lambda}{\mu},\ L = \frac{\rho}{1-\rho},\ W = \frac{1}{\mu-\lambda},\ L_q = \frac{\rho^2}{1-\rho}

You give

MeaningUnitExample
\text{arrival\_rate}
Mean arrival rate lambda (per time unit)—2
\text{service\_rate}
Mean service rate mu of one server (per time unit)—3

You get

MeaningUnitExample
\text{utilization}
rho = lambda/mu—0.6666666667
L
Mean number in system rho/(1 – rho)—2
\text{Lq}
Mean number waiting rho^2/(1 – rho)—1.333333333
W
Mean time in system 1/(mu – lambda)—1
\text{Wq}
Mean wait in queue rho/(mu – lambda)—0.6666666667
\text{p0}
Probability the system is empty—0.3333333333

Applies when

  • arrival_rate < service_rate
  • Poisson arrivals, exponential service, FCFS, infinite queue

Outside these conditions it says what is wrong instead of returning a number.

Worked example

M/M/1 queue with lambda = 2, service rate = 3.
utilization = 0.6666666667
L = 2
Lq = 1.333333333
W = 1
Wq = 0.6666666667
p0 = 0.3333333333

Run it

Terminal
$ industrial-engineering solve ie_mm1_queue arrival_rate=2 service_rate=3
utilization = 0.6666666667
L = 2
Lq = 1.333333333
W = 1
Wq = 0.6666666667
p0 = 0.3333333333
  by: M/M/1 queue  (rho = lambda/mu, L = rho/(1 - rho), W = 1/(mu - lambda), Lq = rho L, Wq = rho W)
  arrival_rate = 2
  service_rate = 3
  assumes: arrival_rate < service_rate; Poisson arrivals, exponential service, FCFS, infinite queue

Figures

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

M/M/1/K queue (finite capacity)1 fig.ie_mm1k_queue

Single-server queue with room for at most K customers in the system: blocking probability, effective arrival rate, mean numbers and times.

P_n = \frac{\rho^n}{\sum_{k=0}^{K}\rho^k},\quad \lambda_{eff} = \lambda(1-P_K)

You give

MeaningUnitExample
\text{arrival\_rate}
Mean arrival rate lambda (per time unit)—4
\text{service\_rate}
Mean service rate mu of one server (per time unit)—5
\text{capacity}
Maximum customers in the system K (including the one in service)—3

You get

MeaningUnitExample
\text{p0}
Probability empty—0.3387533875
p_{\mathrm{block}}
Probability an arrival is turned away P_K—0.1734417344
L
Mean number in system—1.224932249
\text{Lq}
Mean number waiting—0.5636856369
\text{effective\_arrival\_rate}
lambda (1 – P_K)—3.306233062
W
Mean time in system L/lambda_eff—0.3704918033
\text{Wq}
Mean wait Lq/lambda_eff—0.1704918033
\text{utilization}
1 – P0—0.6612466125

Applies when

  • arrival_rate, service_rate > 0 (rho may exceed 1)
  • 1 <= capacity <= 1000

Outside these conditions it says what is wrong instead of returning a number.

Worked example

M/M/1/K queue with lambda = 4, service rate = 5, system capacity = 3.
p0 = 0.3387533875
p_block = 0.1734417344
L = 1.224932249
Lq = 0.5636856369
effective_arrival_rate = 3.306233062
W = 0.3704918033

Run it

Terminal
$ industrial-engineering solve ie_mm1k_queue arrival_rate=4 service_rate=5 capacity=3
p0 = 0.3387533875
p_block = 0.1734417344
L = 1.224932249
Lq = 0.5636856369
effective_arrival_rate = 3.306233062
W = 0.3704918033
Wq = 0.1704918033
utilization = 0.6612466125
  by: M/M/1/K queue (finite capacity)  (P_n = rho^n / sum_{k=0}^{K} rho^k; lambda_eff = lambda (1 - P_K); Little's law)
  arrival_rate = 4
  service_rate = 5
  assumes: arrival_rate, service_rate > 0 (rho may exceed 1); 1 <= capacity <= 1000

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

M/M/c queue (Erlang C)2 fig.ie_mmc_queue

Probability of waiting (Erlang C), mean queue length and mean waits of a multi-server queue with Poisson arrivals and exponential service.

C(c,a) = \frac{\frac{a^c}{c!(1-\rho)}}{\sum_{k=0}^{c-1}\frac{a^k}{k!} + \frac{a^c}{c!(1-\rho)}},\quad L_q = C\frac{\rho}{1-\rho}

You give

MeaningUnitExample
\text{arrival\_rate}
Mean arrival rate lambda (per time unit)—10
\text{service\_rate}
Mean service rate mu of one server (per time unit)—4
\text{servers}
Number of servers c—3

You get

MeaningUnitExample
\text{utilization}
rho = lambda/(c mu)—0.8333333333
p_{\mathrm{wait}}
Erlang C probability of waiting—0.702247191
\text{Lq}
Mean number waiting—3.511235955
\text{Wq}
Mean wait in queue—0.3511235955
W
Mean time in system—0.6011235955
L
Mean number in system—6.011235955
\text{p0}
Probability the system is empty—0.04494382022

Applies when

  • arrival_rate < servers x service_rate
  • 1 <= servers <= 500

Outside these conditions it says what is wrong instead of returning a number.

Worked example

M/M/c queue with lambda = 10, service rate = 4, number of servers = 3.
utilization = 0.8333333333
p_wait = 0.702247191
Lq = 3.511235955
Wq = 0.3511235955
W = 0.6011235955
L = 6.011235955

Run it

Terminal
$ industrial-engineering solve ie_mmc_queue arrival_rate=10 service_rate=4 servers=3
utilization = 0.8333333333
p_wait = 0.702247191
Lq = 3.511235955
Wq = 0.3511235955
W = 0.6011235955
L = 6.011235955
p0 = 0.04494382022
  by: M/M/c queue (Erlang C)  (a = lambda/mu, P0 = [sum_{k<c} a^k/k! + a^c/(c!(1-rho))]^-1, C = a^c P0/(c!(1-rho)), Lq = C rho/(1-rho))
  arrival_rate = 10
  service_rate = 4
  assumes: arrival_rate < servers x service_rate; 1 <= servers <= 500

Figures

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Servers needed for a service level (Erlang C)1 fig.ie_erlang_c_staffing

Fewest servers of an M/M/c queue such that the probability of waiting no longer than a target time reaches a target service level (call-centre staffing).

P(W_q \le t) = 1 – C(c,a)\,e^{-(c\mu-\lambda)t}

You give

MeaningUnitExample
\text{arrival\_rate}
Mean arrival rate lambda (per time unit)—100
\text{service\_rate}
Mean service rate mu of one server (per time unit)—12
\text{target\_time}
Target answer time in the same time unit—0.0333
\text{target\_level}
Required fraction answered within the target time (decimal)—0.8

You get

MeaningUnitExample
\text{servers}
Fewest servers meeting the target—11
\text{service\_level}
P(wait <= t) achieved—0.8967748179
p_{\mathrm{wait}}
Erlang C probability of waiting—0.29961935
\text{utilization}
lambda/(c mu)—0.7575757576
\text{mean\_wait}
Mean wait in queue—0.009363104689

Applies when

  • arrival_rate, service_rate > 0
  • target_time >= 0
  • 0 < target_level < 1

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Servers needed for a service level with lambda = 100, service rate = 12, answer time = 0.0333, service level target = 0.8.
servers = 11
service_level = 0.8967748179
p_wait = 0.29961935
utilization = 0.7575757576
mean_wait = 0.009363104689

Run it

Terminal
$ industrial-engineering solve ie_erlang_c_staffing arrival_rate=100 service_rate=12 target_time=0.0333 target_level=0.8
servers = 11
service_level = 0.8967748179
p_wait = 0.29961935
utilization = 0.7575757576
mean_wait = 0.009363104689
  by: Servers needed for a service level (Erlang C)  (smallest c > lambda/mu with 1 - C(c, a) exp(-(c mu - lambda) t) >= target)
  arrival_rate = 100
  service_rate = 12
  target_time = 0.0333
  target_level = 0.8
  assumes: arrival_rate, service_rate > 0; target_time >= 0; 0 < target_level < 1

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Reliability 13

Cold standby redundancy2 fig.ie_standby_redundancy

Reliability and MTTF of one operating unit backed by identical cold standby units with perfect switching.

R(t) = e^{-\lambda t}\sum_{k=0}^{n-1}\frac{(\lambda t)^k}{k!}

You give

MeaningUnitExample
\text{failure\_rate}
Failure rate lambda of each unit—0.001
\text{time}
Mission time—1000
\text{units}
Total units including the operating one (default 2) optional—

You get

MeaningUnitExample
\text{reliability}
exp(-lambda t) sum_{k<n} (lambda t)^k / k!—0.7357588823
\text{mttf}
n/lambda—2000

An optional input can be left out: a stated default is used.

Applies when

  • failure_rate > 0
  • time >= 0
  • 1 <= units <= 200
  • standby units do not fail, switching is perfect

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Cold standby redundancy with lambda = 0.001, mission time = 1000.
reliability = 0.7357588823
mttf = 2000

Run it

Terminal
$ industrial-engineering solve ie_standby_redundancy failure_rate=0.001 time=1000
reliability = 0.7357588823
mttf = 2000
  by: Cold standby redundancy  (R(t) = e^(-lambda t) sum_{k=0}^{n-1} (lambda t)^k/k!)
  failure_rate = 0.001
  time = 1000
  assumes: failure_rate > 0; time >= 0; 1 <= units <= 200; standby units do not fail, switching is perfect

Figures

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Confidence bounds on MTBF (chi-square)1 fig.ie_mtbf_confidence

Point estimate and chi-square confidence bounds of the MTBF from a life test with constant failure rate.

MTBF_L = \frac{2T}{\chi^2_{C,\,2r+2}},\quad MTBF_U = \frac{2T}{\chi^2_{\alpha/2,\,2r}}

You give

MeaningUnitExample
\text{total\_time}
Total accumulated test time (all units)—10000
\text{failures}
Number of failures observed—4
\text{confidence}
Confidence level (decimal)—0.9
\text{test}
Time (test stopped at a set time) or failure (stopped at the r-th failure); default time optional choice—time

You get

MeaningUnitExample
\text{mtbf}
Point estimate T/r—2500
\text{lower\_one\_sided}
One-sided lower bound 2T/chi2(C; d)—1251.00243
\text{lower\_two\_sided}
Two-sided lower bound—1092.476016
\text{upper\_two\_sided}
Two-sided upper bound 2T/chi2(a/2; 2r)—7318.938268

An optional input can be left out: a stated default is used.

Applies when

  • total_time > 0
  • failures >= 1
  • 0 < confidence < 1
  • d = 2r + 2 for a time-terminated test, 2r for a failure-terminated test

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Confidence bounds on MTBF with total test time = 10000, number of failures = 4, confidence level = 0.9, test type = time.
mtbf = 2500
lower_one_sided = 1251.00243
lower_two_sided = 1092.476016
upper_two_sided = 7318.938268

Run it

Terminal
$ industrial-engineering solve ie_mtbf_confidence total_time=10000 failures=4 confidence=0.9 test=time
mtbf = 2500
lower_one_sided = 1251.00243
lower_two_sided = 1092.476016
upper_two_sided = 7318.938268
  by: Confidence bounds on MTBF (chi-square)  (MTBF_L = 2T / chi2_{C, d}; two-sided: 2T/chi2_{1-a/2, d} and 2T/chi2_{a/2, 2r})
  total_time = 10000
  confidence = 0.9
  test = time
  assumes: total_time > 0; failures >= 1; 0 < confidence < 1; d = 2r + 2 for a time-terminated test, 2r for a failure-terminated test

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Exponential (constant failure rate) reliability2 fig.ie_exponential_reliability

Probability of surviving a mission time with a constant failure rate: R(t) = exp(-lambda t), MTBF = 1/lambda.

R(t) = e^{-\lambda t},\quad MTBF = \frac{1}{\lambda}

You give

MeaningUnitExample
\text{failure\_rate}
Constant failure rate lambda (failures per time unit)—0.0002
\text{time}
Mission time in the same time unit—1000

You get

MeaningUnitExample
\text{reliability}
R(t) = exp(-lambda t)—0.8187307531
\text{unreliability}
F(t) = 1 – R(t)—0.1812692469
\text{mtbf}
Mean time between failures 1/lambda—5000
\text{hazard\_rate}
lambda—0.0002

Applies when

  • failure_rate > 0
  • time >= 0

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Exponential reliability with lambda = 0.0002, mission time = 1000.
reliability = 0.8187307531
unreliability = 0.1812692469
mtbf = 5000
hazard_rate = 0.0002

Run it

Terminal
$ industrial-engineering solve ie_exponential_reliability failure_rate=0.0002 time=1000
reliability = 0.8187307531
unreliability = 0.1812692469
mtbf = 5000
hazard_rate = 0.0002
  by: Exponential (constant failure rate) reliability  (R = exp(-lambda t))
  failure_rate = 0.0002
  time = 1000
  assumes: failure_rate > 0; time >= 0

Figures

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Failure rate and MTBF of a series system1 fig.ie_system_failure_rate

Failure rate, MTBF and mission reliability of a series system of components with constant failure rates.

\lambda_s = \sum_i \lambda_i,\quad MTBF_s = \frac{1}{\lambda_s}

You give

MeaningUnitExample
\text{failure\_rates}
Constant failure rate of each component (per hour, say) vector—[0.0001, 0.0002, 5e-05]
\text{time}
Mission time (optional) optional—1000

You get

MeaningUnitExample
\text{system\_failure\_rate}
Sum of lambda_i—0.00035
\text{mtbf}
1 / sum lambda_i—2857.142857
\text{reliability}
exp(-sum lambda_i t) (when a time is given)—0.7046880897

An optional input can be left out: a stated default is used.

Applies when

  • failure rates > 0
  • time >= 0
  • series system, constant failure rates

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Failure rate of a series system with component failure rates = [0.0001, 0.0002, 5e-05], mission time = 1000.
system_failure_rate = 0.00035
mtbf = 2857.142857
reliability = 0.7046880897

Run it

Terminal
$ industrial-engineering solve ie_system_failure_rate "failure_rates=[0.0001, 0.0002, 5e-05]" time=1000
system_failure_rate = 0.00035
mtbf = 2857.142857
reliability = 0.7046880897
  by: Failure rate and MTBF of a series system  (lambda_s = sum lambda_i, MTBF = 1/lambda_s, R(t) = exp(-lambda_s t))
  time = 1000
  assumes: failure rates > 0; time >= 0; series system, constant failure rates

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Inherent availability from MTBF and MTTR2 fig.ie_availability

Long-run fraction of time a repairable system is up, A = MTBF / (MTBF + MTTR), and the downtime it implies.

A = \frac{MTBF}{MTBF + MTTR}

You give

MeaningUnitExample
\text{mtbf}
Mean time between failures (hours)—500
\text{mttr}
Mean time to repair (hours)—20
\text{hours\_per\_year}
Operating hours in a year (default 8760) optional—

You get

MeaningUnitExample
\text{availability}
MTBF/(MTBF + MTTR)—0.9615384615
\text{unavailability}
MTTR/(MTBF + MTTR)—0.03846153846
\text{downtime\_per\_year}
Expected downtime hours per year—336.9230769
\text{failure\_rate}
1/MTBF—0.002
\text{repair\_rate}
1/MTTR—0.05

An optional input can be left out: a stated default is used.

Applies when

  • mtbf, mttr > 0

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Inherent availability with mean time between failures = 500, mean time to repair = 20.
availability = 0.9615384615
unavailability = 0.03846153846
downtime_per_year = 336.9230769
failure_rate = 0.002
repair_rate = 0.05

Run it

Terminal
$ industrial-engineering solve ie_availability mtbf=500 mttr=20
availability = 0.9615384615
unavailability = 0.03846153846
downtime_per_year = 336.9230769
failure_rate = 0.002
repair_rate = 0.05
  by: Inherent availability from MTBF and MTTR  (A = MTBF/(MTBF + MTTR))
  mtbf = 500
  mttr = 20
  assumes: mtbf, mttr > 0

Figures

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

k-out-of-n system reliability1 fig.ie_k_out_of_n_reliability

Reliability of a system of n identical independent components that works when at least k of them work.

R = \sum_{j=k}^{n}\binom{n}{j}r^j(1-r)^{n-j}

You give

MeaningUnitExample
\text{component\_reliability}
Reliability of each component—0.9
k
Components needed—2
n
Components installed—3

You get

MeaningUnitExample
\text{reliability}
P(at least k of n work)—0.972
\text{unreliability}
1 – reliability—0.028

Applies when

  • 0 <= r <= 1
  • 1 <= k <= n <= 1000
  • identical independent components

Outside these conditions it says what is wrong instead of returning a number.

Worked example

K-out-of-n system reliability with component reliability = 0.9, required components = 2, total components = 3.
reliability = 0.972
unreliability = 0.028

Run it

Terminal
$ industrial-engineering solve ie_k_out_of_n_reliability component_reliability=0.9 k=2 n=3
reliability = 0.972
unreliability = 0.028
  by: k-out-of-n system reliability  (R = sum_{j=k}^{n} C(n, j) r^j (1 - r)^(n - j))
  component_reliability = 0.9
  assumes: 0 <= r <= 1; 1 <= k <= n <= 1000; identical independent components

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

MTTF of identical components in parallel2 fig.ie_parallel_mttf

Mean time to failure of n identical exponential components in active parallel: (1/lambda) sum 1/i.

MTTF = \frac{1}{\lambda}\sum_{i=1}^{n}\frac{1}{i}

You give

MeaningUnitExample
\text{failure\_rate}
Failure rate lambda of each component—0.001
n
Number of components in parallel—2

You get

MeaningUnitExample
\text{mttf}
System MTTF (1/lambda) sum_{i=1}^{n} 1/i—1500
\text{single\_mttf}
1/lambda—1000
\text{improvement\_factor}
sum 1/i—1.5

Applies when

  • failure_rate > 0
  • 1 <= n <= 1000
  • active redundancy, constant failure rate

Outside these conditions it says what is wrong instead of returning a number.

Worked example

MTTF of a parallel system with lambda = 0.001, components = 2.
mttf = 1500
single_mttf = 1000
improvement_factor = 1.5

Run it

Terminal
$ industrial-engineering solve ie_parallel_mttf failure_rate=0.001 n=2
mttf = 1500
single_mttf = 1000
improvement_factor = 1.5
  by: MTTF of identical components in parallel  (MTTF = integral of 1 - (1 - e^(-lambda t))^n dt = (1/lambda) sum 1/i)
  failure_rate = 0.001
  assumes: failure_rate > 0; 1 <= n <= 1000; active redundancy, constant failure rate

Figures

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Parallel components needed for a target reliability2 fig.ie_redundancy_needed

Smallest number of identical components in parallel that reaches a target system reliability.

m = \left\lceil \frac{\ln(1-R_{target})}{\ln(1-r)} \right\rceil

You give

MeaningUnitExample
\text{target\_reliability}
Required system reliability—0.999
\text{component\_reliability}
Reliability of one component—0.9

You get

MeaningUnitExample
\text{components}
Smallest m with 1 – (1 – r)^m ≥ target—3
\text{achieved\_reliability}
Reliability with m components—0.999

Applies when

  • 0 < target < 1
  • 0 < r < 1
  • active parallel redundancy

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Parallel components needed with required reliability = 0.999, component reliability = 0.9.
components = 3
achieved_reliability = 0.999

Run it

Terminal
$ industrial-engineering solve ie_redundancy_needed target_reliability=0.999 component_reliability=0.9
components = 3
achieved_reliability = 0.999
  by: Parallel components needed for a target reliability  (smallest m with 1 - (1 - r)^m >= R_target (m = ceil(ln(1 - R)/ln(1 - r))))
  target_reliability = 0.999
  component_reliability = 0.9
  assumes: 0 < target < 1; 0 < r < 1; active parallel redundancy

Figures

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Reliability of components in parallel1 fig.ie_parallel_reliability

Reliability of a redundant system that works if at least one component works (independent components).

R_p = 1 – \prod_{i=1}^{n}(1 – R_i)

You give

MeaningUnitExample
\text{reliabilities}
Reliability of each component (decimals) vector—[0.9, 0.8]

You get

MeaningUnitExample
\text{reliability}
1 – product (1 – R_i)—0.98
\text{unreliability}
Product (1 – R_i)—0.02

Applies when

  • each reliability in [0, 1]
  • independent failures
  • active redundancy

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Parallel system reliability with component reliabilities = [0.9, 0.8].
reliability = 0.98
unreliability = 0.02

Run it

Terminal
$ industrial-engineering solve ie_parallel_reliability "reliabilities=[0.9, 0.8]"
reliability = 0.98
unreliability = 0.02
  by: Reliability of components in parallel  (R = 1 - product (1 - R_i))
  assumes: each reliability in [0, 1]; independent failures; active redundancy

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Reliability of components in series1 fig.ie_series_reliability

Reliability of a system that works only if every component works (independent components).

R_s = \prod_{i=1}^{n} R_i

You give

MeaningUnitExample
\text{reliabilities}
Reliability of each component (decimals) vector—[0.95, 0.98, 0.99]

You get

MeaningUnitExample
\text{reliability}
System reliability product of R_i—0.92169
\text{unreliability}
1 – system reliability—0.07831

Applies when

  • each reliability in [0, 1]
  • independent failures

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Series system reliability with component reliabilities = [0.95, 0.98, 0.99].
reliability = 0.92169
unreliability = 0.07831

Run it

Terminal
$ industrial-engineering solve ie_series_reliability "reliabilities=[0.95, 0.98, 0.99]"
reliability = 0.92169
unreliability = 0.07831
  by: Reliability of components in series  (R = product R_i)
  assumes: each reliability in [0, 1]; independent failures

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Series system of parallel stages1 fig.ie_series_parallel_reliability

Reliability of stages in series where each stage has redundant components in parallel (each row of the matrix is one stage).

R = \prod_i\Big[1 – \prod_j (1 – r_{ij})\Big]

You give

MeaningUnitExample
\text{stage\_reliabilities}
Matrix: one row per stage, the reliabilities of its parallel components matrix—[0.9 0.9; 0.8 0.8; 0.95 0.95]

You get

MeaningUnitExample
\text{reliability}
Product over stages of 1 – product (1 – r)—0.948024
\text{unreliability}
1 – reliability—0.051976

Applies when

  • every value in [0, 1]
  • independent components
  • rows of equal length

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Series-parallel system reliability with stages = [[0.9, 0.9], [0.8, 0.8], [0.95, 0.95]].
reliability = 0.948024
unreliability = 0.051976

Run it

Terminal
$ industrial-engineering solve ie_series_parallel_reliability "stage_reliabilities=[[0.9, 0.9], [0.8, 0.8], [0.95, 0.95]]"
reliability = 0.948024
unreliability = 0.051976
  by: Series system of parallel stages  (R = prod_i [1 - prod_j (1 - r_ij)])
  assumes: every value in [0, 1]; independent components; rows of equal length

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Weibull fit by median-rank regression1 fig.ie_weibull_median_rank_regression

Weibull shape and scale estimated from complete failure times by regression on Bernard's median ranks (Weibull probability plot).

\ln\ln\frac{1}{1-F_i} = \beta\ln t_{(i)} – \beta\ln\eta,\quad F_i = \frac{i-0.3}{n+0.4}

You give

MeaningUnitExample
\text{failure\_times}
Failure times (complete data, any order) vector—[16, 34, 53, 75, 93, 120]

You get

MeaningUnitExample
\text{shape}
Shape beta (slope of ln ln(1/(1-F)) on ln t)—1.426967111
\text{scale}
Scale eta—76.34541546
r_{\mathrm{squared}}
Coefficient of determination of the plot—0.9911811558

Applies when

  • at least 3 positive failure times, not all equal
  • complete (uncensored) data

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Weibull fit by median rank regression with failure times = [16, 34, 53, 75, 93, 120].
shape = 1.426967111
scale = 76.34541546
r_squared = 0.9911811558

Run it

Terminal
$ industrial-engineering solve ie_weibull_median_rank_regression "failure_times=[16, 34, 53, 75, 93, 120]"
shape = 1.426967111
scale = 76.34541546
r_squared = 0.9911811558
  by: Weibull fit by median-rank regression  (F_i = (i - 0.3)/(n + 0.4); regress y = ln(-ln(1 - F_i)) on x = ln t_(i); beta = slope, eta = exp(-intercept/beta))
  assumes: at least 3 positive failure times, not all equal; complete (uncensored) data

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Weibull reliability, hazard and MTTF1 fig.ie_weibull_reliability

Reliability, hazard rate, mean life and B10 life of a Weibull life distribution (shape beta, scale eta, optional location gamma).

R(t) = \exp\!\left[-\left(\frac{t-\gamma}{\eta}\right)^{\beta}\right],\quad MTTF = \gamma + \eta\,\Gamma(1+1/\beta)

You give

MeaningUnitExample
\text{shape}
Shape parameter beta—2
\text{scale}
Scale parameter eta (characteristic life)—1000
\text{time}
Time t—500
\text{location}
Location gamma, failure-free time (default 0) optional—

You get

MeaningUnitExample
\text{reliability}
R(t) = exp(-((t – gamma)/eta)^beta)—0.7788007831
\text{unreliability}
1 – R(t)—0.2211992169
\text{hazard\_rate}
h(t) = beta/eta ((t – gamma)/eta)^(beta – 1)—0.001
\text{mttf}
gamma + eta Gamma(1 + 1/beta)—886.2269255
\text{b10\_life}
Time by which 10 % have failed—324.592846

An optional input can be left out: a stated default is used.

Applies when

  • shape, scale > 0
  • location >= 0
  • time >= location

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Weibull reliability with beta = 2, scale parameter = 1000, mission time = 500.
reliability = 0.7788007831
unreliability = 0.2211992169
hazard_rate = 0.001
mttf = 886.2269255
b10_life = 324.592846

Run it

Terminal
$ industrial-engineering solve ie_weibull_reliability shape=2 scale=1000 time=500
reliability = 0.7788007831
unreliability = 0.2211992169
hazard_rate = 0.001
mttf = 886.2269255
b10_life = 324.592846
  by: Weibull reliability, hazard and MTTF  (R = exp(-((t-g)/eta)^b); MTTF = g + eta Gamma(1 + 1/b); B10 = g + eta (-ln 0.9)^(1/b))
  shape = 2
  scale = 1000
  time = 500
  assumes: shape, scale > 0; location >= 0; time >= location

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Scheduling 7

Earliest due date (EDD) sequence1 fig.ie_edd_sequence

Order jobs on one machine by earliest due date (minimises the maximum lateness) and report tardiness measures.

d_{[1]} \le d_{[2]} \le \dots,\quad L_{max} = \max_k (C_{[k]} – d_{[k]})

You give

MeaningUnitExample
\text{processing\_times}
Processing time of each job (jobs numbered 1, 2, … in this order) vector—[4, 7, 2, 5]
\text{due\_dates}
Due date of each job (same order) vector—[10, 15, 5, 12]

You get

MeaningUnitExample
\text{sequence}
Job numbers in processing order—[3, 1, 4, 2]
\text{mean\_flow\_time}
Average completion (flow) time—9.25
\text{makespan}
Completion time of the last job—18
\text{average\_jobs\_in\_system}
Sum of completion times / makespan—2.055555556
\text{utilization}
Sum of processing times / sum of completion times—0.4864864865
\text{total\_tardiness}
Sum of tardiness—3
\text{mean\_tardiness}
Average tardiness (job lateness)—0.75
\text{max\_tardiness}
Largest tardiness—3
\text{max\_lateness}
Largest lateness C – d—3
\text{tardy\_jobs}
Number of late jobs—1

Applies when

  • processing times > 0
  • due dates >= 0
  • ties go to the lower job number

Outside these conditions it says what is wrong instead of returning a number.

Worked example

EDD sequence with processing times = [4, 7, 2, 5], due dates = [10, 15, 5, 12].
sequence = [3, 1, 4, 2]
mean_flow_time = 9.25
makespan = 18
average_jobs_in_system = 2.055555556
utilization = 0.4864864865
total_tardiness = 3

Run it

Terminal
$ industrial-engineering solve ie_edd_sequence "processing_times=[4, 7, 2, 5]" "due_dates=[10, 15, 5, 12]"
sequence = [3,1,4,2]
mean_flow_time = 9.25
makespan = 18
average_jobs_in_system = 2.055555556
utilization = 0.4864864865
total_tardiness = 3
mean_tardiness = 0.75
max_tardiness = 3
max_lateness = 3
tardy_jobs = 1
  by: Earliest due date (EDD) sequence  (sort by due date; lateness C - d; tardiness max(0, C - d))
  assumes: processing times > 0; due dates >= 0; ties go to the lower job number

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Johnson's rule (two machines)2 fig.ie_johnson_two_machine

Sequence jobs through two machines in the same order so that the makespan is minimal (Johnson's rule).

\min(a_{1i}, a_{2j}) \le \min(a_{1j}, a_{2i}) \Rightarrow i \text{ before } j

You give

MeaningUnitExample
\text{machine1\_times}
Time of each job on machine 1 (first) vector—[5, 2, 1, 7, 6]
\text{machine2\_times}
Time of each job on machine 2 (second) vector—[2, 6, 2, 5, 3]

You get

MeaningUnitExample
\text{sequence}
Job order—[3, 2, 4, 5, 1]
\text{makespan}
Time all jobs finish on machine 2—23
\text{idle\_time\_machine2}
Idle time of machine 2 (makespan – its work)—5

Applies when

  • times >= 0
  • jobs with a1 <= a2 go first by increasing a1, the others last by decreasing a2; ties by the lower job number

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Johnson's rule with machine 1 times = [5, 2, 1, 7, 6], machine 2 times = [2, 6, 2, 5, 3].
sequence = [3, 2, 4, 5, 1]
makespan = 23
idle_time_machine2 = 5

Run it

Terminal
$ industrial-engineering solve ie_johnson_two_machine "machine1_times=[5, 2, 1, 7, 6]" "machine2_times=[2, 6, 2, 5, 3]"
sequence = [3,2,4,5,1]
makespan = 23
idle_time_machine2 = 5
  by: Johnson's rule (two machines)  (Johnson: front set (a1 <= a2) by a1 ascending, back set by a2 descending)
  assumes: times >= 0; jobs with a1 <= a2 go first by increasing a1, the others last by decreasing a2; ties by the lower job number

Figures

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Johnson's rule extended to three machines1 fig.ie_johnson_three_machine

Optimal job order through three machines when machine 2 is dominated (Johnson's extension with pseudo times a1 + a2 and a2 + a3).

a_i' = a_{1i} + a_{2i},\quad a_i'' = a_{2i} + a_{3i}

You give

MeaningUnitExample
\text{machine1\_times}
Time of each job on machine 1 vector—[8, 10, 6, 7, 11]
\text{machine2\_times}
Time of each job on machine 2 vector—[5, 6, 2, 3, 4]
\text{machine3\_times}
Time of each job on machine 3 vector—[4, 9, 8, 6, 5]

You get

MeaningUnitExample
\text{sequence}
Job order—[3, 2, 1, 4, 5]
\text{makespan}
Time all jobs finish on machine 3—51

Applies when

  • min(machine 1) >= max(machine 2) or min(machine 3) >= max(machine 2) (else refused)
  • ties by the lower job number

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Johnson's rule for three machines with machine 1 times = [8, 10, 6, 7, 11], machine 2 times = [5, 6, 2, 3, 4], machine 3 times = [4, 9, 8, 6, 5].
sequence = [3, 2, 1, 4, 5]
makespan = 51

Run it

Terminal
$ industrial-engineering solve ie_johnson_three_machine "machine1_times=[8, 10, 6, 7, 11]" "machine2_times=[5, 6, 2, 3, 4]" "machine3_times=[4, 9, 8, 6, 5]"
sequence = [3,2,1,4,5]
makespan = 51
  by: Johnson's rule extended to three machines  (Johnson's rule on pseudo machines (a1 + a2, a2 + a3); makespan by the three-machine recursion)
  assumes: min(machine 1) >= max(machine 2) or min(machine 3) >= max(machine 2) (else refused); ties by the lower job number

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Minimise the number of late jobs (Moore-Hodgson)1 fig.ie_moore_hodgson

Sequence on one machine that minimises the number of late jobs: on-time jobs in EDD order, then the late ones (Moore-Hodgson algorithm).

\min \sum_j U_j,\quad U_j = [C_j > d_j]

You give

MeaningUnitExample
\text{processing\_times}
Processing time of each job (jobs numbered 1, 2, … in this order) vector—[4, 3, 2, 5, 6]
\text{due\_dates}
Due date of each job (same order) vector—[5, 6, 8, 10, 12]

You get

MeaningUnitExample
\text{number\_late}
Least possible number of late jobs—2
\text{late\_jobs}
The jobs scheduled late—[1, 5]
\text{on\_time\_jobs}
The on-time jobs in processing (EDD) order—[2, 3, 4]
\text{sequence}
Full sequence—[2, 3, 4, 1, 5]

Applies when

  • processing times > 0
  • due dates >= 0
  • when a job is late, the longest scheduled job is removed (ties: the lower job number)

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Moore-Hodgson with processing times = [4, 3, 2, 5, 6], due dates = [5, 6, 8, 10, 12].
number_late = 2
late_jobs = [1, 5]
on_time_jobs = [2, 3, 4]
sequence = [2, 3, 4, 1, 5]

Run it

Terminal
$ industrial-engineering solve ie_moore_hodgson "processing_times=[4, 3, 2, 5, 6]" "due_dates=[5, 6, 8, 10, 12]"
number_late = 2
late_jobs = [1,5]
on_time_jobs = [2,3,4]
sequence = [2,3,4,1,5]
  by: Minimise the number of late jobs (Moore-Hodgson)  (add jobs in EDD order; whenever the current job finishes late, drop the longest job scheduled so far)
  assumes: processing times > 0; due dates >= 0; when a job is late, the longest scheduled job is removed (ties: the lower job number)

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Permutation flow shop makespan2 fig.ie_flow_shop_makespan

Makespan and completion times of jobs processed in a given order through machines in series (each row a job in processing order, each column a machine).

C_{i,j} = \max(C_{i-1,j},\,C_{i,j-1}) + t_{i,j}

You give

MeaningUnitExample
\text{times}
Matrix: row = job (in processing order), column = machine (in route order) matrix—[5 3 6; 2 7 4; 4 2 5; 6 4 3]

You get

MeaningUnitExample
\text{makespan}
Completion time of the last job on the last machine—27
\text{completion\_times}
Completion time of each job on the last machine—[14, 19, 24, 27]
\text{idle\_time\_last\_machine}
Idle time of the last machine—9

Applies when

  • times >= 0
  • the same job order on every machine, no passing

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Flow shop makespan with processing time matrix = [[5, 3, 6], [2, 7, 4], [4, 2, 5], [6, 4, 3]].
makespan = 27
completion_times = [14, 19, 24, 27]
idle_time_last_machine = 9

Run it

Terminal
$ industrial-engineering solve ie_flow_shop_makespan "times=[[5, 3, 6], [2, 7, 4], [4, 2, 5], [6, 4, 3]]"
makespan = 27
completion_times = [14.0,19.0,24.0,27.0]
idle_time_last_machine = 9
  by: Permutation flow shop makespan  (C(i, j) = max(C(i-1, j), C(i, j-1)) + t(i, j))
  assumes: times >= 0; the same job order on every machine, no passing

Figures

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Sequencing by a dispatching rule (FCFS, SPT, LPT, EDD, CR)1 fig.ie_dispatching_rule

Sequence jobs at one work centre by a priority rule and compare average completion time, utilisation, average number of jobs and tardiness.

\bar F = \frac{\sum C_j}{n},\quad \text{utilization} = \frac{\sum p_j}{\sum C_j},\quad \bar N = \frac{\sum C_j}{C_{max}}

You give

MeaningUnitExample
\text{processing\_times}
Processing time of each job (jobs numbered 1, 2, … in this order) vector—[6, 2, 8, 3, 9]
\text{due\_dates}
Due date of each job (same order) vector—[8, 6, 18, 15, 23]
\text{rule}
Fcfs (given order), spt, lpt (longest first), edd or cr (critical ratio due date / processing time at time 0, smallest first) choice—fcfs

You get

MeaningUnitExample
\text{sequence}
Job numbers in processing order—[1, 2, 3, 4, 5]
\text{mean\_flow\_time}
Average completion (flow) time—15.4
\text{makespan}
Completion time of the last job—28
\text{average\_jobs\_in\_system}
Sum of completion times / makespan—2.75
\text{utilization}
Sum of processing times / sum of completion times—0.3636363636
\text{total\_tardiness}
Sum of tardiness—11
\text{mean\_tardiness}
Average tardiness (job lateness)—2.2
\text{max\_tardiness}
Largest tardiness—5
\text{max\_lateness}
Largest lateness C – d—5
\text{tardy\_jobs}
Number of late jobs—3

Applies when

  • processing times > 0
  • due dates >= 0
  • ties go to the lower job number
  • jobs available at time 0

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Sequence by dispatching rule with processing times = [6, 2, 8, 3, 9], due dates = [8, 6, 18, 15, 23], priority rule = fcfs.
sequence = [1, 2, 3, 4, 5]
mean_flow_time = 15.4
makespan = 28
average_jobs_in_system = 2.75
utilization = 0.3636363636
total_tardiness = 11

Run it

Terminal
$ industrial-engineering solve ie_dispatching_rule "processing_times=[6, 2, 8, 3, 9]" "due_dates=[8, 6, 18, 15, 23]" rule=fcfs
sequence = [1,2,3,4,5]
mean_flow_time = 15.4
makespan = 28
average_jobs_in_system = 2.75
utilization = 0.3636363636
total_tardiness = 11
mean_tardiness = 2.2
max_tardiness = 5
max_lateness = 5
tardy_jobs = 3
  by: Sequencing by a dispatching rule (FCFS, SPT, LPT, EDD, CR)  (order the jobs by the rule; completion times are running sums; tardiness max(0, C - d))
  rule = fcfs
  assumes: processing times > 0; due dates >= 0; ties go to the lower job number; jobs available at time 0

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Shortest processing time (SPT) sequence1 fig.ie_spt_sequence

Order jobs on one machine by shortest processing time first (minimises mean flow time) and report the usual measures.

p_{[1]} \le p_{[2]} \le \dots,\quad \bar F = \frac{1}{n}\sum_k C_{[k]}

You give

MeaningUnitExample
\text{processing\_times}
Processing time of each job (jobs numbered 1, 2, … in this order) vector—[6, 2, 8, 3, 9]
\text{due\_dates}
Due date of each job (same order) optional vector—

You get

MeaningUnitExample
\text{sequence}
Job numbers in processing order—[2, 4, 1, 3, 5]
\text{mean\_flow\_time}
Average completion (flow) time—13
\text{makespan}
Completion time of the last job—28
\text{average\_jobs\_in\_system}
Sum of completion times / makespan—2.321428571
\text{utilization}
Sum of processing times / sum of completion times—0.4307692308
\text{total\_tardiness}
Sum of tardiness—
\text{mean\_tardiness}
Average tardiness (job lateness)—
\text{max\_tardiness}
Largest tardiness—
\text{max\_lateness}
Largest lateness C – d—
\text{tardy\_jobs}
Number of late jobs—

An optional input can be left out: a stated default is used.

Applies when

  • processing times > 0
  • all jobs available at time 0
  • ties go to the lower job number
  • tardiness measures only when due dates are given

Outside these conditions it says what is wrong instead of returning a number.

Worked example

SPT sequence with processing times = [6, 2, 8, 3, 9].
sequence = [2, 4, 1, 3, 5]
mean_flow_time = 13
makespan = 28
average_jobs_in_system = 2.321428571
utilization = 0.4307692308

Run it

Terminal
$ industrial-engineering solve ie_spt_sequence "processing_times=[6, 2, 8, 3, 9]"
sequence = [2,4,1,3,5]
mean_flow_time = 13
makespan = 28
average_jobs_in_system = 2.321428571
utilization = 0.4307692308
  by: Shortest processing time (SPT) sequence  (sort by processing time; completion C_k = sum of the first k times; flow = mean C)
  assumes: processing times > 0; all jobs available at time 0; ties go to the lower job number; tardiness measures only when due dates are given

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Statistical process control 18

Average run length of a Shewhart X-bar chart2 fig.ie_arl_shewhart

Probability that a Shewhart chart signals on a sample after the mean shifts by k sigma, and the average run length (ARL) until it does.

\beta = \Phi(L – k\sqrt n) – \Phi(-L – k\sqrt n),\quad ARL_1 = \frac{1}{1-\beta}

You give

MeaningUnitExample
\text{shift}
Mean shift in units of the process standard deviation (k)—1
\text{subgroup\_size}
Observations per subgroup (default 1) optional—5
\text{limit\_sigma}
Control limits at +/- L sigma of the mean (default 3) optional—

You get

MeaningUnitExample
\text{arl}
Average run length after the shift 1/(1 – beta)—4.495312227
\beta
Probability of no signal per sample—0.7775460414
\text{detection\_probability}
Probability of a signal per sample—0.2224539586
\text{arl\_in\_control}
In-control ARL 1/alpha—370.3983473

An optional input can be left out: a stated default is used.

Applies when

  • shift >= 0
  • 1 <= subgroup_size <= 1000
  • 0 < limit_sigma <= 6

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Average run length with mean shift = 1, sample size = 5.
arl = 4.495312227
beta = 0.7775460414
detection_probability = 0.2224539586
arl_in_control = 370.3983473

Run it

Terminal
$ industrial-engineering solve ie_arl_shewhart shift=1 subgroup_size=5
arl = 4.495312227
beta = 0.7775460414
detection_probability = 0.2224539586
arl_in_control = 370.3983473
  by: Average run length of a Shewhart X-bar chart  (beta = Phi(L - k sqrt(n)) - Phi(-L - k sqrt(n)); ARL = 1/(1 - beta))
  shift = 1
  assumes: shift >= 0; 1 <= subgroup_size <= 1000; 0 < limit_sigma <= 6

Figures

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

c chart control limits1 fig.ie_c_chart_limits

3-sigma limits of the count-of-defects (c) chart: c-bar +/- 3 sqrt(c-bar).

\bar c \pm 3\sqrt{\bar c}

You give

MeaningUnitExample
c_{\mathrm{bar}}
Average number of defects per unit (inspection unit of constant size)—9

You get

MeaningUnitExample
\text{ucl}
Upper control limit—18
\text{lcl}
Lower control limit (not below 0)—0
\text{center}
Centre line—9
\sigma_{c}
sqrt(c-bar)—3

Applies when

  • c_bar > 0
  • defects Poisson, constant inspection unit

Outside these conditions it says what is wrong instead of returning a number.

Worked example

C chart limits with average number of defects = 9.
ucl = 18
lcl = 0
center = 9
sigma_c = 3

Run it

Terminal
$ industrial-engineering solve ie_c_chart_limits c_bar=9
ucl = 18
lcl = 0
center = 9
sigma_c = 3
  by: c chart control limits  (limits c +/- 3 sqrt(c))
  c_bar = 9
  assumes: c_bar > 0; defects Poisson, constant inspection unit

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

DPMO and sigma level1 fig.ie_dpmo_sigma_level

Defects per unit, per opportunity and per million opportunities, and the sigma level (with the conventional 1.5 sigma shift).

DPMO = \frac{10^6\,D}{U\,O},\quad \text{sigma} = \Phi^{-1}(1 – DPO) + 1.5

You give

MeaningUnitExample
\text{defects}
Number of defects found—21
\text{units}
Number of units inspected—500
\text{opportunities}
Defect opportunities per unit—8

You get

MeaningUnitExample
\text{dpmo}
Defects per million opportunities—5250
\text{dpu}
Defects per unit—0.042
\text{dpo}
Defects per opportunity—0.00525
\text{yield}
1 – DPO—0.99475
\sigma_{\mathrm{level}}
Short-term sigma level Phi^-1(1 – DPO) + 1.5—4.05891305

Applies when

  • defects >= 0
  • units, opportunities > 0
  • 0 < DPO < 1

Outside these conditions it says what is wrong instead of returning a number.

Worked example

DPMO and sigma level with number of defects = 21, number of units = 500, opportunities per unit = 8.
dpmo = 5250
dpu = 0.042
dpo = 0.00525
yield = 0.99475
sigma_level = 4.05891305

Run it

Terminal
$ industrial-engineering solve ie_dpmo_sigma_level defects=21 units=500 opportunities=8
dpmo = 5250
dpu = 0.042
dpo = 0.00525
yield = 0.99475
sigma_level = 4.05891305
  by: DPMO and sigma level  (DPO = defects/(units opportunities), DPMO = 1e6 DPO, sigma = Phi^-1(1 - DPO) + 1.5)
  defects = 21
  units = 500
  opportunities = 8
  assumes: defects >= 0; units, opportunities > 0; 0 < DPO < 1

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

EWMA chart control limits2 fig.ie_ewma_limits

Control limits of an exponentially weighted moving average chart at sample i and in the steady state.

\mu_0 \pm L\sigma\sqrt{\frac{\lambda}{2-\lambda}\left[1-(1-\lambda)^{2i}\right]}

You give

MeaningUnitExample
\text{target}
In-control mean mu0—10
\sigma
Standard deviation of the plotted observations—1
\text{smoothing}
Smoothing constant lambda (0 < lambda <= 1)—0.1
\text{limit\_sigma}
Limit width L (often 2.7 to 3)—2.7
\text{sample\_number}
Sample number i—1

You get

MeaningUnitExample
\text{ucl}
UCL at sample i—10.27
\text{lcl}
LCL at sample i—9.73
\text{ucl\_steady}
Steady-state UCL—10.61942248
\text{lcl\_steady}
Steady-state LCL—9.380577519
\text{sd\_ewma}
Standard deviation of the EWMA at sample i—0.1

Applies when

  • sigma > 0
  • 0 < lambda <= 1
  • L > 0
  • sample_number >= 1

Outside these conditions it says what is wrong instead of returning a number.

Worked example

EWMA chart limits with centre line = 10, standard deviation = 1, lambda = 0.1, limit width = 2.7, sample = 1.
ucl = 10.27
lcl = 9.73
ucl_steady = 10.61942248
lcl_steady = 9.380577519
sd_ewma = 0.1

Run it

Figures

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Fraction nonconforming (normal process)1 fig.ie_fraction_nonconforming

Fraction (and parts per million) of output outside the specification limits for a normal process.

p = \Phi\!\left(\frac{LSL-\mu}{\sigma}\right) + 1 – \Phi\!\left(\frac{USL-\mu}{\sigma}\right)

You give

MeaningUnitExample
\text{mean}
Process mean—10.1
\text{sd}
Process standard deviation—0.12
\text{lsl}
Lower specification limit (optional) optional—9.7
\text{usl}
Upper specification limit (optional) optional—10.5

You get

MeaningUnitExample
\text{fraction\_out}
Fraction outside the limits—0.0008581206664
\text{below\_lsl}
Fraction below LSL—0.0004290603332
\text{above\_usl}
Fraction above USL—0.0004290603332
\text{ppm}
Parts per million out of specification—858.1206664
\text{yield}
Fraction within specification—0.9991418793

An optional input can be left out: a stated default is used.

Applies when

  • sd > 0
  • at least one limit
  • usl > lsl
  • process normal

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Fraction nonconforming with process mean = 10.1, standard deviation = 0.12, lower spec = 9.7, upper spec = 10.5.
fraction_out = 0.0008581206664
below_lsl = 0.0004290603332
above_usl = 0.0004290603332
ppm = 858.1206664
yield = 0.9991418793

Run it

Terminal
$ industrial-engineering solve ie_fraction_nonconforming mean=10.1 sd=0.12 lsl=9.7 usl=10.5
fraction_out = 0.0008581206664
below_lsl = 0.0004290603332
above_usl = 0.0004290603332
ppm = 858.1206664
yield = 0.9991418793
  by: Fraction nonconforming (normal process)  (P(X < LSL) + P(X > USL) for X ~ N(mu, sigma^2))
  mean = 10.1
  sd = 0.12
  lsl = 9.7
  usl = 10.5
  assumes: sd > 0; at least one limit; usl > lsl; process normal

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

np chart control limits2 fig.ie_np_chart_limits

3-sigma limits of the number-defective (np) chart: n p +/- 3 sqrt(n p (1 – p)).

n\bar p \pm 3\sqrt{n\bar p(1-\bar p)}

You give

MeaningUnitExample
p_{\mathrm{bar}}
Average fraction defective (decimal)—0.04
\text{sample\_size}
Items per sample—100

You get

MeaningUnitExample
\text{ucl}
Upper control limit—9.878775383
\text{lcl}
Lower control limit (not below 0)—0
\text{center}
Centre line n p—4
\sigma_{\mathrm{np}}
Standard deviation of the number defective—1.959591794

Applies when

  • 0 < p_bar < 1
  • constant sample size

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Np chart limits with average fraction defective = 0.04, sample size = 100.
ucl = 9.878775383
lcl = 0
center = 4
sigma_np = 1.959591794

Run it

Terminal
$ industrial-engineering solve ie_np_chart_limits p_bar=0.04 sample_size=100
ucl = 9.878775383
lcl = 0
center = 4
sigma_np = 1.959591794
  by: np chart control limits  (limits n p +/- 3 sqrt(n p (1 - p)))
  p_bar = 0.04
  assumes: 0 < p_bar < 1; constant sample size

Figures

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

p chart control limits2 fig.ie_p_chart_limits

3-sigma limits of the fraction-defective (p) chart: p-bar +/- 3 sqrt(p-bar (1 – p-bar) / n).

UCL, LCL = \bar p \pm 3\sqrt{\frac{\bar p(1-\bar p)}{n}}

You give

MeaningUnitExample
p_{\mathrm{bar}}
Average fraction defective (decimal)—0.04
\text{sample\_size}
Items per sample—100

You get

MeaningUnitExample
\text{ucl}
Upper control limit—0.09878775383
\text{lcl}
Lower control limit (not below 0)—0
\text{center}
Centre line—0.04
\sigma_{p}
Standard deviation of the fraction defective—0.01959591794

Applies when

  • 0 < p_bar < 1
  • sample_size > 0 (whole number of items)

Outside these conditions it says what is wrong instead of returning a number.

Worked example

P chart limits with average fraction defective = 0.04, sample size = 100.
ucl = 0.09878775383
lcl = 0
center = 0.04
sigma_p = 0.01959591794

Run it

Terminal
$ industrial-engineering solve ie_p_chart_limits p_bar=0.04 sample_size=100
ucl = 0.09878775383
lcl = 0
center = 0.04
sigma_p = 0.01959591794
  by: p chart control limits  (sigma_p = sqrt(p (1 - p)/n); limits p +/- 3 sigma_p, clipped to [0, 1])
  p_bar = 0.04
  assumes: 0 < p_bar < 1; sample_size > 0 (whole number of items)

Figures

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

p chart from sample counts1 fig.ie_p_chart_from_samples

Centre line and 3-sigma limits of a p chart computed from the defectives found in each sample, and the samples that fall outside them.

\bar p = \frac{\sum d_i}{m\,n},\quad \bar p \pm 3\sqrt{\bar p(1-\bar p)/n}

You give

MeaningUnitExample
\text{defectives}
Number of defective items in each sample vector—[3, 5, 2, 4, 12, 3, 4, 2, 5, 3]
\text{sample\_size}
Items in every sample—100

You get

MeaningUnitExample
p_{\mathrm{bar}}
Average fraction defective—0.043
\text{ucl}
Upper control limit—0.1038571278
\text{lcl}
Lower control limit—0
\text{out\_of\_control}
Sample numbers outside the limits—[5]
\text{count\_out}
How many samples are outside—1

Applies when

  • counts are whole numbers ≤ sample size
  • 0 < p-bar < 1
  • constant sample size

Outside these conditions it says what is wrong instead of returning a number.

Worked example

P chart from samples with defective counts = [3, 5, 2, 4, 12, 3, 4, 2, 5, 3], sample size = 100.
p_bar = 0.043
ucl = 0.1038571278
lcl = 0
out_of_control = [5]
count_out = 1

Run it

Terminal
$ industrial-engineering solve ie_p_chart_from_samples "defectives=[3, 5, 2, 4, 12, 3, 4, 2, 5, 3]" sample_size=100
p_bar = 0.043
ucl = 0.1038571278
lcl = 0
out_of_control = [5]
count_out = 1
  by: p chart from sample counts  (p-bar = total defectives / total inspected; limits p-bar +/- 3 sqrt(p-bar (1 - p-bar)/n); points beyond the limits flagged)
  assumes: counts are whole numbers <= sample size; 0 < p-bar < 1; constant sample size

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Process capability Cp and Cpk1 fig.ie_process_capability

Capability indices of a process with known mean and standard deviation against two specification limits.

C_p = \frac{USL-LSL}{6\sigma},\quad C_{pk} = \min\!\left(\frac{USL-\mu}{3\sigma},\frac{\mu-LSL}{3\sigma}\right)

You give

MeaningUnitExample
\text{usl}
Upper specification limit—10.5
\text{lsl}
Lower specification limit—9.5
\text{mean}
Process mean—10.1
\text{sd}
Process standard deviation—0.12

You get

MeaningUnitExample
\text{cpk}
Cpk = min(Cpu, Cpl)—1.111111111
\text{cp}
Cp = (USL – LSL)/(6 sigma)—1.388888889
\text{cpu}
(USL – mean)/(3 sigma)—1.111111111
\text{cpl}
(mean – LSL)/(3 sigma)—1.666666667

Applies when

  • usl > lsl
  • sd > 0
  • process normal and in control

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Process capability with upper spec = 10.5, lower spec = 9.5, process mean = 10.1, standard deviation = 0.12.
cpk = 1.111111111
cp = 1.388888889
cpu = 1.111111111
cpl = 1.666666667

Run it

Terminal
$ industrial-engineering solve ie_process_capability usl=10.5 lsl=9.5 mean=10.1 sd=0.12
cpk = 1.111111111
cp = 1.388888889
cpu = 1.111111111
cpl = 1.666666667
  by: Process capability Cp and Cpk  (Cp = (USL - LSL)/6 sigma, Cpk = min(USL - mu, mu - LSL)/3 sigma)
  usl = 10.5
  lsl = 9.5
  mean = 10.1
  sd = 0.12
  assumes: usl > lsl; sd > 0; process normal and in control

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Process performance Pp and Ppk from data2 fig.ie_process_performance

Performance indices Pp and Ppk from measured data, using the overall sample standard deviation (n – 1).

P_p = \frac{USL-LSL}{6s},\quad P_{pk} = \min\!\left(\frac{USL-\bar x}{3s},\frac{\bar x-LSL}{3s}\right)

You give

MeaningUnitExample
\text{data}
Measurements vector—[10.1, 9.9, 10.2, 10, 10.3, 9.8, 10.1, 10]
\text{usl}
Upper specification limit—10.6
\text{lsl}
Lower specification limit—9.4

You get

MeaningUnitExample
\text{ppk}
Ppk—1.143284202
\text{pp}
Pp—1.247219129
\text{mean}
Sample mean—10.05
\text{sd}
Overall sample standard deviation—0.1603567451

Applies when

  • at least 2 measurements that vary
  • usl > lsl

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Process performance with measurements = [10.1, 9.9, 10.2, 10, 10.3, 9.8, 10.1, 10], upper spec = 10.6, lower spec = 9.4.
ppk = 1.143284202
pp = 1.247219129
mean = 10.05
sd = 0.1603567451

Run it

Terminal
$ industrial-engineering solve ie_process_performance "data=[10.1, 9.9, 10.2, 10, 10.3, 9.8, 10.1, 10]" usl=10.6 lsl=9.4
ppk = 1.143284202
pp = 1.247219129
mean = 10.05
sd = 0.1603567451
  by: Process performance Pp and Ppk from data  (s = sqrt(sum (x - mean)^2/(n - 1)); Pp = (USL - LSL)/6s, Ppk = min(USL - mean, mean - LSL)/3s)
  usl = 10.6
  lsl = 9.4
  assumes: at least 2 measurements that vary; usl > lsl

Figures

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Process standard deviation from the average range2 fig.ie_sigma_from_range

Estimate of the process standard deviation sigma = R-bar / d2 and the natural tolerance 6 sigma.

\hat\sigma = \frac{\bar R}{d_2}

You give

MeaningUnitExample
\text{mean\_range}
Average subgroup range (R-bar)—2
\text{subgroup\_size}
Observations per subgroup (2 to 10)—5

You get

MeaningUnitExample
\sigma
Estimated process standard deviation R-bar/d2—0.8598452279
\text{d2}
d2 constant—2.326
\text{natural\_tolerance}
Natural tolerance 6 sigma—5.159071367

Applies when

  • mean_range > 0
  • subgroup size 2 to 10

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Process sigma from the average range with r bar = 2, sample size = 5.
sigma = 0.8598452279
d2 = 2.326
natural_tolerance = 5.159071367

Run it

Terminal
$ industrial-engineering solve ie_sigma_from_range mean_range=2 subgroup_size=5
sigma = 0.8598452279
d2 = 2.326
natural_tolerance = 5.159071367
  by: Process standard deviation from the average range  (sigma = R-bar / d2)
  mean_range = 2
  assumes: mean_range > 0; subgroup size 2 to 10

Figures

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Rolled throughput yield1 fig.ie_rolled_throughput_yield

Probability that a unit passes every process step defect-free (product of step yields), its geometric mean per step and the equivalent total defects per unit -ln(RTY).

RTY = \prod_i Y_i,\quad Y_{norm} = RTY^{1/k}

You give

MeaningUnitExample
\text{yields}
First-pass yield of each step (decimals) vector—[0.95, 0.98, 0.9, 0.99]

You get

MeaningUnitExample
\text{rty}
Rolled throughput yield—0.829521
\text{normalized\_yield}
Normalized yield RTY^(1/k)—0.9543481726
\text{total\_dpu}
Equivalent total defects per unit -ln RTY—0.1869068532

Applies when

  • each yield in (0, 1]

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Rolled throughput yield with step yields = [0.95, 0.98, 0.9, 0.99].
rty = 0.829521
normalized_yield = 0.9543481726
total_dpu = 0.1869068532

Run it

Terminal
$ industrial-engineering solve ie_rolled_throughput_yield "yields=[0.95, 0.98, 0.9, 0.99]"
rty = 0.829521
normalized_yield = 0.9543481726
total_dpu = 0.1869068532
  by: Rolled throughput yield  (RTY = product of yields; normalized = RTY^(1/k); DPU = -ln RTY)
  assumes: each yield in (0, 1]

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Single sampling plan: OC, AOQ and ATI1 fig.ie_acceptance_sampling

Probability of accepting a lot under a single sampling plan (n, c), the average outgoing quality with rectifying inspection and the average total inspection.

P_a = \sum_{k=0}^{c}\binom{n}{k}p^k(1-p)^{n-k},\quad AOQ = \frac{P_a\,p\,(N-n)}{N}

You give

MeaningUnitExample
\text{sample\_size}
Items sampled n—50
\text{acceptance\_number}
Acceptance number c—1
\text{fraction\_defective}
Lot fraction defective p (decimal)—0.02
\text{lot\_size}
Lot size N—2000

You get

MeaningUnitExample
\text{probability\_accept}
P(accept) = P(X <= c), X ~ Binomial(n, p)—0.7357713945
\text{aoq}
Average outgoing quality Pa p (N – n)/N—0.01434754219
\text{ati}
Average total inspection n + (1 – Pa)(N – n)—565.2457808
\text{probability\_reject}
1 – Pa—0.2642286055

Applies when

  • 0 <= c < n <= N
  • 0 < p < 1
  • binomial sampling
  • n <= 2000

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Single sampling plan with sample size = 50, acceptance number = 1, lot fraction defective = 0.02, n lot = 2000.
probability_accept = 0.7357713945
aoq = 0.01434754219
ati = 565.2457808
probability_reject = 0.2642286055

Run it

Terminal
$ industrial-engineering solve ie_acceptance_sampling sample_size=50 acceptance_number=1 fraction_defective=0.02 lot_size=2000
probability_accept = 0.7357713945
aoq = 0.01434754219
ati = 565.2457808
probability_reject = 0.2642286055
  by: Single sampling plan: OC, AOQ and ATI  (Pa = sum_{k<=c} C(n,k) p^k (1-p)^(n-k); AOQ = Pa p (N-n)/N; ATI = n + (1 - Pa)(N - n))
  fraction_defective = 0.02
  assumes: 0 <= c < n <= N; 0 < p < 1; binomial sampling; n <= 2000

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Tabular CUSUM chart2 fig.ie_tabular_cusum

Upper and lower cumulative sums C+ and C- of a tabular CUSUM chart and the first sample that signals (C+ or C- above h).

C_i^+ = \max(0,\,x_i-(\mu_0+K)+C_{i-1}^+),\quad C_i^- = \max(0,\,(\mu_0-K)-x_i+C_{i-1}^-)

You give

MeaningUnitExample
\text{data}
Observations in time order vector—[9.45, 7.99, 9.29, 11.66, 12.16, 10.18, 8.04, 11.46, 9.2, 10.34, 11.8, 12.2, 11.9, 12.5]
\text{target}
Target mean mu0—10
k
Reference value K (often half the shift to detect)—0.5
h
Decision interval H—5

You get

MeaningUnitExample
\text{first\_signal}
First sample number with C+ or C- above H (0 = none)—14
c_{\mathrm{plus}}
C+ after each sample—[0, 0, 0, 1.16, 2.82, 2.5, 0.04, 1, 0, 0, 1.3, 3, 4.4, 6.4]
c_{\mathrm{minus}}
C- after each sample—[0.05, 1.56, 1.77, 0, 0, 0, 1.46, 0, 0.3, 0, 0, 0, 0, 0]
\text{final\_c\_plus}
Last C+—6.4
\text{final\_c\_minus}
Last C-—0

Applies when

  • k >= 0
  • h > 0
  • C+ and C- start at 0

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Tabular CUSUM with observations = [9.45, 7.99, 9.29, 11.66, 12.16, 10.18, 8.04, 11.46, 9.2, 10.34, 11.8, 12.2, 11.9, 12.5], target mean = 10, reference value = 0.5, decision interval = 5.
first_signal = 14
c_plus = [0, 0, 0, 1.16, 2.82, 2.5, 0.04, 1, 0, 0, 1.3, 3, 4.4, 6.4]
c_minus = [0.05, 1.56, 1.77, 0, 0, 0, 1.46, 0, 0.3, 0, 0, 0, 0, 0]
final_c_plus = 6.4
final_c_minus = 0

Run it

Figures

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Taguchi capability index Cpm1 fig.ie_cpm_taguchi

Capability index that penalises distance from the target: Cpm = (USL – LSL) / (6 sqrt(sigma^2 + (mu – T)^2)).

C_{pm} = \frac{USL-LSL}{6\sqrt{\sigma^2+(\mu-T)^2}}

You give

MeaningUnitExample
\text{usl}
Upper specification limit—10.6
\text{lsl}
Lower specification limit—9.4
\text{mean}
Process mean—10.1
\text{sd}
Process standard deviation—0.1
\text{target}
Target value T—10

You get

MeaningUnitExample
\text{cpm}
Cpm—1.414213562
\text{cp}
Cp—2
\tau
Root mean square deviation from target—0.1414213562

Applies when

  • usl > lsl
  • lsl < target < usl
  • sd > 0

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Taguchi capability index Cpm with upper spec = 10.6, lower spec = 9.4, process mean = 10.1, standard deviation = 0.1, nominal = 10.
cpm = 1.414213562
cp = 2
tau = 0.1414213562

Run it

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

u chart control limits2 fig.ie_u_chart_limits

3-sigma limits of the defects-per-unit (u) chart for samples of n units: u-bar +/- 3 sqrt(u-bar / n).

\bar u \pm 3\sqrt{\bar u / n}

You give

MeaningUnitExample
u_{\mathrm{bar}}
Average defects per unit—1.5
\text{units}
Inspection units in the sample—10

You get

MeaningUnitExample
\text{ucl}
Upper control limit—2.661895004
\text{lcl}
Lower control limit (not below 0)—0.3381049961
\text{center}
Centre line—1.5
\sigma_{u}
sqrt(u-bar / n)—0.3872983346

Applies when

  • u_bar > 0
  • units > 0

Outside these conditions it says what is wrong instead of returning a number.

Worked example

U chart limits with average defects per unit = 1.5, sample size = 10.
ucl = 2.661895004
lcl = 0.3381049961
center = 1.5
sigma_u = 0.3872983346

Run it

Terminal
$ industrial-engineering solve ie_u_chart_limits u_bar=1.5 units=10
ucl = 2.661895004
lcl = 0.3381049961
center = 1.5
sigma_u = 0.3872983346
  by: u chart control limits  (limits u +/- 3 sqrt(u/n))
  u_bar = 1.5
  units = 10
  assumes: u_bar > 0; units > 0

Figures

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

X-bar and R chart control limits1 fig.ie_xbar_r_limits

3-sigma control limits of the X-bar and R charts from the grand mean, the average range and the subgroup size.

UCL_{\bar x} = \bar{\bar x} + A_2\bar R,\quad UCL_R = D_4\bar R,\quad LCL_R = D_3\bar R

You give

MeaningUnitExample
\text{grand\_mean}
Grand mean of the subgroup means (x-double-bar)—50
\text{mean\_range}
Average subgroup range (R-bar)—2
\text{subgroup\_size}
Observations per subgroup (2 to 10)—5

You get

MeaningUnitExample
\text{xbar\_ucl}
X-bar chart UCL—51.154
\text{xbar\_lcl}
X-bar chart LCL—48.846
\text{center}
X-bar chart centre line—50
r_{\mathrm{ucl}}
R chart UCL D4 R-bar—4.228
r_{\mathrm{lcl}}
R chart LCL D3 R-bar—0
\text{A2}
A2—0.577
\text{D3}
D3—0
\text{D4}
D4—2.114

Applies when

  • mean_range > 0
  • subgroup size 2 to 10
  • standard 3-decimal constants

Outside these conditions it says what is wrong instead of returning a number.

Worked example

X-bar and R chart limits with x double bar = 50, r bar = 2, sample size = 5.
xbar_ucl = 51.154
xbar_lcl = 48.846
center = 50
r_ucl = 4.228
r_lcl = 0
A2 = 0.577

Run it

Terminal
$ industrial-engineering solve ie_xbar_r_limits grand_mean=50 mean_range=2 subgroup_size=5
xbar_ucl = 51.154
xbar_lcl = 48.846
center = 50
r_ucl = 4.228
r_lcl = 0
A2 = 0.577
D3 = 0
D4 = 2.114
  by: X-bar and R chart control limits  (UCL/LCL = x-double-bar +/- A2 R-bar; R chart D3 R-bar, D4 R-bar)
  grand_mean = 50
  mean_range = 2
  assumes: mean_range > 0; subgroup size 2 to 10; standard 3-decimal constants

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

X-bar and S chart control limits2 fig.ie_xbar_s_limits

3-sigma control limits of the X-bar and S charts from the grand mean, the average subgroup standard deviation and the subgroup size.

UCL_{\bar x} = \bar{\bar x} + A_3\bar s,\quad UCL_s = B_4\bar s,\quad LCL_s = B_3\bar s

You give

MeaningUnitExample
\text{grand\_mean}
Grand mean of the subgroup means—50
\text{mean\_sd}
Average subgroup standard deviation (s-bar)—0.9
\text{subgroup\_size}
Observations per subgroup (2 to 10)—5

You get

MeaningUnitExample
\text{xbar\_ucl}
X-bar chart UCL—51.2843
\text{xbar\_lcl}
X-bar chart LCL—48.7157
\text{center}
Centre line—50
s_{\mathrm{ucl}}
S chart UCL B4 s-bar—1.8801
s_{\mathrm{lcl}}
S chart LCL B3 s-bar—0
\text{A3}
A3—1.427
\text{B3}
B3—0
\text{B4}
B4—2.089

Applies when

  • mean_sd > 0
  • subgroup size 2 to 10
  • standard 3-decimal constants

Outside these conditions it says what is wrong instead of returning a number.

Worked example

X-bar and S chart limits with x double bar = 50, s bar = 0.9, sample size = 5.
xbar_ucl = 51.2843
xbar_lcl = 48.7157
center = 50
s_ucl = 1.8801
s_lcl = 0
A3 = 1.427

Run it

Terminal
$ industrial-engineering solve ie_xbar_s_limits grand_mean=50 mean_sd=0.9 subgroup_size=5
xbar_ucl = 51.2843
xbar_lcl = 48.7157
center = 50
s_ucl = 1.8801
s_lcl = 0
A3 = 1.427
B3 = 0
B4 = 2.089
  by: X-bar and S chart control limits  (x-double-bar +/- A3 s-bar; S chart B3 s-bar, B4 s-bar)
  grand_mean = 50
  mean_sd = 0.9
  assumes: mean_sd > 0; subgroup size 2 to 10; standard 3-decimal constants

Figures

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Work measurement 5

Capacity utilisation and efficiency1 fig.ie_capacity_utilization

Utilisation (actual output / design capacity) and efficiency (actual output / effective capacity).

U = \frac{\text{actual}}{\text{design}},\quad E = \frac{\text{actual}}{\text{effective}}

You give

MeaningUnitExample
\text{design\_capacity}
Design capacity—1200
\text{effective\_capacity}
Effective capacity—1000
\text{actual\_output}
Actual output—800

You get

MeaningUnitExample
\text{utilization}
Actual / design—0.6666666667
\text{efficiency}
Actual / effective—0.8
\text{effective\_share}
Effective / design—0.8333333333

Applies when

  • capacities > 0
  • effective <= design
  • same units and period

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Capacity utilization and efficiency with design capacity = 1200, effective capacity = 1000, actual output = 800.
utilization = 0.6666666667
efficiency = 0.8
effective_share = 0.8333333333

Run it

Terminal
$ industrial-engineering solve ie_capacity_utilization design_capacity=1200 effective_capacity=1000 actual_output=800
utilization = 0.6666666667
efficiency = 0.8
effective_share = 0.8333333333
  by: Capacity utilisation and efficiency  (utilisation = actual/design, efficiency = actual/effective)
  design_capacity = 1200
  effective_capacity = 1000
  actual_output = 800
  assumes: capacities > 0; effective <= design; same units and period

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Number of cycles to time in a time study1 fig.ie_time_study_sample_size

Observations needed so the mean cycle time is within +/- h (a fraction of the mean) at a confidence level: n = (z s / (h x-bar))^2.

n = \left(\frac{z\,s}{h\,\bar x}\right)^2

You give

MeaningUnitExample
\text{mean}
Mean of the pilot observations—3
\text{sd}
Standard deviation of the pilot observations—0.5
\text{accuracy}
Desired accuracy as a fraction of the mean (decimal; 5% = 0.05)—0.05
\text{confidence}
Confidence level (decimal)—0.95

You get

MeaningUnitExample
\text{sample\_size}
Observations needed (rounded up)—43
\text{exact}
(z s / (h x-bar))^2—42.68287579
z
Two-sided z—1.959963985

Applies when

  • mean, sd > 0
  • 0 < accuracy < 1
  • 0 < confidence < 1
  • normal approximation

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Time study sample size with sample mean = 3, standard deviation = 0.5, desired accuracy = 0.05, confidence level = 0.95.
sample_size = 43
exact = 42.68287579
z = 1.959963985

Run it

Terminal
$ industrial-engineering solve ie_time_study_sample_size mean=3 sd=0.5 accuracy=0.05 confidence=0.95
sample_size = 43
exact = 42.68287579
z = 1.959963985
  by: Number of cycles to time in a time study  (n = (z s / (h x-bar))^2, z for a two-sided confidence)
  mean = 3
  sd = 0.5
  accuracy = 0.05
  confidence = 0.95
  assumes: mean, sd > 0; 0 < accuracy < 1; 0 < confidence < 1; normal approximation

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Overall equipment effectiveness (OEE)1 fig.ie_oee

OEE = availability x performance x quality from planned time, downtime, ideal cycle time and counts.

OEE = A \times P \times Q = \frac{\text{good} \times t_{ideal}}{T_{planned}}

You give

MeaningUnitExample
\text{planned\_time}
Planned production time—420
\text{downtime}
Stop time within the planned time—47
\text{ideal\_cycle\_time}
Ideal time per unit (same time unit)—1
\text{total\_count}
Units produced—300
\text{good\_count}
Good units—285

You get

MeaningUnitExample
\text{oee}
Availability x performance x quality—0.6785714286
\text{availability}
Run time / planned time—0.8880952381
\text{performance}
Ideal cycle time x total count / run time—0.8042895442
\text{quality}
Good / total—0.95
\text{run\_time}
Planned time – downtime—373

Applies when

  • downtime < planned time
  • good <= total
  • performance <= 1

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Overall equipment effectiveness with planned production time = 420, stop time = 47, ideal cycle time = 1, total units = 300, good units = 285.
oee = 0.6785714286
availability = 0.8880952381
performance = 0.8042895442
quality = 0.95
run_time = 373

Run it

Terminal
$ industrial-engineering solve ie_oee planned_time=420 downtime=47 ideal_cycle_time=1 total_count=300 good_count=285
oee = 0.6785714286
availability = 0.8880952381
performance = 0.8042895442
quality = 0.95
run_time = 373
  by: Overall equipment effectiveness (OEE)  (A = (T - D)/T, P = ct n / (T - D), Q = good/n, OEE = A P Q (= good x ct / T))
  planned_time = 420
  downtime = 47
  ideal_cycle_time = 1
  total_count = 300
  good_count = 285
  assumes: downtime < planned time; good <= total; performance <= 1

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Standard time from a time study2 fig.ie_standard_time

Normal time (mean observed time x performance rating) and standard time with a personal, fatigue and delay allowance.

NT = \bar t \times PR,\quad ST = NT(1+A)\ \text{or}\ \frac{NT}{1-A}

You give

MeaningUnitExample
\text{observed\_times}
Observed cycle times vector—[4.2, 4.5, 4, 4.3, 4.5]
\text{rating}
Performance rating (decimal; 110% = 1.1)—1.1
\text{allowance}
Allowance fraction (decimal; 15% = 0.15)—0.15
\text{basis}
Job: ST = NT (1 + A); shift: ST = NT / (1 – A), A a share of the workday choice—job

You get

MeaningUnitExample
\text{standard\_time}
Standard time—5.4395
\text{normal\_time}
Mean x rating—4.73
\text{mean\_observed\_time}
Mean observed time—4.3

Applies when

  • observed times > 0
  • rating > 0
  • 0 <= allowance < 1
  • the allowance basis must be stated

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Standard time with observed times = [4.2, 4.5, 4, 4.3, 4.5], performance rating = 1.1, allowance factor = 0.15, allowance basis = job.
standard_time = 5.4395
normal_time = 4.73
mean_observed_time = 4.3

Run it

Terminal
$ industrial-engineering solve ie_standard_time "observed_times=[4.2, 4.5, 4, 4.3, 4.5]" rating=1.1 allowance=0.15 basis=job
standard_time = 5.4395
normal_time = 4.73
mean_observed_time = 4.3
  by: Standard time from a time study  (NT = mean x rating; ST = NT (1 + A) on a job basis or NT / (1 - A) on a workday basis)
  rating = 1.1
  allowance = 0.15
  basis = job
  assumes: observed times > 0; rating > 0; 0 <= allowance < 1; the allowance basis must be stated

Figures

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Work sampling sample size1 fig.ie_work_sampling_sample_size

Random observations needed to estimate the fraction of time in an activity within +/- h (absolute) at a confidence level: n = z^2 p (1 – p) / h^2.

n = \frac{z^2\,p(1-p)}{h^2}

You give

MeaningUnitExample
\text{proportion}
Estimated fraction of time in the activity (decimal)—0.2
\text{accuracy}
Absolute accuracy (decimal; 0.05 = +/- 5 points)—0.05
\text{confidence}
Confidence level (decimal)—0.95

You get

MeaningUnitExample
\text{sample\_size}
Observations needed (rounded up)—246
\text{exact}
z^2 p (1 – p) / h^2—245.8533645
z
Two-sided z—1.959963985

Applies when

  • 0 < p < 1
  • 0 < h < 1
  • 0 < confidence < 1

Outside these conditions it says what is wrong instead of returning a number.

Worked example

Work sampling sample size with estimated proportion = 0.2, desired accuracy = 0.05, confidence level = 0.95.
sample_size = 246
exact = 245.8533645
z = 1.959963985

Run it

Terminal
$ industrial-engineering solve ie_work_sampling_sample_size proportion=0.2 accuracy=0.05 confidence=0.95
sample_size = 246
exact = 245.8533645
z = 1.959963985
  by: Work sampling sample size  (n = z^2 p (1 - p) / h^2)
  proportion = 0.2
  accuracy = 0.05
  confidence = 0.95
  assumes: 0 < p < 1; 0 < h < 1; 0 < confidence < 1

Figure

Each figure varies one input around the worked example and recomputes the result at every point. Press Compute above and they are redrawn for your own inputs.

Figures

Computed, not drawn by hand

Every point in these figures is an answer of the model: one input is varied, the others are held at the worked example, and the curve shows how the result responds. The marked point is the worked example itself.

Simple exponential smoothing forecast

F_{t+1} = F_t + \alpha\,(A_t – F_t)
forecasts against k: Simple exponential smoothing forecastforecasts (forecasts for periods 1, …, n + 1) for each index, as returned by industrial-engineering-ai999x for its example (5 values).01234140141142143k — indexforecasts
forecasts (forecasts for periods 1, …, n + 1) for each index, as returned by industrial-engineering-ai999x for its example (5 values).

Economic order quantity (EOQ)

Q^* = \sqrt{\frac{2DS}{H}},\quad TC^* = \sqrt{2DSH}
Q against demand: Economic order quantity (EOQ)Q (economic order quantity Q*) against demand (demand per year (units)), with holding_cost = 6, order_cost = 100. 31 points computed by industrial-engineering-ai999x; marked: demand = 1200, Q = 200.10001500150175200225250200 demand — demand per year (units)Q
Q (economic order quantity Q*) against demand (demand per year (units)), with holding_cost = 6, order_cost = 100. 31 points computed by industrial-engineering-ai999x; marked: demand = 1200, Q = 200.

M/M/c queue (Erlang C)

C(c,a) = \frac{\frac{a^c}{c!(1-\rho)}}{\sum_{k=0}^{c-1}\frac{a^k}{k!} + \frac{a^c}{c!(1-\rho)}},\quad L_q = C\frac{\rho}{1-\rho}
Lq against arrival_rate: M/M/c queue (Erlang C)Lq (mean number waiting) against arrival_rate (mean arrival rate lambda (per time unit)), with servers = 3, service_rate = 4. 21 points computed by industrial-engineering-ai999x; marked: arrival_rate = 10, Lq = 3.51124.681001020303.51124 arrival_rate — mean arrival rate lambda (per time unit)Lq
Lq (mean number waiting) against arrival_rate (mean arrival rate lambda (per time unit)), with servers = 3, service_rate = 4. 21 points computed by industrial-engineering-ai999x; marked: arrival_rate = 10, Lq = 3.51124.

Johnson's rule (two machines)

\min(a_{1i}, a_{2j}) \le \min(a_{1j}, a_{2i}) \Rightarrow i \text{ before } j
sequence against k: Johnson's rule (two machines)sequence (job order) for each index, as returned by industrial-engineering-ai999x for its example (5 values).0123412345k — indexsequence
sequence (job order) for each index, as returned by industrial-engineering-ai999x for its example (5 values).
Questions

Frequently asked

What does industrial-engineering-ai999x do?

Industrial Engineering and Supply Chain answers questions in industrial engineering and supply chain: inventory policies (EOQ, reorder point, safety stock, newsvendor), statistical process control, reliability, queueing, scheduling, forecasting accuracy, line balancing, learning curves and facility location. Each answer gives the value with its unit, the steps and the formula in LaTeX.

Is there a desktop app or a command-line program?

Yes, both, for Windows and Linux. AI999X Industrial Engineering and Supply Chain is a desktop app of its own, and the AI999X desktop app holds all AI999X models in one window (search, ask in words, forms, figures, explanations). The command-line bundle holds one program per model; for this one run `industrial-engineering list` for its capabilities, `industrial-engineering info <capability>` for what one needs and `industrial-engineering solve <capability> name=value …` for an answer. Both run offline and need no Python. Downloads and checksums: https://www.ai999x.com/desktop-cli/

How do I install industrial-engineering-ai999x?

With pip: pip install industrial-engineering-ai999x. The same files are on Hugging Face (hf download AI999X/industrial-engineering-ai999x –local-dir industrial-engineering-ai999x) and GitHub.

Does it run offline?

Yes. It is a Python package that runs on an ordinary CPU without a network connection (Python >=3.10); no GPU and no API key are needed.

How many capabilities does industrial-engineering-ai999x have?

94 capabilities in 11 topics, including Inventory, Statistical process control, Reliability, Forecasting, Queueing.

Which field and tasks does it cover?

Field: Engineering. Tasks: Question Answering, Sentence Similarity, Feature Extraction.

What does an answer look like?

Asked "Economic order quantity with annual demand = 1200, ordering cost = 100, holding cost = 6.", it answers: Q = 200, orders_per_year = 6, cycle_time = 0.166667, ordering_cost = 600, holding_cost_per_year = 600, total_cost = 1200.

What happens when a question cannot be answered?

It says so and names what is missing or out of range, instead of guessing a number.

More from AI999X

Explore every model.