---
title: "Learning Curves"
output:
  html_vignette:
    fig_width: 7
    fig_height: 5
vignette: >
  %\VignetteIndexEntry{Learning Curves}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)
```

Learning curves model how efficiency or completion rate evolves over time as a team gains experience. In project management they are used to:

- **Forecast completion**: Predict when a task or deliverable will reach 100% based on past progress.
- **Identify acceleration**: Detect when a project is in its rapid-improvement phase versus plateauing.
- **Set realistic milestones**: Calibrate schedule targets against demonstrated learning rates.

## Sigmoidal Models

Sigmoidal (S-shaped) functions capture the three phases of learning: slow start, rapid improvement, and plateau. The PRA package provides three model types:

| Model | Formula | Parameters |
|-------|---------|------------|
| **Logistic** | K / (1 + exp(−r(t − t₀))) | K = ceiling; r = growth rate; t₀ = inflection time |
| **Pearl** | K / (1 + exp(−r(t − t₀))) | Same as logistic (identical functional form) |
| **Gompertz** | A · exp(−b · exp(−c · t)) | A = ceiling; c = growth rate; b = initial suppression |

**Parameter interpretation (Logistic / Pearl):**
- **K** — the maximum achievable value (e.g., 100% completion)
- **r** — how fast the S-curve rises; larger r = steeper transition
- **t₀** — the time at which the outcome is at its midpoint (inflection point)

## Example: Fitting a Logistic Model

```{r setup}
library(PRA)
```

We have weekly completion percentage data for a construction deliverable over 9 weeks.

```{r}
data <- data.frame(
  time       = 1:9,
  completion = c(5, 15, 40, 60, 70, 75, 80, 85, 90)
)
```

### Fit the Model

```{r}
fit <- fit_sigmoidal(data, "time", "completion", "logistic")
```

### Assess Fit Quality

Use `summary()` to examine the fitted coefficients, their standard errors, and the residual standard error — a measure of how closely the model matches the observed data.

```{r}
summary(fit)
```

A small residual standard error (relative to the response scale) indicates a good fit. Coefficient `t values` with |t| > 2 are statistically meaningful.

### Plot with Confidence Bands

`plot_sigmoidal()` plots the data, fitted curve, and optional confidence bounds in a single call.

```{r}
plot_sigmoidal(
  fit, data, "time", "completion", "logistic",
  conf_level = 0.95,
  main = "Logistic Learning Curve - Completion Forecast",
  xlab = "Week",
  ylab = "Completion (%)"
)
```

The shaded region is the 95% confidence band — the range within which the true fitted curve is likely to lie. Wider bands at the tails reflect greater uncertainty in extrapolated predictions.

### Predict Future Completion

Use `predict_sigmoidal()` to generate numeric forecasts, including confidence bounds for specific future time points.

```{r}
future_times <- seq(1, 12, length.out = 100)
predictions <- predict_sigmoidal(fit, future_times, "logistic", conf_level = 0.95)

knitr::kable(
  tail(round(predictions, 1), 5),
  caption = "Predicted completion (final 5 points)",
  row.names = FALSE
)
```

## Comparing All Three Model Types

Different model types can produce different forecasts, especially in the tails. It is good practice to fit multiple models and compare their goodness-of-fit.

```{r warning=FALSE}
fit_logistic <- fit_sigmoidal(data, "time", "completion", "logistic")
fit_pearl <- fit_sigmoidal(data, "time", "completion", "pearl")
fit_gompertz <- fit_sigmoidal(data, "time", "completion", "gompertz")
```

```{r}
# Residual standard errors for comparison
rse <- function(fit) summary(fit)$sigma

comparison <- data.frame(
  Model = c("Logistic", "Pearl", "Gompertz"),
  Residual_StdError = round(c(rse(fit_logistic), rse(fit_pearl), rse(fit_gompertz)), 3)
)
knitr::kable(comparison, caption = "Model Fit Comparison (lower RSE = better fit)")
```

Now plot all three fits side by side:

```{r}
x_seq <- seq(1, 12, length.out = 200)

pred_log <- predict_sigmoidal(fit_logistic, x_seq, "logistic")
pred_prl <- predict_sigmoidal(fit_pearl, x_seq, "pearl")
pred_gom <- predict_sigmoidal(fit_gompertz, x_seq, "gompertz")

# Base plot with observed data
plot(data$time, data$completion,
  pch = 16, xlim = c(1, 12), ylim = c(0, 105),
  main = "Learning Curve: Model Comparison",
  xlab = "Week", ylab = "Completion (%)"
)
lines(pred_log$x, pred_log$pred, col = "steelblue", lwd = 2)
lines(pred_prl$x, pred_prl$pred, col = "tomato", lwd = 2, lty = 2)
lines(pred_gom$x, pred_gom$pred, col = "darkgreen", lwd = 2, lty = 3)
legend("bottomright",
  legend = c("Logistic", "Pearl", "Gompertz"),
  col = c("steelblue", "tomato", "darkgreen"),
  lty = c(1, 2, 3), lwd = 2, bty = "n"
)
```

**Note:** Logistic and Pearl share the same functional form and will produce identical fits on the same data. Gompertz has a different shape, its inflection point occurs earlier and the curve is asymmetric, making it better suited for processes that accelerate quickly early on.

## Summary

The sigmoidal workflow in PRA:

1. `fit_sigmoidal()` — fit a model to observed time-completion data
2. `summary(fit)` — inspect coefficient estimates and goodness-of-fit
3. `predict_sigmoidal()` — generate numeric forecasts with optional confidence bounds
4. `plot_sigmoidal()` — visualize the fit and confidence band

Choose the model type based on the shape of your data and theoretical expectations about the learning process.
