--- title: "06 — Record correction" author: "Pierpaolo Massoli" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{06 — Record correction} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include=FALSE} knitr::opts_chunk$set(collapse = TRUE, comment = "#>", eval = FALSE) ``` > Operational examples assume that the SSPICE project root is the working directory. Operational chunks are not executed when building the vignette because they require the project data. Standalone chunks explicitly marked `eval=TRUE` are exceptions. # Extended DAG and initial partition Step 09 inserts logical-edit nodes into the DAG and prepares the corresponding data. Step 10 checks the records and partitions them once into `EXACT` and `ERRONEOUS` records. Exact records remain unchanged and form the donor pool. Correction operates on records that were initially erroneous; a pilot limit is applied after partitioning. ```{r correction-steps} source(file.path("scripts", "09_build_extended_DAG.R")) source(file.path("scripts", "10_correct_data.R")) ``` # Configuring a pilot In the project, `correction_strata = "STRATUM"`, `correction_record_limit = 100L` and `correction_output_dir` configure the example pilot. `correction_control_args` includes temperature, penalties, minimum donor counts, seed, `use_parallel` and `parallel_workers`. Set these options in `scripts/00_config.R` before Step 10. Parallel work is distributed by record; check the effective worker count in the execution summary. Conditional distributions are precomputed from exact donors by stratum and immediate predecessor. Missing predecessors are handled using the appropriate pool of exact donors. Distinguish immutable variables (the identifier, user-specified variables, and strata when `freeze_strata = TRUE`) from variables whose category is locked. An active exogenous auxiliary variable retains its original category, whereas an inactive one may become `NA`. Logical groups have their own structural treatment; they are not generally synonymous with immutable columns. # Correction with mapped categories Supply the same `items_mapping_file` used for checking and export. Mapped variable domains and proposed values use observed dataset codes; the engine translates them when evaluating modal positions and jumps. Custom `domains` and `imputation_priors` for these variables must also use observed codes. Keep donor records in the same coding as the records to be corrected. The [Item mapping](item-mapping-02c.html) guide demonstrates correction with an irregularly coded variable held fixed. The mapping regression suite also tests filling a mapped variable while preserving its observed-code domain. VAUX/LEDIT predicates continue to refer to observed values. # Outputs and diagnosis Step 10 saves `correction_result.rds`, `corrected_questionnaire_data.rds` and CSV summaries in the configured directory. Distinguish corrected records from unresolved records and retain their link to the original row and identifier. Persistent logical-edit violations require diagnosis and appear in the quality assessment. # Full runs, batches and workers The example below uses the original extended inputs, not a dataset corrected by an earlier run. Execute it from the PROJECT root after the required steps. Use an output directory distinct from those of other experiments. ```{r full-run, eval=FALSE} run <- new.env(parent = globalenv()) sys.source("scripts/00_config.R", envir = run) run$config$correction_record_limit <- Inf run$config$correction_strata <- "STRATUM" run$config$correction_batch_size <- 100L run$config$correction_resume_batches <- FALSE run$config$correction_cache_policy <- "auto" run$config$correction_control_args$freeze_strata <- TRUE run$config$correction_control_args$use_parallel <- TRUE run$config$correction_control_args$parallel_workers <- 6L run$config$correction_output_dir <- "output/corrected-full-STRATUM" stopifnot(!dir.exists(run$config$correction_output_dir)) sys.source("scripts/10_correct_data.R", envir = run) ``` `Inf` selects all initially erroneous records. Initially exact records remain donors and must not be corrected again. A batch of 100 is the checkpoint unit; parallel work is distributed by record. The batch message appears on completion, not at startup. Before the first message, processing may include reading inputs, the initial check, donor preparation, worker startup and correction of the first batch. The initial routing-check cache and batch checkpoints are separate. `correction_cache_policy = "auto"` allows reuse of a valid initial check; it does not mean reusing a previous correction. To resume interrupted batches, use the same directory and `correction_resume_batches = TRUE`, keeping inputs and settings compatible. Do not enable resumption to compare FPROV and STRATUM in the same directory. Always inspect the cache reason, reused-batch count and effective worker count in the summary. To freeze FPROV as well when STRATUM is the stratification variable, include it explicitly in `correction_immutable_variables`. A variable's statistical role is separate from its immutable status. For a comparison that isolates the effect of stratification alone, keep the set of immutable variables the same in both runs. ## Territorial stratum codes In the supplied example, STRATUM identifies five geographical divisions of Italy: North-West (1), North-East (2), Centre (3), South (4), and Islands (5). It is used for stratification during correction. With freeze_strata = TRUE, stratum membership remains unchanged. ## Preparation before the first batch Before record correction begins, SSPICE prepares or reuses conditional distributions, donor information, variable domains and other supporting structures. Parallel execution also requires worker initialization. Step 10 performs an initial routing check unless a valid cached result is available. Preparation time depends on the number of variables and records, the number of categories and strata, and the routing structure. Computing conditional distributions can take appreciable time before the first batch starts. The first batch-completion message appears only after preparation and processing of that batch. A delay before this message does not by itself indicate that execution has stalled. Distinguish total script elapsed time from the correction time reported in the output. Their difference is not a complete measure of initialization time, because some preparation may occur within the timed correction call. Measuring individual preparation stages requires separate timing. # Controls and returned objects | Control | Default and meaning | |:--|:--| | `max_iterations = NULL` | One iteration per DAG node as the record-specific maximum; termination may occur sooner | | `initial_temperature = NULL` | Maximum of the final temperature, the floored initial constraint score, and `lambda_change * max(penalty_fill, penalty_blank, penalty_flip)` | | `final_temperature = 1e-4` | Positive temperature used after cooling | | `cooling_fraction = 0.9` | Fraction of iterations used for linear cooling | | `use_parallel = FALSE` | Sequential execution unless explicitly enabled | | `parallel_workers = NULL` | Automatic worker choice when parallel execution is enabled, capped by record count | | `beta_fill = 1` | Retained compatibility control; stored and validated but not consumed by the supplied proposal code | `beta_fill` is retained for compatibility; changing it does not alter proposals in this source version. The default maximum iteration count is a computational budget, not a guarantee of feasibility or global minimum change. Increasing it can increase run time. Keep diagnostic weights positive when interpreting zero weighted violations as logical feasibility; zero weights can hide their corresponding terms. `correct_data()` returns a list with class `sspice_correction_result`: | Component | Use | |:--|:--| | `corrected_data` | Corrected rows in the prepared representation | | `record_summary` | Per-record status and diagnostics; inspect `resolved` | | `unresolved_records` | Subset of the summary for unresolved records | | `final_routing_check` | Final record/variable violation reports | | `donor_diagnostics` | Counts of supplied and retained donors | | `control`, `strata`, `immutable_variables` | Effective correction settings | | `parallel`, `batch_manifest` | Workers, batches and checkpoint reuse | Step 10 performs the initial EXACT/ERRONEOUS split and applies the pilot limit. Calling `correct_data()` directly does not reproduce that script-level selection automatically. Its `corrected_data` corresponds to the rows passed to the function; Step 10 writes the reconstructed questionnaire output.