Each control is a coverage-weighted mixture of the captured confounders plus
noise. With one confounder and coverage = omega this reduces to
the classic w_signal proxy in generate_toy_data(). Setting captured to a
strict subset of the confounders models controls that miss part of the
confounder subspace (invalidating the negative-control assumption).
Arguments
- U
n x kconfounder matrix.- covariates
Covariate data frame (unused; kept for the NC contract).
- params
List with
n_features, and optionallycoverage(scalar in[0, 1], default 0.7),captured(integer confounder indices the controls see, default all),noise_sd(default 0.3),MMCon(loading multiplier, default 1),mode(default"shared"), andnoise_cor(ap x pcorrelation matrix for correlated noise, orNULLfor independent noise).
Details
When noise_cor is supplied (a p x p correlation matrix), the noise
component is drawn from a multivariate normal with that correlation
structure, so the negative controls retain realistic cross-feature
correlations conditional on the confounder. When noise_cor is NULL
(default), the noise is independent across features.
Modes
"shared"All columns carry the same
rowMeans(U[, captured])signal. This is the original behaviour (backward-compatible) and is numerically stable, but the W matrix has only one effective dimension regardless ofn_features, so the proximal completeness condition is never binding for the matrix-bridge PGC."distinct"Column
fcaptures confoundercaptured[((f - 1) \%\% length(captured)) + 1]. Different columns therefore carry signals from different confounders, giving the W matrix genuine dimensional structure. This is the mode to use when benchmarking the completeness cliff: the matrix-bridge PGC is identified only whenn_features >= k.
