Changelog

v0.2.1.9000

Robustness. scfit() gains a torch_threads argument that caps torch’s intra-op thread count (the results are unchanged); the main use is torch_threads = 1 to work around the rare R-session abort some Windows users hit with torch’s default multi-threaded CPU backend (issue #7). See the Get Started chapter’s troubleshooting notes.

Attribute interactions. scfit() gains an interactions argument ("none", the default; "lowrank"; or "explicit") that adds a population-level cross-attribute term g(X) to the profile utility, with interaction_rank and lambda_V controlling the low-rank head and its ridge penalty. The default reproduces previous behavior exactly. With an interaction term, DML inference runs on the expanded linear-in-parameters representation and carries the interaction coefficients and clustered covariance on fit$interaction; the Stage-2 MAP update absorbs the cross-fitted interaction as a known per-task offset; and the index-evaluating quantities (sc_ame(), sc_counterfactual(), sc_optimal_profile(), sc_surplus(), sc_welfare_change(), and predict()) include the offset. sc_mrs() and sc_wtp() are reference-profile-specific under interactions, and importance shares stay main-effect-only.

v0.2.1

Full replication datasets. The bundled sw2022, gs2020, and br2017 datasets are now the paper’s full analysis frames, with the complete respondent moderator set (19, 22, and 23 covariates). The worked examples in this book fit the paper’s production configuration and reproduce the published estimates. The attribute columns are the paper’s analysis columns (candidate dummies for Saha-Weeks, differenced contrasts for Graham-Svolik, numeric bracket rates for Ballard-Rosa); raw convenience columns (resp_party, resp_pid7, ideo7, pid7, weight) are carried for subgroup and weighting analyses but are not part of the moderator set. bs2013 stays a lightweight teaching example. See ?sw2022, ?gs2020, ?br2017.

Quantity calls. sc_importance(design = "levels") covers continuous-attribute designs, and design = "uniform" reproduces the paper’s factor-design importance shares. sc_voteshare_contrast() returns a debiased vote share for a raw attribute-dummy contrast.

Tutorial book. The application chapters are ordered democratic norms, tax preferences, candidate choice, then climate treaties, and each closes with a short summary. A new “Estimands” chapter (7  Estimands) collects the quantities of interest into a single reference, organized by the recovery tiers of the design; “Plot options” and “Advanced options” follow it. plot_importance() gains an xlim argument (a coord_cartesian() zoom that preserves the ridgeline densities past the cap). plot_hetero() panels are now sized in proportion to each attribute group’s number of levels, and the data-overview chunks drop head() in favor of str().

v0.2.0

Survey-weighted estimands (0.2.0.9007)

  • scfit() gains respondent_weights for respondent-level survey/design weights. The weights reweight the target-population aggregation and clustered standard errors for theta, the debiased orthogonal quantities, and the production-facing plug-in summaries. They do not reweight first-stage learner training. See 7  Estimands for the formula and usage pattern.

Bundled br2017 data corrected (0.2.0.9004)

  • The source replication file stores the 45% level of the $175–375k bracket as the number 5 in its derived rate column; the bundled br2017 inherited this on 19.9% of rows. The build now rebuilds all six bracket rates from the coded variables and their value labels. Estimates involving the $175–375k bracket (and, through the design’s correlation, the revenue coefficient) change under the corrected data; 4  Example: Tax Preferences was re-rendered accordingly.
  • sc_importance() gains design = "levels" (with a levels argument) for continuous-attribute designs; the documentation now states which weighting convention reproduces the paper’s reported shares ("uniform" for factor designs, "levels" for continuous ones).

Paper-catchup release: brings the package up to the algorithmic defaults in the 2026-04 paper revision of Acharya, Hainmueller, and Xu (2026).

Major default-behavior change

  • scfit() now runs the paper’s empirical-Bayes MAP update (paper EnsC5) as the default Stage 2. The returned beta_hat is the hybrid (Stage-2-refined), task-expanded matrix that every sc_* quantity function reads. DML point estimates and clustered standard errors are unchanged on the same seed — they continue to use the Stage-1 single-DNN prediction.
  • Set stage2 = "none" on scfit() to recover v0.1 behavior exactly.

Debiased inference for the additional quantities

  • The orthogonal-score debiasing now extends beyond the average parameter to the quantities of Supplementary Materials Section C. sc_counterfactual() defaults to a debiased counterfactual probability (vartype = "orthogonal"); new sc_ame() returns a debiased structural average marginal effect on the probability scale; sc_mrs() / sc_wtp() add estimand = "population" for the debiased ratio of average parameters with a Fieller interval; and sc_importance(vartype = "orthogonal") gives the debiased attribute-importance shares. scfit() now stores a single-profile pool (object$profile_pool) for the AME integral. See 7  Estimands.

Pluggable first-stage learners

  • scfit(learner = ...) selects the first-stage estimator of \(\beta(\mathbf Z)\): "dnn" (default, the cross-fitted deep network), "enet" (cross-fitted elastic-net logit with an automatically spline-expanded moderator basis; needs glmnet), or "grf" (a generalized-random-forest local logit; needs grf). All three feed the identical DML inference; only the first stage changes. The Stage-2 refinement is specific to the network, so stage2 is forced to "none" for the alternative learners.
  • enet_alpha, enet_df, enet_interactions: the elastic-net mixing parameter and its spline basis-expansion controls (enet_df = 1 with enet_interactions = FALSE recovers a linear-in-moderators first stage). See 2  Simulated Example for a worked recovery comparison.

New scfit() arguments

  • stage2: one of "map_c5" (default), "none", "varref", "mixed_logit". The mixed-logit option implements the lme4::glmer BLUP alternative (paper Supplementary Materials) with a deterministic tryCatch fallback to the Stage-1 DNN on convergence failure.
  • stage2_seed: integer seed for the 2nd DNN in the Stage-2 ensemble (default 12345L); independent of seed, so the master-seed bit-exact determinism guarantee extends through Stage 2.

New sc_fit slots

  • beta_hat_dnn: the Stage-1 single-DNN matrix that DML used.
  • beta_hat_dnn2, beta_hat_ens, beta_hat_resp: auxiliary Stage-2 intermediates.
  • sigma_prior, sigma_post_diag: diagonal prior variance and diagonal posterior variance (from the MAP Hessian).
  • stage2_method, stage2_warnings, stage2_seed: provenance.

New which_beta argument on every quantity function

  • Each sc_* quantity now accepts which_beta = c("hybrid", "dnn"). Default "hybrid" reads the Stage-2-refined betas; "dnn" reads the Stage-1 single-DNN view.

New exports

  • sc_validate_amce(object, subgroup = NULL): pooled (and optionally subgroup) homogeneous-logit comparison against the DML \(\hat\theta\). Mirrors the paper’s Supplementary Materials Section D, where the pooled correlation on the paper’s external validation data is near 1. See [Example: Candidate Choice](#sec-sw-validate) for a worked example.

Bug guards

  • Regression test against the prototype’s 2026-04-26 prior-indexing bug.
  • Bit-exact orthogonality and determinism test suites confirm theta and vcov are invariant across Stage-2 choices on the same seed and identical across sequential vs parallel × cores.

New dependencies

  • lme4 added as Suggests (required only for stage2 = "mixed_logit").

v0.1.0

(2026-04-12) Initial release.

Estimator

  • scfit(): structural deep-learning estimator with DML inference, respondent-clustered cross-fitting, and bit-exact determinism across core counts.
  • predict.sc_fit(): forward-pass on new moderator data via newdata and type arguments.
  • keep_modules argument to persist per-fold torch modules for forward-pass prediction.

Structural quantities (21 functions)

  • Tier A (9): sc_mrs, sc_counterfactual, sc_wtp, sc_importance, sc_polarization, sc_fraction_preferring, sc_optimal_profile, sc_direction_intensity, sc_heterogeneity_test.
  • Tier B (3): sc_subgroup, sc_compensating, sc_clusters.
  • Tier C (7): sc_surplus, sc_welfare_change, sc_average, sc_indifference, sc_demand_curve, sc_decisiveness, sc_inequality.

Baselines

  • sc_baseline_logit, sc_baseline_lpm for side-by-side comparison with the structural model.

Plots (7 functions)

  • plot_amce, plot_fraction, plot_hetero, plot_subgroup, plot_importance: publication-quality diagnostic plots.
  • All accept dummies, labels, groups for customization (variable selection, display names, attribute-group faceting).
  • plot.sc_fit: beta ridgelines ("beta_ridgelines") and training loss trace ("loss_trace").

Bundled datasets

  • sw2022 (Saha & Weeks 2022): 1,191 respondents, candidate choice, 5 factor attributes, 3 moderators.
  • gs2020 (Graham & Svolik 2020): 1,605 respondents, democratic norms, 30 attribute levels (7 groups), 12 moderators.
  • br2017 (Ballard-Rosa, Martin & Scheve 2017): 2,000 respondents, tax preferences, 7 numeric attributes, 12 moderators.
  • bs2013 (Bechtel & Scheve 2013): 2,500 respondents, climate treaties, 6 attributes (including numeric cost), 3 moderators.
  • simdata: 1,000 synthetic respondents with known ground truth for validation.

Tutorial

  • 9-chapter Quarto book: installation, simulated example, four real-data worked examples (SW, GS, BR, BS), plot options reference, references, changelog.