---
title: "DP Regression and Privacy-Aware Confidence Intervals"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Regression Guide}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(collapse = TRUE, comment = "#>")
```

```{r setup}
library(DPrivStats)
set.seed(7)
```

## Closed-form DP linear regression

`dp_lm()` fits OLS on clipped data and releases coefficients with the
analytic Gaussian mechanism calibrated to the L2 sensitivity
$\Delta_2 = C \cdot D / \lambda_{\min}(X^\top X)$ (see
`?dp_lm_sensitivity`).

```{r}
data(example_microdata)
fit <- dp_lm(income ~ education + age + hours, example_microdata,
             epsilon = 2.0, delta = 1e-6,
             bounds = list(y = c(0, 500000)))
fit
```

## Privacy-aware confidence intervals

Standard intervals fail under DP because the point estimate is biased by
privacy noise and the standard error is itself privatized. `dp_confint()`
adds the known privacy-noise variance to the sampling variance:

```{r}
ci <- dp_confint(fit)
ci
```

Bootstrap alternatives:

```{r}
dp_confint(fit, method = "parametric_bootstrap", B = 200)
```

## DP-SGD for GLMs

For logistic regression, `dp_glm()` implements DP-SGD with per-sample
gradient clipping:

```{r}
d <- transform(example_microdata,
               high_income = as.numeric(income > 60000))
glm_fit <- dp_glm(high_income ~ education + age, d, binomial(),
                  epsilon = 2.0, delta = 1e-6,
                  max_grad_norm = 1, n_iter = 300, lr = 0.05,
                  bounds = list(y = c(0, 1)))
glm_fit
```

## Coverage validation

`validate_coverage()` checks that the analytical intervals attain nominal
coverage across Monte Carlo replicates:

```{r}
gen <- function(n) {
  data.frame(x = rnorm(n, 2, 1))
}
set.seed(1)
vc <- validate_coverage(y ~ x, c(`(Intercept)` = 1, x = 2),
                        sigma = 1, data_gen = gen, n = 400, n_sims = 50,
                        epsilon = 3, delta = 1e-6,
                        y_bounds = c(-20, 20))
vc$coverage_rate
```
