DGP Dossier: synth_baseline

1. Identity & Status

DGP ID synth_baseline
Version 1.6.0
Status stable
Difficulty (1/5)
Stress Profile  overlap: moderatenoise: gaussianlinearity: lineareffect: lineartarget: both

2. What This DGP Stresses (Intent)

Baseline sanity check: if an estimator fails here, it is fundamentally broken. Intended to confirm correct implementation under ideal linear, well-behaved conditions.

3. Identification Assumptions (Explicit)

  • Selection on observables holds.
  • Overlap is moderate (propensity bounded).
  • SUTVA holds.

4. Mathematical Specification

Covariates: \(X_1, X_2, X_3, X_4, X_5 \sim \mathcal{N}(0, 1^2)\) independently. Only \(X_1, X_2\) drive outcomes and treatment.

Outcome (control): \[\mu_0(X) = 1 + X_1 + 0.5 X_2\]

Propensity: \[p(X) = \text{expit}(0.5 X_1 - 0.5 X_2)\]

Treatment effect: \[\tau(X) = 1 + 0.5 X_1\]

Potential Outcomes: \[Y_0 = \mu_0(X) + \varepsilon_0\] \[Y_1 = \mu_0(X) + \tau(X) + \varepsilon_1\] where \(\varepsilon_0, \varepsilon_1 \sim \mathcal{N}(0, 0.5^2)\) are independent.

5. Oracle Truth Definition

  • True ATT is calculated as the sample mean of structural_te among treated units.
  • No Monte Carlo approximation needed for ATT (exact sample truth).

6. Visual Diagnostics (n = 5000)

7. Empirical Validation

We expect correctly specified OLS (lm_att) and the oracle to be essentially unbiased on this baseline.

Empirical validation (n=5000, seeds=1:10)
estimator_id mean_bias rmse
lm_att 0.002 0.012
oracle_att 0.000 0.000

8. Failure Mode Summary

  • Naive estimators (unadjusted) fail due to confounding.
  • L2 estimators succeed (linear surface).
  • Propensity estimators succeed (moderate overlap).

9. Implementation Reference

  • Code: R/dgp-synth-baseline.R (v1.6.0)
  • Registry: cs_dgp_registry() entry for synth_baseline
  • Oracle: true_att computed from structural_te among treated
  • Oracle truth: cs_get_oracle_qst("synth_baseline", version = "1.6.0")
  • Airlock: oracle columns removed unless explicitly allowed

10. Validation Checklist

11. Changelog

  • v1.0 dossier: Initial dossier following Standard Template v1.0
  • v1.6.0: Implemented Common Random Numbers (CRN) for Oracle generation. This reduces Monte Carlo variance of the QST contrast; it does not eliminate empirical-quantile sampling uncertainty.

Appendix: Implementation

Source code for: dgp_synth_baseline_v160

function (n, seed = NULL, include_truth = TRUE, oracle_only = FALSE) 
{
    if (!is.null(seed)) {
        cs_set_rng(seed)
    }
    X1 <- stats::rnorm(n, mean = 0, sd = 1)
    X2 <- stats::rnorm(n, mean = 0, sd = 1)
    if (!isTRUE(oracle_only)) {
        X3 <- stats::rnorm(n, mean = 0, sd = 1)
        X4 <- stats::rnorm(n, mean = 0, sd = 1)
        X5 <- stats::rnorm(n, mean = 0, sd = 1)
    }
    mu0 <- 1 + X1 + 0.5 * X2
    tau <- 1 + 0.5 * X1
    p <- stats::plogis(0.5 * X1 - 0.5 * X2)
    w <- stats::rbinom(n, size = 1, prob = p)
    eps0 <- stats::rnorm(n, mean = 0, sd = 0.5)
    if (isTRUE(oracle_only)) {
        eps1 <- eps0
    }
    else {
        eps1 <- stats::rnorm(n, mean = 0, sd = 0.5)
    }
    y0 <- mu0 + eps0
    y1 <- mu0 + tau + eps1
    if (isTRUE(oracle_only)) {
        return(list(df = tibble::tibble(w = w, y0 = y0, y1 = y1)))
    }
    y <- ifelse(w == 1, y1, y0)
    true_att <- cs_true_att(structural_te = tau, w = w)
    true_qst <- if (isTRUE(include_truth)) 
        cs_get_oracle_qst("synth_baseline", version = "1.6.0")
    else NULL
    list(df = tibble::tibble(y = y, w = w, y0 = y0, y1 = y1, 
        p = p, structural_te = tau, X1 = X1, X2 = X2, X3 = X3, 
        X4 = X4, X5 = X5), true_att = true_att, true_qst = true_qst, 
        meta = list(dgp_id = "synth_baseline", version = "1.6.0", 
            type = "synthetic", params = list(n = n, seed = seed), 
            structural_te = tau))
}
<bytecode: 0x5642b9d1dc98>
<environment: namespace:CausalStress>