
A Fixed, Matched-Pair Design with Greedy Which-Member-Treated Optimization
Source:R/design_fixed_matching_greedy_pair_switching.R
DesignFixedMatchingGreedyPairSwitching.RdA fixed-sample-size DesignFixed that combines
DesignFixedBinaryMatch's non-bipartite
matched-pair structure with DesignFixedGreedy's
greedy imbalance-minimization search, restricted so every move respects the pairing:
subjects are first paired by covariate closeness (as in
DesignFixedBinaryMatch), guaranteeing exactly one treated and one control
subject per pair; then, rather than assigning within-pair treatment status by a coin
flip, the greedy search (greedy_design_search_cpp(), pair-constrained mode)
chooses which member of each pair is treated so as to directly minimize the
same aggregate covariate-imbalance objective as
DesignFixedGreedy (squared Mahalanobis distance
or sum of absolute standardized mean differences between the treated and control
group means) across the whole sample, not just within each pair. This targets
both close within-pair matches (from the matching step) and low aggregate covariate
imbalance (from the greedy refinement) simultaneously — a strictly more constrained
search than plain DesignFixedGreedy, since only the \(2^{n/2}\)
which-member-treated assignments consistent with the fixed pairing are considered,
rather than all \(\binom{n}{n/2}\) balanced allocations.
Search algorithm. Pairing is computed by
compute_binary_match_structure() exactly as in
DesignFixedBinaryMatch (Mahalanobis or
Euclidean distance per objective), lazily on first draw and cached in
private$bms. Given the pairing, each replicate search initializes with a
random coin flip per pair (which member starts treated), then in exhaustive mode
(n_iter = Inf, default) repeatedly finds and applies the single pair-flip that
most decreases the imbalance objective, stopping at a strict local optimum (or runs
exactly n_iter random-pair stochastic flip-if-improving steps otherwise, with
patience-based early stopping) — the same two search modes as
DesignFixedGreedy, but with moves restricted to
"flip which side of a given pair is treated" rather than "swap any treated/control
pair of subjects." Random initialization and swap selection are seeded from R's own
RNG (via greedy_design_search_cpp()'s per-thread seeding), so seed does
govern reproducibility here.
Pair-preserving bootstrap. draw_bootstrap_indices() resamples whole
matched pairs (via draw_matching_bootstrap_sample_cpp()) rather than
individual subjects, since the greedy search only ever flips which member of a pair
is treated (never crosses pairs), so \(w\) always has exactly one treated subject
per pair — the pair, not the subject, is the exchangeable resampling unit.
Constraints. Only prob_T = 0.5 is supported (the constructor errors
otherwise), and n must be divisible by 4 (draw_ws_raw() errors
otherwise); n/2 matched pairs are formed regardless of parity, but the
additional divisible-by-4 requirement is enforced by this class specifically (unlike
DesignFixedBinaryMatch, which only requires
even n).
References
Krieger, A. M., Azriel, D., and Kapelner, A. (2019). "Nearly random designs with greatly improved balance." Biometrika, 106(3), 695-701, doi:10.1093/biomet/asz026 ; Greevy, R., Lu, B., Silber, J. H., and Rosenbaum, P. (2004). "Optimal multivariate matching before randomization." Biostatistics, 5(2), 263-275, doi:10.1093/biostatistics/5.2.263 , for the matched-pair design this class refines.
Super classes
Design -> DesignFixed -> DesignFixedMatchingGreedyPairSwitching
Methods
+ inherited public methods from DesignFixed
+ inherited public methods from Design
Design$add_one_subject_response()Design$any_censoring()Design$applicable_inference_class_names()Design$assert_all_responses_recorded()Design$assert_all_subjects_arrived()Design$assert_even_allocation()Design$assert_fixed_sample()Design$capabilities()Design$check_experiment_completed()Design$draw_ws_according_to_design()Design$duplicate()Design$get_X()Design$get_X_imp()Design$get_X_raw()Design$get_design_formula()Design$get_edi_version_created()Design$get_effective_dead()Design$get_effective_time()Design$get_missingness_method()Design$get_n()Design$get_ordinal_levels()Design$get_original_ordinal_levels()Design$get_prob_T()Design$get_response_type()Design$get_response_type_original()Design$get_t()Design$get_w()Design$get_y()Design$get_y_L()Design$get_y_R()Design$get_y_original()Design$has_general_censoring()Design$incompatible_inference_classes_due_to_design_structure()Design$is_a_bernoulli_capable()Design$is_a_cluster_capable()Design$is_a_kk_matching_capable()Design$is_blocking_design()Design$is_fixed_sample_size()Design$is_matching_design()Design$prepare_for_resampling_replay()Design$randomization_family()Design$supports()Design$supports_randomization_draw()Design$supports_resampling()Design$supports_resampling_replay()Design$transform_y()Design$unavailable_inference_classes_due_to_missing_packages()Design$warm_all_subject_data_cache()
DesignFixedMatchingGreedyPairSwitching$new()
Initialize a fixed design that performs binary matching followed
by greedy which-member-treated optimization (see class documentation).
Only prob_T = 0.5 is supported, and n must be divisible by 4.
Usage
DesignFixedMatchingGreedyPairSwitching$new(
response_type,
prob_T = 0.5,
include_is_missing_as_a_new_feature = TRUE,
n,
verbose = FALSE,
objective = "mahal_dist",
n_iter = Inf,
missingness_method = "impute",
design_formula = ~.,
seed = NULL
)Arguments
response_typeThe data type of response values.
prob_TThe probability of treatment assignment. Must be
0.5.include_is_missing_as_a_new_featureFlag for missingness indicators.
nThe sample size; must be divisible by 4.
verboseA flag for verbosity.
objectiveThe covariate-imbalance objective to minimize when choosing which pair member is treated: either
"mahal_dist"(default, squared Mahalanobis distance between treated/control means, also used as the matching distance) or"abs_sum_diff"(sum of absolute standardized mean differences); see class documentation for the exact criteria.n_iterNumber of swap iterations.
Inf(default) uses exhaustive best-improvement search guaranteed to reach a strict local optimum. A positive integer runs that many stochastic random-pair iterations with patience-based early stopping.missingness_methodHow to handle missing values in covariates.
design_formulaA formula object.
seedInteger seed for reproducibility.
DesignFixedMatchingGreedyPairSwitching$supports_batch_w_pregeneration()
Returns TRUE so the calling framework pre-generates all
replicate w vectors for a simulation cell in one batched call to
greedy_design_search_cpp(), paying the one-time nbpMatching
pairing cost once per cell (cached in private$bms) and reusing it
across all replicates and the OpenMP-parallelized greedy searches, rather
than recomputing the pairing per replicate.