



| DGP ID | synth_placebo_nonlinear |
| Version | 1.3.0 |
| Status | experimental |
| Difficulty | ★★☆☆☆ (2/5) |
| Stress Profile | overlap: moderatenoise: gaussianlinearity: smootheffect: constanttarget: both |
Intent: The “Hallucination Test.” The outcome surface is smooth but highly nonlinear (\(\mu_0(X) = \sin(X_1) + \cos(X_2)\)). There is no treatment effect.
The Scientific Question: “Does the estimator mistake background structure for a signal?” Flexible ML estimators (like BART or Forests) risk overfitting the “wiggles” of the outcome surface and attributing some of that variance to the treatment indicator. This tests for “False Discovery via Overfitting.”
Covariates: \(X_1, X_2, X_3, X_4, X_5 \sim \mathcal{N}(0, 1^2)\) independently.
Outcome (control): \[\mu_0(X) = \sin(X_1) + \cos(X_2)\]
Propensity: \[p(X) = \text{expit}(0.5 X_1 - 0.5 X_2)\]
Treatment effect (sharp null): \[\tau(X) \equiv 0\]
Noise is Gaussian: \(\varepsilon \sim \mathcal{N}(0, 0.5^2)\) and \(Y_1 \equiv Y_0\) pathwise.




We validate only the oracle estimator to keep builds fast.
| mean_bias | rmse |
|---|---|
| 0 | 0 |
R/dgp-synth-placebo-nonlinear.R (v1.3.0)cs_dgp_registry() entry for synth_placebo_nonlineartrue_att = 0, true_qst = 0Source code for: dgp_synth_placebo_nonlinear_v130
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)
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 <- sin(X1) + cos(X2)
tau <- rep(0, n)
p <- stats::plogis(0.5 * X1 - 0.5 * X2)
w <- stats::rbinom(n, size = 1L, prob = p)
eps <- stats::rnorm(n, mean = 0, sd = 0.5)
y0 <- mu0 + eps
y1 <- y0
if (isTRUE(oracle_only)) {
return(list(df = tibble::tibble(w = w, y0 = y0, y1 = y1)))
}
y <- ifelse(w == 1L, y1, y0)
true_att <- cs_true_att(structural_te = tau, w = w)
true_qst <- if (isTRUE(include_truth))
cs_get_oracle_qst("synth_placebo_nonlinear", version = "1.3.0")
else NULL
out <- 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_placebo_nonlinear", version = "1.3.0",
type = "synthetic", params = list(n = n, seed = seed),
structural_te = tau))
cs_check_dgp_synthetic(out)
out
}
<bytecode: 0x5651a528e7a8>
<environment: namespace:CausalStress>