Learning Curve Modeling Approaches
Learning curves are mathematical models predicting improvements in productivity and efficiency as experience with a task increases. These curves are essential tools for:
- Estimating project costs and timelines.
- Analyzing historical data for efficiency trends.
- Forecasting and decision-making.
The following documentation covers three popular methods implemented using Julia with multiple dispatch:
Learning Curve Methods
The learning curve methods are implemented as an abstract type hierarchy:
LearningCurveMethod
: Abstract base typeWrightMethod
: Wright's cumulative-average modelCrawfordMethod
: Crawford's unit-time modelExperienceMethod
: Experience curve model
Wright's Curve
MCHammer.WrightMethod
— TypeWright learning curve method.
struct WrightMethod <: LearningCurveMethod end
Introduced by T.P. Wright in 1936 in his seminal work on airplane production cost analysis (Wright, 1936). This model observes that with each doubling of cumulative production, the unit cost decreases by a fixed percentage. It is well‑suited for processes where learning is continuous and gradual.
Parameters (package-wide convention)
Learning
= progress ratio LR in(0,1]
(e.g.0.85
= 85%)b = log(Learning)/log(2)
(negative when there is learning)InitialEffort
= first‑unit costC₁
Implementation returns cumulative total cost (cumulative‑average form):
\[\mathrm{Total}(N)=C_1\,N^{\,b+1},\qquad b=\frac{\log(\mathrm{LR})}{\log 2}\]
Unit‑cost form (reference):
\[C_N = C_1\,N^{\,b}\]
When to Use
- When historical data show a smooth, predictable decline in unit costs as production doubles.
When to Avoid
- When cost reductions occur in discrete steps or when the production process experiences structural changes.
Crawford's Curve
MCHammer.CrawfordMethod
— TypeCrawford learning curve method.
struct CrawfordMethod <: LearningCurveMethod end
Crawford models per‑unit learning discretely and accumulates unit costs.
Parameters
Learning
= progress ratio LR in(0,1]
b = log(Learning)/log(2)
InitialEffort
= first‑unit costC₁
Implementation returns cumulative total cost (discrete sum):
\[\mathrm{Total}(N)=\sum_{i=1}^N C_1\, i^{\,b}\]
Per‑unit cost (reference):
\[C_i = C_1\, i^{\,b}\]
Experience Curve
MCHammer.ExperienceMethod
— TypeExperience learning curve method.
struct ExperienceMethod <: LearningCurveMethod end
BCG/Excel-style experience curve where the exponent equals the progress ratio LR
. This matches spreadsheet formulas like C1 * N^(LR)
; e.g., with LR=0.8
the total is C1 * N^0.8
.
Parameters
Learning
= progress ratio LR in(0,1]
InitialEffort
= average cost atN=1
(ar{C}_1
)
Implementation returns cumulative total cost:
\[\mathrm{Total}(N)=\bar{C}_1\,N^{\,\mathrm{LR}}\]
When to Use
- Strategic/competitive planning when broad efficiency improvements are observed and spreadsheet convention is desired.
When to Avoid
- When per‑unit discreteness dominates (see
CrawfordMethod
).
Cumulative Cost Analysis
To compute cumulative cost analytically for an experience curve, here are the functions to accomplish this.
Wright Learning Curve
# compute the cumulative total cost for 500 units with a progress ratio of 0.85
result = lc_analytic(WrightMethod(), 200, 500, 0.85)
println(result)
23290.84865742685
Crawford Learning Curve
# compute the cumulative total cost for 500 units with a progress ratio of 0.85
result = lc_analytic(CrawfordMethod(), 200, 500, 0.85)
println(result)
30290.08483739403
Experience Curve
# compute the cumulative total cost for 500 units with a progress ratio of 0.85
result = lc_analytic(ExperienceMethod(), 200, 500, 0.85)
println(result)
39369.01049745011
Curve Functions
Generates detailed DataFrame including cumulative, incremental, and average costs.
MCHammer.lc_curve
— Functionlc_curve(method::LearningCurveMethod,
InitialEffort::Real,
StartUnit::Integer,
TotalUnits::Integer,
Learning::Real;
steps::Integer=1) -> DataFrame
Build a table of cumulative and per-unit costs.
Columns:
Units
— cumulative units at this rowCumulativeCost
— total cost up toUnits
Incremental
— incremental cost over the laststeps
unitsAvgCost
— cumulative average cost up toUnits
Method
— method name
Notes on Incremental
:
- Wright uses block-difference of
C_1 N^{b+1}
divided bysteps
. - Crawford uses the average of unit costs
C_1 i^b
over the block. - Experience uses block-difference of
ar{C}_1 N^{LR}
divided bysteps
.
Wright Learning Curve
Generate a table of cumulative and per‑unit costs for Wright’s model using initial cost 200, from unit 1 to 500, progress ratio 0.85, sampling every 25 units
df = lc_curve(WrightMethod(), 200, 1, 500, 0.85; steps=25)
println(first(df, 5))
5×5 DataFrame
Row │ Units CumulativeCost Incremental AvgCost Method
│ Float64 Float64 Float64 Float64 String
─────┼────────────────────────────────────────────────────────
1 │ 1.0 200.0 8.0 200.0 Wright
2 │ 26.0 2422.37 88.895 93.1682 Wright
3 │ 51.0 4057.27 65.396 79.5544 Wright
4 │ 76.0 5506.28 57.9602 72.451 Wright
5 │ 101.0 6845.54 53.5704 67.7776 Wright
Crawford Learning Curve
Generate a table of cumulative and per‑unit costs for Crawford’s model using initial cost 200, from unit 1 to 500, progress ratio 0.85, sampling every 25 units
df = lc_curve(CrawfordMethod(), 200, 1, 500, 0.85; steps=25)
println(first(df, 5))
5×5 DataFrame
Row │ Units CumulativeCost Incremental AvgCost Method
│ Float64 Float64 Float64 Float64 String
─────┼──────────────────────────────────────────────────────────
1 │ 1.0 200.0 8.0 200.0 Crawford
2 │ 26.0 3053.31 114.133 117.435 Crawford
3 │ 51.0 5182.18 85.1545 101.611 Crawford
4 │ 76.0 7071.44 75.5704 93.0452 Crawford
5 │ 101.0 8818.55 69.8845 87.3124 Crawford
Experience Curve
Generate a table of cumulative and per‑unit costs for the Experience model using initial cost 200, from unit 1 to 500, progress ratio 0.85, sampling every 25 units
df = lc_curve(ExperienceMethod(), 200, 1, 500, 0.85; steps=25)
println(first(df, 5))
5×5 DataFrame
Row │ Units CumulativeCost Incremental AvgCost Method
│ Float64 Float64 Float64 Float64 String
─────┼───────────────────────────────────────────────────────────
1 │ 1.0 200.0 8.0 200.0 Experience
2 │ 26.0 3189.76 119.59 122.683 Experience
3 │ 51.0 5655.42 98.6265 110.891 Experience
4 │ 76.0 7938.19 91.311 104.45 Experience
5 │ 101.0 10108.9 86.8277 100.088 Experience
Analysis Functions
Fitting Functions
MCHammer.lc_fit
— Functionlc_fit(::LearningCurveMethod, n1, x1, n2, x2) -> (b, p)
Generic two‑point fit for a power law x = a n^b
. Returns the slope b
and the progress ratio p = 2^b
.
Example:
The function lc_fit
estimates the slope $b$ and progress ratio $p = 2^b$ from two observations. Given two points at units $n_1$ and $n_2$ with corresponding costs $x_1$ and $x_2$, we can estimate $b$ and $p$ for any of the learning‑curve methods. The following example uses the same data for Wright, Crawford and Experience models. Though the results are identical, the derivations are different.
# two observation points
n1, x1 = 8, 200.0
n2, x2 = 32, 140.0
# estimate (b, progress ratio) for each method using the same inputs
(b_w, L_w) = lc_fit(WrightMethod(), n1, x1, n2, x2)
(b_c, L_c) = lc_fit(CrawfordMethod(), n1, x1, n2, x2)
(b_e, L_e) = lc_fit(ExperienceMethod(),n1, x1, n2, x2)
((b_w, L_w), (b_c, L_c), (b_e, L_e))
((-0.2572865864148791, 0.8366600265340756), (-0.2572865864148791, 0.8366600265340756), (-0.2572865864148791, 0.8366600265340756))
Learning Rate Estimation
Estimates learning rates using Wright's method from two data points.
MCHammer.learn_rate
— Functionlearn_rate(::WrightMethod, n1, y1, n2, y2; mode=:avg) -> Float64
Estimate Wright progress ratio p
from two observations.
- If
mode = :avg
(default),y
values are cumulative averages atn1
andn2
:
\[b = \frac{\ln(y_2/y_1)}{\ln(n_2/n_1)}, \quad p = 2^b.\]
- If
mode = :unit
,y
values are unit times atn1
andn2
. The function solves
for b
from the unit‑increment relation and returns p = 2^b
.
learn_rate(::WrightMethod, n::AbstractVector, y::AbstractVector; mode=:auto) -> Float64
Estimate Wright progress ratio p
from ≥3 points. If mode = :auto
(default), fits both average and unit models and picks the lower SSE. Set mode=:avg
or :unit
to force a specific interpretation.
learn_rate(::CrawfordMethod, i1, y1, i2, y2) -> Float64
Two‑point fit for Crawford’s unit model using per‑unit costs y(i) = a i^b
. With two observations (i₁, y₁)
and (i₂, y₂)
:
\[b = \frac{\ln(y_2/y_1)}{\ln(i_2/i_1)}, \quad p = 2^b.\]
Returns the learning rate p
.
learn_rate(::ExperienceMethod, n1, avg1, n2, avg2) -> Float64
Two‑point fit for the Experience curve under the Excel/BCG convention where the exponent equals LR. Given cumulative totals T(N) = ar{C}_1 N^{LR}
, the average at N
is avg(N) = T(N)/N = ar{C}_1 N^{LR-1}
. Using averages:
\[LR = 1 + \frac{\ln(\mathrm{avg}_2/\mathrm{avg}_1)}{\ln(n_2/n_1)}.\]
Returns LR
(e.g., 0.8
).
rate = learn_rate(WrightMethod(), 1, 2000, 144, 1600)
println(rate)
0.9693571494126194
Comparison Utility
Compares learning curves across a range of learning rates.
MCHammer.learn_rates
— Functionlearn_rates(InitialEffort, TotalUnits; α_step=0.1) -> DataFrame
Compare cumulative total cost across methods for a sweep of learning rates LR
in (0,1]
.
- Wright:
C_1 * N^(1 + b)
withb = log(LR)/log 2
- Crawford:
∑ C_1 * i^b
withb = log(LR)/log 2
- Experience:
ar{C}_1 * N^(LR)
Example:
rates_df = learn_rates(100, 500; α_step=0.05)
println(first(rates_df, 5))
5×4 DataFrame
Row │ LC Wright Crawford Experience
│ Float64 Float64 Float64 Float64
─────┼─────────────────────────────────────────
1 │ 1.0 50000.0 50000.0 50000.0
2 │ 0.95 31567.8 34064.7 36645.6
3 │ 0.9 19441.0 22878.5 26858.0
4 │ 0.85 11645.4 15145.0 19684.5
5 │ 0.8 6762.32 9884.72 14427.0
Picking the right curve
Sometimes picking the right curve is challenging and in these cases plotting a comparison of average costs across methods using Plots.jl
can be very helpful.
# Generate sample tables for each method and plot the average cost across units.
CC = lc_curve(CrawfordMethod(), 50, 1, 1000, 0.85; steps=25)
WC = lc_curve(WrightMethod(), 50, 1, 1000, 0.85; steps=25)
EC = lc_curve(ExperienceMethod(), 50, 1, 1000, 0.85; steps=25)
# Combine the results
GraphResults = vcat(CC, WC, EC)
first(GraphResults,5)
Row | Units | CumulativeCost | Incremental | AvgCost | Method |
---|---|---|---|---|---|
Float64 | Float64 | Float64 | Float64 | String | |
1 | 1.0 | 50.0 | 2.0 | 50.0 | Crawford |
2 | 26.0 | 763.328 | 28.5331 | 29.3588 | Crawford |
3 | 51.0 | 1295.54 | 21.2886 | 25.4028 | Crawford |
4 | 76.0 | 1767.86 | 18.8926 | 23.2613 | Crawford |
5 | 101.0 | 2204.64 | 17.4711 | 21.8281 | Crawford |
Create and display the plot
using Plots
plot(GraphResults.Units, GraphResults.AvgCost, group=GraphResults.Method,
xlabel="Units", ylabel="Average Cost per Unit",
title="Learning Curves Comparison",
lw=2, legend=:topright)
Mathematical Notes
Symbols:
- α: learning exponent (progress ratio = $2^{b}$)
- N: number of units
Wright's Law (Cumulative Average Model):
\[\text{Cumulative Average Cost}_N = \text{Initial} \times N^{-\alpha}\]
Crawford's Law (Unit Cost Model):
\[\text{Unit Cost}_N = \text{Initial} \times N^{-\alpha}\]
Experience Curve:
\[\text{Cost}_N = \text{Initial} \times N^{-\alpha}\]
Sources & References
- Eric Torkia, Decision Superhero Vol. 2, chapter 6 : SuperPower: The Laws of Nature that Predict, Technics Publishing, 2025
- Available on Amazon : https://a.co/d/4YlJFzY . Volumes 2 and 3 to be released in Spring and Fall 2025.
- Wright, T.P. (1936). Factors Affecting the Cost of Airplanes. Journal of the Aeronautical Sciences, 3(4), 122–128.
- Henderson, B.D. (1973). Industrial Experience, Technology Transfer, and Cost Behavior. Harvard Business School Working Paper.
- Crawford, D. (1982). Learning Curves: Theory and Practice. Journal of Cost Analysis.