| Title: | Automated Test Assembly for Multistage Tests Using Mixed-Integer Linear Programming |
|---|---|
| Description: | Provides a suite of mixed-integer linear programming (MILP) model builders and solvers—including 'Gurobi', 'HiGHS', 'Symphony', 'GNU Linear Programming Kit (GLPK)', and 'lpSolve'—for automated test assembly (ATA) in multistage testing (MST). Offers filtering of decision variables through item–module eligibility and the application of explicit bounds to simplify the MILP model and accelerate the optimization process. Supports bottom up, top down, and hybrid assembly strategies; enemy-item and enemy-stimulus exclusions; stimulus all in/all out or partial selection; anchor item/stimulus specification; and item exposure control. Accommodates both single-objective and multi-objective optimization ('weighted sum', 'maximin', 'capped maximin', 'minimax', and 'goal programming'). Enables simultaneous assembly of multiple panels with item and stimulus content balancing and exposure control. Provides analytical evaluation of assembled MST performance within seconds. Includes tools for diagnosing infeasible optimization models by systematically identifying sources of infeasibility and reformulating models with slack variables to restore feasibility.Methods implemented in this package build on established work in optimal test assembly (van der Linden, 2005 <doi:10.1007/0-387-29054-0>), item-set constrained test assembly (van der Linden, 2000 <doi:10.1177/01466210022031697>), hybrid assembly (Xiong, 2018 <doi:10.1177/0146621618762739>), recursion-based analytic methods (Lim et al., 2021 <doi:10.1111/jedm.12276>), and classification evaluation (Rudner, 2000 <doi:10.7275/an9m-2035>; Rudner, 2005 <doi:10.7275/56a5-6b14>). |
| Authors: | Hong Chen [aut, cre] |
| Maintainer: | Hong Chen <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.1.0 |
| Built: | 2026-05-12 21:42:22 UTC |
| Source: | https://github.com/hongchen030/mstata |
Once the analytical CSEMs are derived based on recursion-based approach (Lim, 2000),
the evaluation of MST performance using classification metrics can be estimated
using Rudner's method (2000,2005). The implementation follows the same logic
as irtQ::cac_rud().
analytic_mst_classification(decision_theta_cuts, eval_tb, theta_weight)analytic_mst_classification(decision_theta_cuts, eval_tb, theta_weight)
decision_theta_cuts |
Numeric vector of classification cut theta values.
These define |
eval_tb |
A data frame containing at least the columns |
theta_weight |
A data frame containing the population distribution over the ability grid. It must have the following columns:
The |
This function evaluates classification performance without simulation. Given a set of decision cuts and conditional standard errors across a fixed ability grid, classification accuracy and consistency are computed analytically by integrating conditional classification probabilities over a population ability distribution.
The procedure consists of the following steps:
Define true classification levels:
Each ability value on the evaluation grid is assigned to a
true classification level based on the specified cut theta values.
Compute conditional classification probabilities:
For each , the probability of being classified into each level
is computed assuming a normal distribution for the reported ability
estimate:
Conditional accuracy and consistency:
Conditional classification accuracy is defined as
where is the true classification level.
Conditional consistency is defined as
representing the probability that two independent parallel administrations yield the same classification.
Marginalization over the population:
Conditional indices are integrated over a population ability distribution using externally supplied weights, yielding marginal classification accuracy, marginal classification consistency, and a confusion matrix.
A list with the following components:
A matrix giving the joint probability of true and expected classification levels. Rows correspond to true levels; columns correspond to expected levels.
A data frame of marginal classification accuracy and consistency by true level, including an overall (marginal) row.
A data frame of conditional accuracy and consistency
at each ability value .
A data frame of conditional classification probabilities
for each level at each .
The classification cut theta values used in the analysis.
Let denote an ability grid point and
the corresponding conditional standard error.
For classification cut scores , define level boundaries
.
The probability of classifying an examinee with true ability
into level is
where is the interval for level .
Conditional accuracy at is
and conditional consistency is
Let be population weights on the grid, with
.
The marginal (population) indices are the discrete weighted averages of the conditional quantities:
where is the true level implied by and the cut
scores.
If approximates a density , these correspond to
the integrals .
Rudner, L. M. (2000). Computing the expected proportions of misclassified examinees. Practical Assessment, Research, and Evaluation, 7(1). doi:10.7275/an9m-2035
Rudner, L. M. (2005). Expected classification accuracy. Practical Assessment, Research, and Evaluation, 10(1). doi:10.7275/56a5-6b14
Computes conditional bias and conditional standard error of measurement (CSEM)
for a multistage test (MST) panel using a recursion-based evaluation method.
The implementation follows the logic of irtQ::reval_mst(), propagating
score distributions stage by stage conditional on true ability ,
applying routing rules, and mapping final scores to reported ability estimates
via inverse test characteristic curves (TCCs).
analytic_mst_precision( design, exclude_pathways = NULL, assembled_panel, item_par_cols, model_col, D = 1, theta = seq(-3, 3, 0.1), range_tcc = c(-5, 5), rdps, tol = 1e-04 )analytic_mst_precision( design, exclude_pathways = NULL, assembled_panel, item_par_cols, model_col, D = 1, theta = seq(-3, 3, 0.1), range_tcc = c(-5, 5), rdps, tol = 1e-04 )
design |
A character string specifying the MST design. The string encodes the number of modules per stage and may use commas, dashes, or slashes as separators. For example, "1-3-3", "1,3,3", and "1/3/3" all define an MST with 1 module in stage 1, 3 modules in stage 2, and 3 modules in stage 3. |
exclude_pathways |
Optional character vector specifying disallowed pathways.
Each element must be a string of the form "x-y-z", where each number
refers to a module index at the corresponding stage. If |
assembled_panel |
A "mstATA_panel" object returned by assembled_panel(). All panels share identical module and pathway structure. |
item_par_cols |
A named list defining the IRT parameter columns
required for each supported model. The list names must exactly match
the model identifiers specified in |
model_col |
A character string specifying the column name in either
|
D |
Scaling constant used in the IRT model. Default is D=1 (for logistic metric); D=1.702 yields approximately the normal metric. |
theta |
Numeric vector specifying the ability grid used to construct ICCs. Defaults are -3 to 3 with 0.1 interval. |
range_tcc |
Numeric vector giving the search interval for inverse TCC evaluation (length = 2). Defaults is (-5,5). |
rdps |
List of routing cuts on the theta scale. |
tol |
A convergence tolerance used for inverse TCC calculations. Default is 1e-4. |
1. Recursion-based analytic evaluation
The analytic evaluation proceeds in four conceptual steps:
Module score distributions
For each module, the conditional score distribution
is computed from item response category
probabilities.
Stage-wise recursion with routing
Joint (cumulative) score distributions are built recursively across stages. At each stage, examinees are deterministically assigned to next-stage modules based on the comparison between their ITCC estimates and the predefined cut points for that stage.
Exact joint score propagation
For each valid routing branch, the cumulative score distribution is updated by convolving the previous-stage score distribution with the score distribution of the next module.
Inverse TCC and conditional moments
Final pathway-specific score distributions are mapped to reported ability
estimates via inverse test characteristic curves (ITCCs). The conditional
mean, conditional bias and conditional variance (CSEM) are
computed at each true ability value .
2. Conditional bias and conditional SEM
Let denote the cumulative test score and
the ITCC estimator.
For each true ability value , this function computes:
where the expectation is taken with respect to the exact joint score distribution induced by the MST routing rules.
A list with components:
prefix-to-module lookup tables by stage.
ITCC estimates for each stage.
Module-level score distributions.
Stage-wise joint score distributions by prefix.
A data frame with columns
theta, mu, sigma2, bias, and csem.
Let denote a true ability value on a discrete grid.
Consider a multistage test (MST) consisting of stages, where at each
stage exactly one module is administered according to deterministic routing
rules that map observed cumulative scores to modules.
(a) Module score distributions
For module , let denote the module score. Conditional on
ability , the module score distribution is
which is obtained by analytically combining item response category probabilities under the specified IRT model. This distribution is computed independently for each module using module_score_dist().
(b) Stage-wise recursion with routing
Let denote the cumulative score after stage .
At each stage , examinees are assigned to a
next-stage module based on the comparison between
the ITCC estimates and the cut theta points.
The routing rule can be written as a deterministic mapping
where maps observed cumulative scores to modules at stage
.
(c) Exact joint score propagation
For a given routing branch induced by the realized cumulative score, the cumulative score evolves as
Conditional on , the joint score distribution is updated
analytically via convolution:
where the sum is taken over all reachable values of along the
routing branch.
(d) Inverse TCC and conditional moments
Let denote the final cumulative test score, and let
be the reported ability estimate obtained by applying the
inverse test characteristic curve (TCC) associated with the administered
pathway determined by the routing rules.
For each true ability value , the conditional mean and conditional
variance of the reported ability are defined as
where the expectation is taken with respect to the exact joint distribution
induced by the MST routing rules.
Explicitly,
Lim, H., Davey, T., & Wells, C. S. (2020). A recursion-based analytical approach to evaluate the performance of MST. Journal of Educational Measurement, 58(2), 154–178. doi:10.1111/jedm.12276
Constructs a panel-centric representation of an assembled multistage panel (MST) from the solver output. The function extracts binary decision variables, maps them to items in the item pool, and organizes the results by panel, module, and pathway.
This function is typically called after solve_model() and is intended
for post-solution interpretation, diagnostics, and reporting.
assembled_panel(x, result)assembled_panel(x, result)
x |
An object of class |
result |
A solver result returned by |
The workflow is:
Extract item-module-panel binary decision variables with value 1 from the solver solution.
Parse decision variable names of the form
x[module_id, item_id, panel_id].
Map internal item indices (item_id) to item-module-panel identifiers.
Merge selected items with the item pool to attach item attributes.
For each panel:
Construct ItemsInModules, listing items selected in each module.
Construct ItemsInPathways, listing items associated with each
pathway based on the pathway-module mapping.
If pathway or module labels are available in x$PathwayIndex and
x$ModuleIndex, labels for modules/pathways are attached.
An object of S3 class mstATA_panel with a named list with one element per panel:
Panel_1, Panel_2, ....Each panel is a list with components:
A data frame containing selected items grouped by
module. Columns include item_name, item_id,
varname, module_id, and all item attributes from the item pool.
A data frame containing selected items grouped by
pathway. Columns include item_name, item_id,
varname, pathway_id, and all item attributes from the item pool.
A precomputed multistage testing (MST) panel assembled using the minimax objective formulation (two_dev) described in the Formulation for Multiple Objectives vignette.
binary_minimax_panelbinary_minimax_panel
An object of class mstATA_panel.
This object is included to avoid long solver runtimes during vignette building and package checking.
Generated using mstATA::assembled_panels() and mstATA::solve_model()with the HiGHS solver.
A precomputed multistage testing (MST) panel assembled using the bottom-up strategy demonstrated in the Three ATA Strategies Vignette.
BU13_panelBU13_panel
An object of class mstATA_panel.
Generated using mstATA::assembled_panels() and mstATA::solve_model()with the HiGHS solver.
The capped maximin strategy balances multiple competing objectives by maximizing a common lower bound across multiple objective terms, while simultaneously limiting how far any single objective term may exceed that bound.
Compared to the classical maximin formulation–where overflow control may be
imposed through a user-specified upper bound –the capped maximin
strategy treats as a decision variable and optimizes it
jointly with the common floor value . The resulting objective to be maximized,
, balances improving the worst-performing objective
while penalizing excessive dominance by any single objective.
capped_maximin_obj(x, multiple_terms, strategy_args = list())capped_maximin_obj(x, multiple_terms, strategy_args = list())
x |
An object of class |
multiple_terms |
A list of objective terms created by |
strategy_args |
A named list of strategy-specific arguments used by the capped_maximin aggregation. Supported fields:
|
1. Overview
The capped maximin strategy applies when there are two or more objective terms, each representing a linear score of the form
where is the coefficient vector constructed by
objective_term(), and denotes the binary
item-module decision variables.
The goal is to:
maximize the minimum normalized performance across all objective terms, and
restrict excessive dominance of any single objective via an overflow band.
Unlike the classical maximin strategy (where is user-specified or
infinite), capped maximin treats as a decision variable and
optimizes it jointly with the common floor.
Each objective term is created using objective_term() and may differ in attribute type, attribute level, and target value.
Key characteristics for each objective term:
(1) Requirement type
Categorical: maximize the number of items from a specified category level; or
Quantitative: maximize the sum of item-level quantitative attributes (e.g., difficulty, discrimination, item information).
(2) Application level
"Module-level" – only items in a specified module contribute;
"Pathway-level" – items in all modules belonging to a pathway;
"Panel-level" – all item selections in the panel contribute.
(3) Objective type
The capped maximin strategy supports relative objectives only: maximize
Absolute (goal-based) objectives of the form
are not permitted under capped maximin.
2. Proportions and normalization
Each objective term may be associated with a positive proportion
. These proportions encode the relative scaling of each objective.
By default, for all terms.
3. Overflow control via
The capped maximin formulation introduces a common overflow variable
, yielding the constraints:
These constraints ensure that:
all objective terms achieve a highest value proportional to a common normalized floor
, and
no term exceeds the highest value by more than .
A list of class "compiled_objective"
A character vector indicating the specifications in each row of A_binary
A data.frame summarizing the constraint specification, including
the requirement name, attribute, constraint type, application level,
operator, and the number of constraint rows generated.
A sparse binary matrix representing the linear constraint coefficients.
A sparse constraint matrix (class "Matrix") for
continuous decision variables. Must have the same number of rows as
A_binary.
A character vector of constraint operators, one per row of A_binary.
A numeric vector of right-hand-side values for the constraints.
A numeric vector of objective coefficients for binary decision variables.
A numeric vector of objective coefficients for continuous decision variables.
Always "max" for the capped_maximin strategy.
Character vector indicating the names of new decision variables, same length as ncol(A_real).
A character vector of "C" (continuous), same length as ncol(A_real).
List of strategy metadata.
Let denote the vector of binary item-module decision variables.
For each objective term , define:
Introduce two continuous decision variables:
– the common normalized floor value;
– the maximum allowable overflow above the floor.
The capped maximin optimization problem is:
subject to:
This formulation encourages balanced improvement across multiple objectives while penalizing excessive disparity among them.
data("mini_itempool") # MST 1-2-3 design, S1R-S2E-S3H, S1R-S2H-S3E pathways are not allowed. test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", exclude_pathway = c("1-1-3", "1-3-1"), pathway_length = 8 ) # Example: Maximize the minimum TIF across theta = -1, 0, 1 theta_n1 <- objective_term( x = test_mstATA, attribute = "iif(theta=-1)", applied_level = "Module-level", which_module = 1, sense = "max" ) theta_0 <- objective_term( x = test_mstATA, attribute = "iif(theta=0)", applied_level = "Module-level", which_module = 1, sense = "max" ) theta_1 <- objective_term( x = test_mstATA, attribute = "iif(theta=1)", applied_level = "Module-level", which_module = 1, sense = "max" ) capped_maximin_obj(x = test_mstATA, multiple_terms = list(theta_n1,theta_0,theta_1))data("mini_itempool") # MST 1-2-3 design, S1R-S2E-S3H, S1R-S2H-S3E pathways are not allowed. test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", exclude_pathway = c("1-1-3", "1-3-1"), pathway_length = 8 ) # Example: Maximize the minimum TIF across theta = -1, 0, 1 theta_n1 <- objective_term( x = test_mstATA, attribute = "iif(theta=-1)", applied_level = "Module-level", which_module = 1, sense = "max" ) theta_0 <- objective_term( x = test_mstATA, attribute = "iif(theta=0)", applied_level = "Module-level", which_module = 1, sense = "max" ) theta_1 <- objective_term( x = test_mstATA, attribute = "iif(theta=1)", applied_level = "Module-level", which_module = 1, sense = "max" ) capped_maximin_obj(x = test_mstATA, multiple_terms = list(theta_n1,theta_0,theta_1))
A precomputed multistage testing (MST) panel assembled using the capped_maximin objective formulation described in the Formulation for Multiple Objectives vignette.
capped_maximin_panelcapped_maximin_panel
An object of class mstATA_panel.
This object is included to avoid long solver runtimes during vignette building and package checking.
Generated using mstATA::assembled_panels() and mstATA::solve_model()with the HiGHS solver.
Diagnoses infeasibility in an mstATA_model by testing whether a
user-specified combination of constraint blocks, together with the
core set of constraints, results in an infeasible model.
The full model must be infeasible. A reduced model is constructed that
always includes the core constraints (objective-related constraints and
essential MST structure constraints) and additionally includes the
constraint blocks specified in con_blocks. The solver status of
this reduced model is then evaluated.
check_comblock_feasibility(model_spec, con_blocks, solver, time_limit = 99999)check_comblock_feasibility(model_spec, con_blocks, solver, time_limit = 99999)
model_spec |
An object of class |
con_blocks |
An integer vector giving the indices of constraint
blocks
(rows of |
solver |
A character string indicating which solver to use.
One of |
time_limit |
The maximum amount of computation time allocated to the solver. Default is 99999 seconds. |
The reduced model always includes a fixed core set of constraints:
Objective-related constraints.
Essential MST structure constraints (e.g., module-/pathway-level item count constraints, routing decision points constraints, item reusage within a panel).
The constraint blocks specified in con_blocks are added to this
core simultaneously and tested as a group. This function does not
perform a one-at-a-time or incremental check; instead, it evaluates the
feasibility of the combined block set.
This function is primarily intended for second-stage infeasibility diagnostics, such as verifying suspected conflicting constraint combinations or validating results from block-wise (additive or subtractive) diagnostic procedures.
A list with the following elements:
Character vector of requirement names corresponding
to con_blocks.
Solver status returned for the reduced model (e.g.,
"INFEASIBLE", "OPTIMAL", "FEASIBLE").
check_singleblock_feasibility()
Diagnoses infeasibility in an mstATA_model by solving a sequence of
reduced models. The full model must be infeasible. A core set of constraints
(objective-related constraints and essential MST structure
constraints) is checked for feasibility first. If feasible, the core set of
constraints is always included. Each remaining constraint block is then tested
individually by solving a reduced model that contains the core constraints plus
exactly one additional constraint block (i.e., non-core blocks are not accumulated).
check_singleblock_feasibility(model_spec, solver, time_limit = 99999)check_singleblock_feasibility(model_spec, solver, time_limit = 99999)
model_spec |
An object of class |
solver |
A character string indicating which solver to use.
One of |
time_limit |
The maximum amount of computation time allocated to the solver. Default is 99999 seconds. |
The core model always includes:
Objective-related constraints.
Essential MST structure constraints (e.g., module-/pathway-level item count constraints, routing decision points constraints, item reusage within a panel).
The MST structure constraints ensure that the fundamental structural requirements of the MST design are satisfied.
Specifically, MST structure constraints include:
(1) Item count constraints
(a) Number of items in each module is provided in mst_design()
One constraint is created for each module.
Each module must contain exactly the specified number of items.
(b) Number of items in each pathway is provided in mst_design().
Each pathway must contain exactly the specified number of items.
Optional stage-level structure constraints may additionally enforce:
Minimum number of items per stage.
Maximum number of items per stage.
If stage_length_bound = NULL, the following default stage-level
structure is enforced:
Each stage must contain at least one item.
Modules within the same stage must have equal length.
(2) Routing decision points constraints
These constraints are generated when rdps is provided in
mst_design().
The test information at the routing decision point between adjacent modules in the next stage is similar within a specified tolerance.
(3) Panel-level item usage constraints
These constraints are generated using panel_itemreuse_con() limiting
how many times an item may be selected across the modules and pathways contained within a single MST panel.
After checking the feasibility of the core set of constraints, all other (non-structural) constraint blocks are tested individually by adding them to the core model one at a time. This function does not attempt to diagnose infeasibility arising from interactions among multiple non-core constraint blocks.
A data frame with one row per constraint block tested.
Computes item category characteristic curves (ICCs) for dichotomous, polytomous, or mixed-format item pools. The function supports multiple IRT models simultaneously and returns category-level response probabilities for each item at specified ability points.
compute_icc(items, item_par_cols, theta, model_col, nrCat_col = NULL, D = 1)compute_icc(items, item_par_cols, theta, model_col, nrCat_col = NULL, D = 1)
items |
A data frame containing item metadata.
Each row represents an item. The data frame must include a column
specifying the item model (see |
item_par_cols |
A named list defining the IRT parameter columns
required for each supported model. The list names must exactly match
the model identifiers specified in |
theta |
A numeric vector of ability values at which the ICCs are evaluated. |
model_col |
A character string specifying the column name in
|
nrCat_col |
A character string specifying the column name in
|
D |
Scaling constant used in the IRT model. Default is D=1 (for logistic metric); D=1.702 yields approximately the normal metric. |
The output matrices returned by compute_icc() include
a fixed set of category columns (cat0, cat1, ...),
with unused categories filled with zeros to ensure consistent dimensions
across mixed-format item pools.
(1) Dichotomous models.
For the models "1PL", "RASCH", "2PL", "3PL",
and "4PL", item parameters are extended to the following four
columns:
discriminationSlope parameter ().
difficultyLocation parameter ().
guessingLower asymptote ().
upperUpper asymptote ().
Missing parameters required for a given model are automatically filled. For example, the RASCH and 1PL
models are represented with , , and .
All dichotomous item parameters are validated prior to ICC computation:
discrimination > 0
0 <= guessing <= 1
0 <= upper <= 1
guessing < upper
(2) Polytomous models.
The supported polytomous models include "GRM", "MGRM",
"PCM", "GPCM", "RSM", and "NRM". Let
denotes the number of non-baseline response
categories.
Required parameters depend on the specific model and may include
discrimination parameters and category-specific thresholds or step
parameters (e.g., betaj1, ..., betajK,
deltaj1, ..., deltajK). See Pi_internal().
A named list of matrices, one for each value in
theta. List length = the number of ability values
and List names = Character strings of the form "theta=<value>".
Each matrix entry gives the probability of responding in the
corresponding category for the given item at the specified
ability level. Matrix rows = the number of items, with row names equal to item identifiers.
Matrix columns = Response categories labeled
cat0, cat1, ..., catM.
## Example 1: Dichotomous model data("mini_itempool") compute_icc(mini_itempool,list("3PL"=c("discrimination","difficulty","guessing")), theta = c(-1,0,1),model_col = "model",D = 1.7) ## Example 2: Polytomous model (PCM) data("poly_itempool") compute_icc(poly_itempool,list("PCM"=c("deltaj1","deltaj2","deltaj3")), theta = c(-1,0,1),model_col = "model") ## Example 3: multiple IRT models (3PL + GPCM + GRM) data("Rmst_pool") compute_icc(Rmst_pool, item_par_cols = list("3PL"=c("a","b","c"), "GPCM" = c("alpha","delta1","delta2","delta3"), "GRM" = c("alpha","beta1","beta2")), theta = c(-1,0,1),model_col = "model")## Example 1: Dichotomous model data("mini_itempool") compute_icc(mini_itempool,list("3PL"=c("discrimination","difficulty","guessing")), theta = c(-1,0,1),model_col = "model",D = 1.7) ## Example 2: Polytomous model (PCM) data("poly_itempool") compute_icc(poly_itempool,list("PCM"=c("deltaj1","deltaj2","deltaj3")), theta = c(-1,0,1),model_col = "model") ## Example 3: multiple IRT models (3PL + GPCM + GRM) data("Rmst_pool") compute_icc(Rmst_pool, item_par_cols = list("3PL"=c("a","b","c"), "GPCM" = c("alpha","delta1","delta2","delta3"), "GRM" = c("alpha","beta1","beta2")), theta = c(-1,0,1),model_col = "model")
Computes item information function (IIF) values for dichotomous, polytomous, or mixed-format item pools across a set of target ability values. The function supports multiple unidimensional IRT models simultaneously and returns an item-by-theta information matrix.
compute_iif(items, item_par_cols, theta, model_col, D = 1)compute_iif(items, item_par_cols, theta, model_col, D = 1)
items |
A data frame containing item metadata.
Each row represents an item. The data frame must include a column
specifying the item model (see |
item_par_cols |
A named list defining the IRT parameter columns
required for each supported model. The list names must exactly match
the model identifiers specified in |
theta |
A numeric vector of ability values at which the IIFs are evaluated. |
model_col |
A character string specifying the column name in
|
D |
Scaling constant used in the IRT model. Default is D=1 (for logistic metric); D=1.702 yields approximately the normal metric. |
A numeric matrix of item information values, with rows corresponding to items
and columns corresponding to theta.
## Example 1: Dichotomous model data("mini_itempool") compute_iif(mini_itempool, item_par_cols = list("3PL"=c("discrimination","difficulty","guessing")), theta = c(-1,0,1),model_col = "model") ## Example 2: Polytomous model (PCM) data("poly_itempool") compute_iif(poly_itempool, item_par_cols = list("PCM"=c("deltaj1","deltaj2","deltaj3")), theta = c(-1,0,1),model_col = "model") ## Example 3: multiple IRT models (3PL + GPCM + GRM) data("Rmst_pool") compute_iif(Rmst_pool, item_par_cols = list("3PL"=c("a","b","c"), "GPCM" = c("alpha","delta1","delta2","delta3"), "GRM" = c("alpha","beta1","beta2")), theta = c(-1,0,1),model_col = "model")## Example 1: Dichotomous model data("mini_itempool") compute_iif(mini_itempool, item_par_cols = list("3PL"=c("discrimination","difficulty","guessing")), theta = c(-1,0,1),model_col = "model") ## Example 2: Polytomous model (PCM) data("poly_itempool") compute_iif(poly_itempool, item_par_cols = list("PCM"=c("deltaj1","deltaj2","deltaj3")), theta = c(-1,0,1),model_col = "model") ## Example 3: multiple IRT models (3PL + GPCM + GRM) data("Rmst_pool") compute_iif(Rmst_pool, item_par_cols = list("3PL"=c("a","b","c"), "GPCM" = c("alpha","delta1","delta2","delta3"), "GRM" = c("alpha","beta1","beta2")), theta = c(-1,0,1),model_col = "model")
Concatenates enemy sets produced by create_enemy_sets().
Enemy sets from each source are appended without modification, while
pairwise enemy relationships are unioned across all inputs.
No transitive closure or set expansion is performed.
concat_enemy_sets(...)concat_enemy_sets(...)
... |
One or more enemy relationships returned by
|
Suppose source A defines five enemy sets and source B defines two enemy sets.
The resulting object will contain seven enemy sets, formed by simple
concatenation of the input EnemySet components.
The ExclusionPair component of the result is the union of all unique,
unordered pairwise enemy relationships across inputs.
Importantly, no transitive inference is applied. If item A is an enemy of B and item B is an enemy of C (possibly from different sources), this function does not infer that A is an enemy of C.
This function is intended for situations where enemy relationships are defined from multiple independent sources (e.g., similarity, cluing, or security rules) and must be preserved exactly as specified.
A list with components:
A two-column character matrix of unioned enemy pairs.
A list of enemy sets formed by concatenating all inputs.
## Example: combining multiple sources of enemy relationships ## Enemy relationships based on similarity similarity <- create_enemy_sets( id_col = mini_itempool$item_id, enemy_col = mini_itempool$enemy_similarity ) ## Enemy relationships based on cluing cluing <- create_enemy_sets( id_col = mini_itempool$item_id, enemy_col = mini_itempool$enemy_cluing ) ## Combine all enemy relationships into a single enemy set enemy_all <- concat_enemy_sets( similarity, cluing ) enemy_all## Example: combining multiple sources of enemy relationships ## Enemy relationships based on similarity similarity <- create_enemy_sets( id_col = mini_itempool$item_id, enemy_col = mini_itempool$enemy_similarity ) ## Enemy relationships based on cluing cluing <- create_enemy_sets( id_col = mini_itempool$item_id, enemy_col = mini_itempool$enemy_cluing ) ## Combine all enemy relationships into a single enemy set enemy_all <- concat_enemy_sets( similarity, cluing ) enemy_all
Create pairwise enemy relationships and corresponding enemy sets for items or stimuli based on metadata in the item pool.
This function parses enemy information from two aligned vectors– an identifier column and an enemy-specification column–and returns (1) a matrix of unique enemy pairs and (2) a list of enemy sets. Enemy pairs represent item or stimulus combinations that must not be selected together. See Details.
The function is intended as a preprocessing step prior to constructing enemy-item or enemy-stimulus exclusion constraints.
create_enemy_sets(id_col, enemy_col, sep_pattern = ",")create_enemy_sets(id_col, enemy_col, sep_pattern = ",")
id_col |
A character vector of item or stimulus identifiers (e.g., item IDs or stimulus names). |
enemy_col |
A character vector specifying enemy items or stimuli
associated with each element of |
sep_pattern |
A regular expression used to split multiple enemy
identifiers within |
1. Enemy definition
Two items or two stimuli are considered enemies if they must not appear together. Typical reasons include:
High surface similarity or paraphrasing
Shared clues or solution pathways
Security, exposure, or operational constraints
The ExclusionPair component is the authoritative definition
of explicitly declared enemy relationships. Each row represents a single,
directly specified pairwise exclusion.
The EnemySet component provides a grouped representation of enemy
relationships for constraint construction. Enemy sets may include items
or stimuli that are connected through one or more pairwise exclusions in
ExclusionPair. Formally, each enemy set corresponds to a connected
component of the graph induced by ExclusionPair.
2. Interpretation of enemy relationships
Enemy relationships specified through enemy_col are interpreted
transitively. That is, if item/stimulus A is an enemy of B, and
B is an enemy of C, then A, B, and C are merged into a single
enemy set. From each enemy set, at most one item or stimulus
may be selected.
This conservative interpretation prevents indirect information leakage or similarity chains that may not be obvious from pairwise specifications alone.
3. Important modeling note
If users intend different types of enemy relationships that should not propagate transitively, they should encode them in separate columns of the item pool.
For example:
Item A is an enemy of item B because they are too similar.
Item B is an enemy of item C because they provide clues to each other.
The user does not believe that item A and item C should be treated as enemies.
In this case, a safer modeling strategy is:
Encode the A-B enemy relationship in one enemy column
(e.g., enemy_similarity);
Encode the B-C enemy relationship in a different enemy column
(e.g., enemy_clueing);
Construct enemy sets separately from each column.
This approach prevents unintended transitive grouping, allowing items A and C to remain eligible for joint selection while still enforcing the intended pairwise exclusions.
In this case, users construct enemy sets separately, concatenate them using concat_enemy_sets() and supply the concatenated result to mst_design().
A list with the following components:
A two-column character matrix in which each row represents a unique pair of mutually exclusive (enemy) items or stimuli.
A list of character vectors, where each element represents a set of items or stimuli that are mutually exclusive with one another.
## Example 1: Enemy item relationships create_enemy_sets( id_col = mini_itempool$item_id, enemy_col = mini_itempool$enemy_similarity, sep_pattern = "," ) ## Example 2: Enemy stimulus relationships create_enemy_sets( id_col = reading_itempool$stimulus, enemy_col = reading_itempool$enemy_stimulus, sep_pattern = ", " )## Example 1: Enemy item relationships create_enemy_sets( id_col = mini_itempool$item_id, enemy_col = mini_itempool$enemy_similarity, sep_pattern = "," ) ## Example 2: Enemy stimulus relationships create_enemy_sets( id_col = reading_itempool$stimulus, enemy_col = reading_itempool$enemy_stimulus, sep_pattern = ", " )
Construct a stimulus-pivot item map from an item pool containing stimulus identifiers and pivot-item indicators. This function extracts the pivot item for each stimulus and identifies all items associated with that stimulus.
This function is typically used as a preprocessing step before applying any constraints related with stimuli and stimulus-based items.
create_pivot_stimulus_map( itempool, item_id_col = "item_id", stimulus, pivot_item )create_pivot_stimulus_map( itempool, item_id_col = "item_id", stimulus, pivot_item )
itempool |
A |
item_id_col |
A string giving the column name in |
stimulus |
A string giving the column name in |
pivot_item |
A string giving the column name in |
Formally, a pivot item is defined as an item that is selected if and only if its corresponding stimulus is selected. In practice, the pivot item is typically chosen as the item within a set that best represents the stimulus–identified by content experts as having the most representative content or desirable psychometric properties.
A list with the following components:
pivot_item_idA character vector of pivot item IDs, one per stimulus.
stimulus_nameA character vector giving the stimulus
identifier associated with each pivot item. The order matches
pivot_item_id.
stimulus_membersA named list. Each element contains the item
IDs belonging to a stimulus. Names match stimulus_name.
numItems_stimulusAn integer vector giving the number of
items associated with each stimulus. This is length(stimulus_members[[i]]).
itempool <- data.frame( item_id = 1:7, stimulus_id = c("S1","S1","S1","S2","S2", NA, NA), is_pivot = c("P", NA, NA, "P", NA, NA, NA) ) create_pivot_stimulus_map( itempool = itempool, item_id_col = "item_id", stimulus = "stimulus_id", pivot_item = "is_pivot" )itempool <- data.frame( item_id = 1:7, stimulus_id = c("S1","S1","S1","S2","S2", NA, NA), is_pivot = c("P", NA, NA, "P", NA, NA, NA) ) create_pivot_stimulus_map( itempool = itempool, item_id_col = "item_id", stimulus = "stimulus_id", pivot_item = "is_pivot" )
This function does not need to be called by users and is internally used by multipanel_spec(). It is a structural component of multi-panel MST assembly.
It has two roles.
Define the semantics of the solution-level indicator
variable : an item is considered used if and only if it is selected
in at least one module of at least one panel.
Constrain user-specified minimum and maximum reuse limits for each item across all panels. The total number of constraints depends on the number of items in the item pool (for min and max usage, two constraints per item).
dvlink_item_solution( x, num_panels, global_min_use = 0, global_max_use = Inf, item_min_use = NULL, item_max_use = NULL )dvlink_item_solution( x, num_panels, global_min_use = 0, global_max_use = Inf, item_min_use = NULL, item_max_use = NULL )
x |
An object of class "mstATA_design" created by mst_design(). |
num_panels |
Integer. Number of panels to be assembled. |
global_min_use |
Scalar. Minimum number of times any item may be used across panels. Default is 0. |
global_max_use |
Scalar. Maximum number of times any item may be used
across panels. Default is |
item_min_use |
Optional data frame with columns |
item_max_use |
Optional data frame with columns |
1. Specification
The constraint enforces:
Each item can be used at least a specified minimum number of times and/or no more than a specified maximum number of times across all panels.
Key characteristics:
Attribute: itemset level (item-itself set) logical (if selected, then increment reuse).
Constraints are applied at the "Solution-level".
2. Number of times an item can be selected
Global reuse limits are supplied via global_min_use and
global_max_use. These bounds apply to all items unless overridden.
Item-specific reuse limits may be supplied through:
item_min_use: a data frame with columns item_id and min
item_max_use: a data frame with columns item_id and max
The total number of constraints generated is always
where is the pool size,
corresponding to one minimum and one maximum
constraint per item.
An object of S3 class "mstATA_constraint" with named elements:
A character vector indicating the specifications in each row of A_binary
A data.frame summarizing the constraint specification, including
the requirement name, attribute, constraint type, application level,
operator, and the number of constraint rows generated.
A sparse binary matrix representing the linear constraint coefficients.
NULL for 'mstATA_constraint' object
A character vector of constraint operators, one per row of A_binary.
A numeric vector of right-hand-side values for the constraints.
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
Suppose the item pool contains (S - 1) stimulus-based item sets, indexed by
. Each stimulus has a designated pivot item,
indexed by . In addition, the pool contains a set of discrete
(non-stimulus-based) items, which are represented by a dummy stimulus
to allow a unified indexing scheme. Items belonging to stimulus
are indexed as .
Suppose there are modules in an MST panel. Let
denote the module index. Suppose
there are panels assembled in one solution. Let
denote the panel index.
Decision variable set 1: item-module-panel selection variables
For each item , = 1 if item
is selected in module of panel .
= 0 otherwise.
Decision variable set 2: solution-level item indicators
For each item , = 1 if item
is used in any module in any panel.
= 0 otherwise.
Number of times item i is selected in a solution
This constraints enforce:
ensuring consistency between panel-level selections and solution-level indicators while enforcing reuse limits.
where:
indicates whether item is selected in module
of panel ;
indicates whether item is used anywhere in the solution;
and are item-specific
reuse bounds.
These constraints are structural: they define the meaning of the solution-level indicator variables and also create constraints for the item exposure control across panels.
If , then item cannot be selected in any module
of any panel.
If , the total number of selections of item
must lie within the specified reuse bounds.
If item is not selected in any module across panels,
then must equal 0.
If item is selected in at least one module of any panel,
then must equal 1.
data("mini_itempool") test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", module_length = c(6, 4, 4, 4, 3, 3, 3) ) # Example: Allow each item to be used at most once across all panels dvlink_item_solution( x = test_mstATA, num_panels = 2, global_max_use = 1 )data("mini_itempool") test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", module_length = c(6, 4, 4, 4, 3, 3, 3) ) # Example: Allow each item to be used at most once across all panels dvlink_item_solution( x = test_mstATA, num_panels = 2, global_max_use = 1 )
Constructs linear constraints to ensure that items belonging to the same enemy set do not appear together within any assembled MST pathway (i.e., any complete test form).
Enemy items are items that:
give away the answer to one another,
are too similar in content or structure, or
should not be seen by the same examinee for security or fairness reasons.
The total number of constraints = num of enemy item sets * num of pathways
enemyitem_exclu_con(x)enemyitem_exclu_con(x)
x |
An object of class |
1. Specification
The enforced constraint is:
At most one item from the same enemy set can be selected in a pathway
The attribute is a itemset-level logical grouping: enemyitem_set defines enemy item groups in the item pool.
The constraint must be applied at "Pathway-level". Because each pathway represents the full sequence of modules that an examinee could encounter, preventing enemy items from appearing in a pathway ensures that no examinee can see more than one item from the same enemy set.
2. Logical Interpretation
For an enemy item set :If one item in the set is selected anywhere in the pathway,
all other items in the same set must be excluded from that pathway.
This ensures that at most one item from each enemy group appears in any assembled test form.
An object of S3 class "mstATA_constraint" with named elements:
A character vector indicating the specifications in each row of A_binary
A data.frame summarizing the constraint specification, including
the requirement name, attribute, constraint type, application level,
operator, and the number of constraint rows generated.
A sparse binary matrix representing the linear constraint coefficients.
NULL for 'mstATA_constraint' object
A character vector of constraint operators, one per row of A_binary.
A numeric vector of right-hand-side values for the constraints.
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
Suppose the item pool contains (S - 1) stimulus-based item sets, indexed by
. Each stimulus has a designated pivot item,
indexed by . In addition, the pool contains a set of discrete
(non-stimulus-based) items, which are represented by a dummy stimulus
to allow a unified indexing scheme. Items belonging to stimulus
are indexed as .
Suppose there are modules in an MST panel. Let
denote the module index.
Let denotes a set of items that are mutually exclusive (enemy) items.
Here:
is the binary decision variable indicating whether
item is selected into module m.
denote modules belonging to pathway r.
# Example 1: Two enemy sets: {Item1, Item2, Item3} and {Item4, Item5} data("mini_itempool") enemyitem_set<- create_enemy_sets(mini_itempool$item_id, mini_itempool$enemy_similarity, sep_pattern = ",") test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", module_length = c(4,2,2,2,2,2,2), enemyitem_set = enemyitem_set ) enemyitem_exclu_con(x = test_mstATA) # Example 2: ## Enemy relationships based on similarity similarity <- create_enemy_sets( id_col = mini_itempool$item_id, enemy_col = mini_itempool$enemy_similarity ) ## Enemy relationships based on cluing cluing <- create_enemy_sets( id_col = mini_itempool$item_id, enemy_col = mini_itempool$enemy_cluing ) ## Combine all enemy relationships into a single enemy set enemy_all <- concat_enemy_sets( similarity, cluing ) ## Use the combined enemy set in the test design test_mstATA2 <- mst_design( itempool = mini_itempool, design = "1-3-3", module_length = c(4,2,2,2,2,2,2), enemyitem_set = enemy_all ) enemyitem_exclu_con(test_mstATA2)# Example 1: Two enemy sets: {Item1, Item2, Item3} and {Item4, Item5} data("mini_itempool") enemyitem_set<- create_enemy_sets(mini_itempool$item_id, mini_itempool$enemy_similarity, sep_pattern = ",") test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", module_length = c(4,2,2,2,2,2,2), enemyitem_set = enemyitem_set ) enemyitem_exclu_con(x = test_mstATA) # Example 2: ## Enemy relationships based on similarity similarity <- create_enemy_sets( id_col = mini_itempool$item_id, enemy_col = mini_itempool$enemy_similarity ) ## Enemy relationships based on cluing cluing <- create_enemy_sets( id_col = mini_itempool$item_id, enemy_col = mini_itempool$enemy_cluing ) ## Combine all enemy relationships into a single enemy set enemy_all <- concat_enemy_sets( similarity, cluing ) ## Use the combined enemy set in the test design test_mstATA2 <- mst_design( itempool = mini_itempool, design = "1-3-3", module_length = c(4,2,2,2,2,2,2), enemyitem_set = enemy_all ) enemyitem_exclu_con(test_mstATA2)
Constructs linear constraints to ensure that stimuli belonging to the same enemy set do not appear together within any MST pathway (i.e., any complete test form).
Enemy stimuli are stimuli that should not be viewed by the same examinee for security or fairness reasons.
The total number of constraints = number of enemy stimulus sets * number of pathways.
enemystim_exclu_con(x)enemystim_exclu_con(x)
x |
An object of class |
1. Specification
The enforced constraint is:
At most one stimulus from the same enemy set can be selected in a pathway
The attribute is a itemset-level logical grouping: enemystim_set defines enemy stimulus groups in the item pool.
The constraint must be applied at "Pathway-level". Because each pathway represents the full sequence of modules that an examinee could encounter, preventing enemy stimuli from appearing in a pathway ensures that no examinee can see more than one stimulus from the same enemy set.
2. Logical Interpretation
For an enemy stimulus set :If a stimulus in the set is selected anywhere in the pathway,
all other stimuli in the same set must be excluded from that pathway.
This ensures that at most one stimulus from each enemy group appears in any assembled test form.
An object of S3 class "mstATA_constraint" with named elements:
A character vector indicating the specifications in each row of A_binary
A data.frame summarizing the constraint specification, including
the requirement name, attribute, constraint type, application level,
operator, and the number of constraint rows generated.
A sparse binary matrix representing the linear constraint coefficients.
NULL for 'mstATA_constraint' object
A character vector of constraint operators, one per row of A_binary.
A numeric vector of right-hand-side values for the constraints.
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
Suppose the item pool contains (S - 1) stimulus-based item sets, indexed by
. Each stimulus has a designated pivot item,
indexed by . In addition, the pool contains a set of discrete
(non-stimulus-based) items, which are represented by a dummy stimulus
to allow a unified indexing scheme. Items belonging to stimulus
are indexed as .
Suppose there are modules in an MST panel. Let
denote the module index.
Let denotes a set of stimuli that are mutually exclusive (enemy).
Here:
indicates whether the pivot item for stimulus
s is selected into module m, thereby indicating whether the
stimulus s is selected in that module.
denote modules belonging to pathway r.
data("reading_itempool") pivot_stim_map <- create_pivot_stimulus_map( itempool = reading_itempool, stimulus = "stimulus", pivot_item = "pivot_item" ) # Create enemy-stimulus sets enemystim_set<-create_enemy_sets( reading_itempool$stimulus, reading_itempool$enemy_stimulus, sep_pattern = "," ) test_mstATA <- mst_design( itempool = reading_itempool, design = "1-3-3", module_length = c(10,12,12,12,15,15,15), exclude_pathway = c("1-1-3", "1-3-1"), pivot_stim_map = pivot_stim_map, enemystim_set = enemystim_set ) enemystim_exclu_con(x = test_mstATA)data("reading_itempool") pivot_stim_map <- create_pivot_stimulus_map( itempool = reading_itempool, stimulus = "stimulus", pivot_item = "pivot_item" ) # Create enemy-stimulus sets enemystim_set<-create_enemy_sets( reading_itempool$stimulus, reading_itempool$enemy_stimulus, sep_pattern = "," ) test_mstATA <- mst_design( itempool = reading_itempool, design = "1-3-3", module_length = c(10,12,12,12,15,15,15), exclude_pathway = c("1-1-3", "1-3-1"), pivot_stim_map = pivot_stim_map, enemystim_set = enemystim_set ) enemystim_exclu_con(x = test_mstATA)
Computes the expected total score implied by item category probability curves. The expectation can be evaluated either at a grid point (single ICC matrix) or at an arbitrary ability value.
expected_score(icc, target_theta = NULL)expected_score(icc, target_theta = NULL)
icc |
Either a numeric matrix of item category
probabilities at a fixed ability level |
target_theta |
Optional numeric value giving the ability level at
which the expected score is to be evaluated. Required when |
1. How expected score is computed
Consider there are items. Let the score for item
be a discrete random variable taking values
. Conditional on ability ,
item responses are assumed to be locally independent, with category
probabilities
The expected score for item at ability level is
The expected total score is the sum of item-level expectations:
where denotes the total score.
This function evaluates the above expression numerically using the item category probability matrix produced by compute_icc(). Missing categories (if any) are assumed to have zero probability.
2. ICC input
(1) If icc is a matrix, the expected score is computed directly as
where denotes the probability that item
produces score at ability level .
(2) If icc is a list, the expected score function
is first evaluated on the grid encoded in
names(icc), and a continuous approximation is constructed via
linear interpolation. The expected score at target_theta is then
obtained from this interpolated test characteristic curve using stats::approxfun().
The numerical accuracy of the interpolated value depends on the density
and range of the ability grid used to construct the ICC list.
A single numeric value giving the expected total score
at the specified ability level.
## Example 1: Dichotomous model data("mini_itempool") icc_mat<-compute_icc(mini_itempool, list("3PL"=c("discrimination","difficulty","guessing")), theta = 0,model_col = "model",D = 1.7) icc_list<-compute_icc(mini_itempool, list("3PL"=c("discrimination","difficulty","guessing")), theta = seq(-5,5,0.1),model_col = "model",D = 1.7) expected_score(icc_mat[[1]]) expected_score(icc_list,target_theta=seq(-5,5,0.1)) ## Example 2: Polytomous model (PCM) data("poly_itempool") icc_mat<-compute_icc(poly_itempool, list("PCM"=c("deltaj1","deltaj2","deltaj3")), theta = 0,model_col = "model") icc_list<-compute_icc(poly_itempool, list("PCM"=c("deltaj1","deltaj2","deltaj3")), theta = seq(-5,5,0.1),model_col = "model") expected_score(icc_mat[[1]]) expected_score(icc_list,target_theta=0) ## Example 3: Mixed item format (3PL + GPCM + GRM) data("Rmst_pool") icc_mat<-compute_icc(Rmst_pool, item_par_cols = list("3PL"=c("a","b","c"), "GPCM" = c("alpha","delta1","delta2","delta3"), "GRM" = c("alpha","beta1","beta2")), theta = 0,model_col = "model") icc_list<-compute_icc(Rmst_pool, item_par_cols = list("3PL"=c("a","b","c"), "GPCM" = c("alpha","delta1","delta2","delta3"), "GRM" = c("alpha","beta1","beta2")), theta = seq(-5,5,0.1),model_col = "model") expected_score(icc_mat[[1]]) expected_score(icc_list,target_theta=0)## Example 1: Dichotomous model data("mini_itempool") icc_mat<-compute_icc(mini_itempool, list("3PL"=c("discrimination","difficulty","guessing")), theta = 0,model_col = "model",D = 1.7) icc_list<-compute_icc(mini_itempool, list("3PL"=c("discrimination","difficulty","guessing")), theta = seq(-5,5,0.1),model_col = "model",D = 1.7) expected_score(icc_mat[[1]]) expected_score(icc_list,target_theta=seq(-5,5,0.1)) ## Example 2: Polytomous model (PCM) data("poly_itempool") icc_mat<-compute_icc(poly_itempool, list("PCM"=c("deltaj1","deltaj2","deltaj3")), theta = 0,model_col = "model") icc_list<-compute_icc(poly_itempool, list("PCM"=c("deltaj1","deltaj2","deltaj3")), theta = seq(-5,5,0.1),model_col = "model") expected_score(icc_mat[[1]]) expected_score(icc_list,target_theta=0) ## Example 3: Mixed item format (3PL + GPCM + GRM) data("Rmst_pool") icc_mat<-compute_icc(Rmst_pool, item_par_cols = list("3PL"=c("a","b","c"), "GPCM" = c("alpha","delta1","delta2","delta3"), "GRM" = c("alpha","beta1","beta2")), theta = 0,model_col = "model") icc_list<-compute_icc(Rmst_pool, item_par_cols = list("3PL"=c("a","b","c"), "GPCM" = c("alpha","delta1","delta2","delta3"), "GRM" = c("alpha","beta1","beta2")), theta = seq(-5,5,0.1),model_col = "model") expected_score(icc_mat[[1]]) expected_score(icc_list,target_theta=0)
Computes normalized weights on a user-specified ability grid theta based on a chosen population distribution.
The function evaluates the specified density at each grid point and rescales the resulting values so that the weights sum to 1.
The output provides a discrete approximation of the population ability distribution and can be used for marginal
summaries in analytic classification accuracy or precision evaluation.
Supports:
Named base-R distributions via their densities (e.g., norm, t, logis, unif, beta,
gamma, lnorm,...).
Finite mixtures of named distributions
Empirical distributions via Gaussian-kernel KDE (kernel density estimation)
Weights are normalized so that sum(w) == 1. Use them to approximate expectations:
gen_weight( theta = seq(-5, 5, 0.1), dist = "norm", params = list(mean = 0, sd = 1), components = NULL, empirical_theta = NULL )gen_weight( theta = seq(-5, 5, 0.1), dist = "norm", params = list(mean = 0, sd = 1), components = NULL, empirical_theta = NULL )
theta |
Optional numeric vector specifying the ability grid at which the
population distribution is evaluated. Default is |
dist |
Character string specifying the distribution family:
one of |
params |
List of parameters for the named distribution (when |
components |
For |
empirical_theta |
For |
A dataframe with:
The supplied ability grid.
Normalized weights, sum(w) = 1.
## Standard normal population on a custom grid theta <- seq(-3, 3, by = 0.2) gen_weight(theta,dist = "norm") ## Normal population with custom parameters gen_weight( theta, dist = "norm", params = list(mean = -0.5, sd = 1.2) ) ## Empirical population via KDE gen_weight( theta, dist = "empirical", empirical_theta = rnorm(1000) ) ## Two-component mixture distribution gen_weight( theta, dist = "mixture", components = list( list(dist = "norm", params = list(mean = -1, sd = 0.8), weight = 0.4), list(dist = "norm", params = list(mean = 1, sd = 0.8), weight = 0.6) ) )## Standard normal population on a custom grid theta <- seq(-3, 3, by = 0.2) gen_weight(theta,dist = "norm") ## Normal population with custom parameters gen_weight( theta, dist = "norm", params = list(mean = -0.5, sd = 1.2) ) ## Empirical population via KDE gen_weight( theta, dist = "empirical", empirical_theta = rnorm(1000) ) ## Two-component mixture distribution gen_weight( theta, dist = "mixture", components = list( list(dist = "norm", params = list(mean = -1, sd = 0.8), weight = 0.4), list(dist = "norm", params = list(mean = 1, sd = 0.8), weight = 0.6) ) )
Create a vector representing the attribute value.
get_attribute_val(itempool, attribute, cat_level = NULL)get_attribute_val(itempool, attribute, cat_level = NULL)
itempool |
A |
attribute |
A string giving the column name in |
cat_level |
A optional character string for one category for the categorical attribute. Default is NULL, indicating the attribute is a quantitative attribute. |
A vector of item attribute values. The same length as the item pool.
If the attribute is a quantitative attribute, return a numeric vector. NA is not allowed in the quantitative attribute.
If the attribute is a categorical attribute, return a binary integer vector with 1 indicating an item having the categorical attribute, 0 indicating an item not having the categorical attribute. If an item has NA in the categorical attribute, it will be coded as 0, indicating this item not having the categorical attribute.
# Example 1, item categorical attribute data("mini_itempool") get_attribute_val(itempool = mini_itempool,attribute = "itemtype",cat_level = "MC") # Example 2, item quantitative attribute get_attribute_val(itempool = mini_itempool,attribute = "difficulty",cat_level = NULL) # Example 3: stimulus categorical attribute data("reading_itempool") get_attribute_val(itempool = reading_itempool[!is.na(reading_itempool$pivot_item),], attribute = "stimulus_type",cat_level = "history") # Example 4: stimulus quantitative attribute get_attribute_val(itempool = reading_itempool[!is.na(reading_itempool$pivot_item),], attribute = "stimulus_words")# Example 1, item categorical attribute data("mini_itempool") get_attribute_val(itempool = mini_itempool,attribute = "itemtype",cat_level = "MC") # Example 2, item quantitative attribute get_attribute_val(itempool = mini_itempool,attribute = "difficulty",cat_level = NULL) # Example 3: stimulus categorical attribute data("reading_itempool") get_attribute_val(itempool = reading_itempool[!is.na(reading_itempool$pivot_item),], attribute = "stimulus_type",cat_level = "history") # Example 4: stimulus quantitative attribute get_attribute_val(itempool = reading_itempool[!is.na(reading_itempool$pivot_item),], attribute = "stimulus_words")
Implements a goal programming objective that minimizes deviations between achieved objective values and user-specified target goals.
Multiple absolute objective terms are combined into a single optimization
problem. Each term contributes one (mode = "one_dev") or
two (mode = "two_dev") deviation variables, and the solver
minimizes a (weighted) sum of these deviations.
Weights may be assigned to individual objective terms to reflect their relative importance.
goal_programming_obj(x, multiple_terms, strategy_args = list())goal_programming_obj(x, multiple_terms, strategy_args = list())
x |
An object of class |
multiple_terms |
A list of objective terms created by
|
strategy_args |
A named list of strategy-specific arguments used by the goal_programming aggregation. Supported fields:
|
1. Overview
Goal programming applies when there are two or more objective terms, each formulated as an absolute deviation objective of the form
where:
is the linear score defined by the objective term;
is the target value specified by the test developer.
Each objective term is created using objective_term() and may differ in attribute type, attribute level, and target value.
Key characteristics for each objective term:
(1) Requirement type
Categorical: minimize deviation from a target number of items belonging to a specified category level; or
Quantitative: minimize deviation from a target sum of item-level quantitative attributes (e.g., difficulty, discrimination, or item information).
(2) Application level
"Module-level" – only items in a specified module contribute;
"Pathway-level" – items in all modules belonging to a pathway;
"Panel-level" – all item selections in the panel contribute.
(3) Objective type
The goal_programming strategy supports absolute objectives only.
2. Deviation Modes
Two deviation formulations are supported:
One-deviation mode (mode = "one_dev"):
Introduces one nonnegative deviation variable for each term:
The objective minimizes:
Two-deviation mode (mode = "two_dev"):
Introduces separate positive and negative deviation variables
and :
with constraints:
The objective minimizes:
Interpretation:
measures how much objective exceeds its target;
measures how much objective falls short;
(one-dev) measures total absolute deviation.
An object of S3 class "compiled_objective" with named elements:
A string indicating the objective function name
A data.frame summarizing the constraint specification, including
the requirement name, attribute, constraint type, application level,
operator, and the number of constraint rows generated.
A sparse binary matrix representing the linear constraint coefficients.
A sparse constraint matrix (class "Matrix") for
continuous decision variables. Must have the same number of rows as
A_binary.
A numeric vector of objective coefficients for binary decision variables.
A numeric vector of objective coefficients for continuous decision variables.
A character vector of constraint operators, one per row of A_binary.
A numeric vector of right-hand-side values for the constraints.
Always "min" for the goal_programming strategy.
A character vector of "B" (binary), same length as ncol(A_real).
Character vector indicating the names of decision variables, same length as ncol(A_real).
information about "strategy" ("goal_programming") and "strategy_args" ("mode","weights")
For each objective term :
where:
is the coefficient vector defined by the attribute,
level, and application scope;
is the vector of binary item-module-panel decision variables;
is the target value.
Auxiliary deviation variables are introduced to linearize
, and the solver minimizes a weighted sum of these
deviations.
All goal programming problems are compiled as minimization problems.
data("mini_itempool") test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", exclude_pathway = c("1-1-3", "1-3-1"), pathway_length = 8 ) obj1 <- objective_term( test_mstATA, "iif(theta=-1)", NULL, "Module-level", which_module = 1, sense = "min", goal = 12 ) obj2 <- objective_term( test_mstATA, "iif(theta=0)", NULL, "Module-level", which_module = 1, sense = "min", goal = 15 ) obj3 <- objective_term( test_mstATA, "iif(theta=1)", NULL, "Module-level", which_module = 1, sense = "min", goal = 12 ) # Example 1: One deviation per goal, equal weights goal_programming_obj( x = test_mstATA, multiple_terms = list(obj1, obj2, obj3), strategy_args = list(mode = "one_dev",weights = NULL)) # Example 2: One deviation per goal, unequal weights goal_programming_obj( x = test_mstATA, multiple_terms = list(obj1, obj2, obj3), strategy_args = list(mode = "one_dev",weights = c(1,0.5,1))) # Example 3: Two deviations per goal goal_programming_obj( x = test_mstATA, multiple_terms = list(obj1, obj2, obj3), strategy_args = list(mode = "two_dev",weights = NULL))data("mini_itempool") test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", exclude_pathway = c("1-1-3", "1-3-1"), pathway_length = 8 ) obj1 <- objective_term( test_mstATA, "iif(theta=-1)", NULL, "Module-level", which_module = 1, sense = "min", goal = 12 ) obj2 <- objective_term( test_mstATA, "iif(theta=0)", NULL, "Module-level", which_module = 1, sense = "min", goal = 15 ) obj3 <- objective_term( test_mstATA, "iif(theta=1)", NULL, "Module-level", which_module = 1, sense = "min", goal = 12 ) # Example 1: One deviation per goal, equal weights goal_programming_obj( x = test_mstATA, multiple_terms = list(obj1, obj2, obj3), strategy_args = list(mode = "one_dev",weights = NULL)) # Example 2: One deviation per goal, unequal weights goal_programming_obj( x = test_mstATA, multiple_terms = list(obj1, obj2, obj3), strategy_args = list(mode = "one_dev",weights = c(1,0.5,1))) # Example 3: Two deviations per goal goal_programming_obj( x = test_mstATA, multiple_terms = list(obj1, obj2, obj3), strategy_args = list(mode = "two_dev",weights = NULL))
A precomputed multistage testing (MST) panel assembled using the goal_programming objective formulation (one_dev) described in the Formulation for Multiple Objectives vignette.
goal_programming_panelgoal_programming_panel
An object of class mstATA_panel.
This object is included to avoid long solver runtimes during vignette building and package checking.
Generated using mstATA::assembled_panels() and mstATA::solve_model()with the HiGHS solver.
A precomputed MST panel assembled using the hybrid strategy demonstrated in the Three ATA Strategies Vignette.
Hy13_panelHy13_panel
An object of class mstATA_panel.
Generated using mstATA::assembled_panels() and mstATA::solve_model()with the HiGHS solver.
Computes the inverse Test Characteristic Curve (ITCC) by mapping each
possible observed total score to its corresponding estimated ability
value (). The inversion is performed numerically using a
dense theta grid and root-finding.
The function supports mixed-format tests, including dichotomous
(e.g., 1PL, 2PL, 3PL, 4PL) and polytomous models
(e.g., GRM, PCM, GPCM, RSM, NRM), provided the required item parameters
are correctly specified in item_par_cols.
For models with guessing (e.g., 3PL/4PL), scores below the lower
asymptote are handled using linear interpolation toward the lower
bound specified by range_tcc.
inverse_tcc( items, item_par_cols, model_col, D = 1, range_tcc = c(-5, 5), tol = 1e-04 )inverse_tcc( items, item_par_cols, model_col, D = 1, range_tcc = c(-5, 5), tol = 1e-04 )
items |
A data frame containing item metadata.
Each row represents an item. The data frame must include a column
specifying the item model (see |
item_par_cols |
A named list defining the IRT parameter columns
required for each supported model. The list names must exactly match
the model identifiers specified in |
model_col |
A character string specifying the column name in
|
D |
Scaling constant used in the IRT model. Default is D=1 (for logistic metric); D=1.702 yields approximately the normal metric. |
range_tcc |
A numeric vector of length two specifying the lower
and upper bounds of the theta search interval. The estimated theta
values are constrained within this range. Defaults to |
tol |
A numeric tolerance passed to the root-finding algorithm. Smaller values yield more precise solutions at increased computational cost. Default is 1e-4. |
A data frame with two columns:
All possible observed total scores.
Estimated theta corresponding to each total score.
Consider items are taken by an examinee. Let the score for item
be a discrete random variable taking values
, where is the maximum item score
for item i. Conditional on ability , item
responses are assumed to be locally independent, with category
probabilities
The expected score for item at ability level is
and the expected total module score (the test characteristic curve) is
where denotes the total module score.
Given a target score , the inverse TCC problem is to find
such that
Because generally has no closed-form inverse, this
function evaluates on a grid of ability values using
ICCs. A root-finding algorithm is then used to solve
on a specified ability interval.
3PL and Non-Invertible Scores
When items follow the three-parameter logistic (3PL) model with
guessing parameters , the TCC has a nonzero lower bound:
Therefore, any NC score cannot be obtained from the
TCC for any finite , and the inverse TCC is undefined
in the strict sense.
To ensure a monotone score-to-theta mapping, the minimum invertible NC score is defined as
the smallest integer strictly greater than the guessing floor.
Let denote the lower bound of the restricted
ability range (given by range_tcc[1]), and let
denote the inverse-TCC solution corresponding to score .
For any score such that , the ability
estimate is obtained by linear interpolation between
and :
This construction:
Preserves monotonicity of the score-to-theta function;
Respects the lower bound imposed by guessing;
Ensures continuity at ;
Avoids artificial extrapolation of the TCC.
Scores above the maximum attainable TCC value are mapped to
the upper bound range_tcc[2].
# Example 1: dichotomous items (guessing is not allowed) items<-data.frame(discrimination = c(1,1),difficulty = c(-1,0), model= rep("2PL",2)) inverse_tcc(items = items, item_par_cols = list("2PL"=c("discrimination","difficulty")), model_col = "model",range_tcc = c(-5,5)) # Example 2: dichotomous items, (guessing is allowed) items<-data.frame(discrimination = c(1,1),difficulty = c(-1,0),guessing = c(0.2, 0.2), model= rep("3PL",2)) inverse_tcc(items = items, item_par_cols = list("3PL"=c("discrimination","difficulty","guessing")), model_col = "model", range_tcc = c(-5,5)) # Example 3: polytomous items items <- data.frame(alphaj = c(1.169,1.052,0.828,0.892,0.965), betaj1 = c(-0.006,-2.405,-0.799,-1.148,-0.299), betaj2 = c(0.487,1.125,0.764,-0.289,1.512), model = rep("GRM",5)) inverse_tcc(items = items, item_par_cols = list("GRM"=c("alphaj","betaj1","betaj2")), model_col = "model", range_tcc = c(-5,5)) # Example 4: dichotomous and polytomous items items <- data.frame(discrimination = c(1,1,rep(NA,5)), difficulty = c(-1,0,rep(NA,5)), alphaj = c(rep(NA,2),1.169,1.052,0.828,0.892,0.965), betaj1 = c(rep(NA,2),-0.006,-2.405,-0.799,-1.148,-0.299), betaj2 = c(rep(NA,2),0.487,1.125,0.764,-0.289,1.512), model = c(rep("2PL",2),rep("GRM",5))) inverse_tcc(items = items, item_par_cols = list("2PL"=c("discrimination","difficulty"), "GRM"=c("alphaj","betaj1","betaj2")), model_col = "model", range_tcc = c(-5,5))# Example 1: dichotomous items (guessing is not allowed) items<-data.frame(discrimination = c(1,1),difficulty = c(-1,0), model= rep("2PL",2)) inverse_tcc(items = items, item_par_cols = list("2PL"=c("discrimination","difficulty")), model_col = "model",range_tcc = c(-5,5)) # Example 2: dichotomous items, (guessing is allowed) items<-data.frame(discrimination = c(1,1),difficulty = c(-1,0),guessing = c(0.2, 0.2), model= rep("3PL",2)) inverse_tcc(items = items, item_par_cols = list("3PL"=c("discrimination","difficulty","guessing")), model_col = "model", range_tcc = c(-5,5)) # Example 3: polytomous items items <- data.frame(alphaj = c(1.169,1.052,0.828,0.892,0.965), betaj1 = c(-0.006,-2.405,-0.799,-1.148,-0.299), betaj2 = c(0.487,1.125,0.764,-0.289,1.512), model = rep("GRM",5)) inverse_tcc(items = items, item_par_cols = list("GRM"=c("alphaj","betaj1","betaj2")), model_col = "model", range_tcc = c(-5,5)) # Example 4: dichotomous and polytomous items items <- data.frame(discrimination = c(1,1,rep(NA,5)), difficulty = c(-1,0,rep(NA,5)), alphaj = c(rep(NA,2),1.169,1.052,0.828,0.892,0.965), betaj1 = c(rep(NA,2),-0.006,-2.405,-0.799,-1.148,-0.299), betaj2 = c(rep(NA,2),0.487,1.125,0.764,-0.289,1.512), model = c(rep("2PL",2),rep("GRM",5))) inverse_tcc(items = items, item_par_cols = list("2PL"=c("discrimination","difficulty"), "GRM"=c("alphaj","betaj1","betaj2")), model_col = "model", range_tcc = c(-5,5))
This function generates linear constraints that require specific items to be either must be selected or not selected in a multistage test (MST) panel assembly.
If item_module_eligibility is supplied in mst_design() and the
requested item selection conflicts with module eligibility restrictions, an
error is thrown.
For details about item_module_eligibility, see mst_design().
Constraints may be applied at the "Module-level", "Pathway-level",
or "Panel-level".
If item_module_eligibility is NULL, the number of constraints is:
Module-level: when which_module is provided and
which_pathway = NULL
The number of constraints is (number of items in item_ids) x (number of specified modules)
Pathway-level: when which_pathway is provided and
which_module = NULL
The number of constraints is (number of items in item_ids) x (number of specified pathways)
Panel-level: both which_module and which_pathway are NULL
The number of constraints is (number of items in item_ids)
itemcat_con( x, item_ids, select = TRUE, which_module = NULL, which_pathway = NULL )itemcat_con( x, item_ids, select = TRUE, which_module = NULL, which_pathway = NULL )
x |
An object of class |
item_ids |
A numeric vector of item row indices, or
a character vector of item IDs from |
select |
Logical. Indicates whether items in |
which_module |
Optional integer vector of module indices to which the constraints apply. |
which_pathway |
Optional integer vector of pathway indices to which the constraints apply. |
1. Specification
The constraint enforced by this function is:
Items listed in item_ids must (or must not) be selected.
Key characteristics:
The attribute type is categorical (each item has a unique ID).
The attribute is defined at the item-level in the item pool.
Application levels:
Module-level: enforce selection in specific module(s).
Pathway-level: enforce selection in any module of a pathway.
Panel-level: enforce selection somewhere in the panel.
2. Examples of Interpretation
Item i must be selected in the routing module (Module-level):
item_ids = i, which_module = 1
Item i must be selected in Stage 2 easy and medium modules
(modules not belonging to the same pathway) (Module-level):
which_module = c(2,3)
Item i must be selected in the RM pathway (Pathway-level):
which_pathway = 2
Item i must appear somewhere in the assembled panel
(Panel-level):
which_module = NULL, which_pathway = NULL
3. Interaction with panel_itemreuse_con()
When overlap = FALSE in panel_itemreuse_con(), each item can at most be selected once
in a panel.
Therefore:
which_module or which_pathway must be a scalar (not
a vector).
If both are NULL, the constraint simply enforces that the
item must appear somewhere in the panel, without specifying the
module/pathway.
When overlap = TRUE in panel_itemreuse_con(), each item can at most be selected once
in a pathway, but each item may be selected in multiple modules within the same stage.
Therefore:
which_module may be a vector (can not be modules that appear in the same pathway)
An object of S3 class "mstATA_constraint" with named elements:
A character vector indicating the specifications in each row of A_binary
A data.frame summarizing the constraint specification, including
the requirement name, attribute, constraint type, application level,
operator, and the number of constraint rows generated.
A sparse binary matrix representing the linear constraint coefficients.
NULL for 'mstATA_constraint' object
A character vector of constraint operators, one per row of A_binary.
A right-hand-side vector of 1s or 0s depending on whether select is TRUE or FALSE.
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
Suppose the item pool contains (S - 1) stimulus-based item sets, indexed by
. Each stimulus has a designated pivot item,
indexed by . In addition, the pool contains a set of discrete
(non-stimulus-based) items, which are represented by a dummy stimulus
to allow a unified indexing scheme. Items belonging to stimulus
are indexed as .
Suppose there are modules in an MST panel. Let
denote the module index.
1. Module-level item selection/not selection
In specified module m: for all specified in item_ids
if item must be selected in module m.
if item must not be selected in module m.
2. Pathway-level item selection/not selection
In specified pathway r: for all specified in item_ids
if item must be selected in pathway r.
if item must not be selected in pathway r.
3. Panel-level item selection/not selection
In a panel: for all specified in item_ids
if item
must be selected in a panel.
if item
must not be selected in a panel.
Here:
is the binary decision variable indicating whether
item is selected into module m.
denote modules belonging to pathway r.
data("mini_itempool") test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", module_length = c(4,2,2,2,2,2,2) ) # Example 1: Item 2 must be selected in the routing module itemcat_con(x = test_mstATA, item_ids = 2, select = TRUE, which_module = 1) # Example 2: Item 2 must appear somewhere in the MST panel itemcat_con(x = test_mstATA, item_ids = 2, select = TRUE) # Example 3: Item 2 must be selected in Stage 2 easy and medium modules itemcat_con(x = test_mstATA, item_ids = 2, select = TRUE, which_module = c(2,3)) # Example 4: Item 2 must be selected in the REE pathway itemcat_con(x = test_mstATA, item_ids = 2, select = TRUE, which_pathway = 1) # Example 5: Items 1 and 3 must be selected in the routing module itemcat_con(x = test_mstATA, item_ids = c(1,3), select = TRUE, which_module = 1) # Example 6: Items 1 and 3 must be selected in the REE pathway itemcat_con(x = test_mstATA, item_ids = c(1,3), select = TRUE, which_pathway = 1) # Example 7: Items 1 and 3 must appear somewhere in the panel itemcat_con(x = test_mstATA, item_ids = c(1,3), select = TRUE) # Example 8: With item_module_eligibility provided mini_itempool <- mini_itempool[order(mini_itempool$difficulty), ] item_module_eligibility <- list( `2` = 1:15, `3` = 11:25, `4` = 15:30 ) new_test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", module_length = c(6,4,4,4,3,3,3), item_module_eligibility = item_module_eligibility ) itemcat_con(new_test_mstATA, item_ids = 2, select = TRUE, which_module = 2) # This call produces an error because item 2 is not eligible for module 3 try(itemcat_con(new_test_mstATA, item_ids = 2, select = TRUE, which_module = c(2,3)))data("mini_itempool") test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", module_length = c(4,2,2,2,2,2,2) ) # Example 1: Item 2 must be selected in the routing module itemcat_con(x = test_mstATA, item_ids = 2, select = TRUE, which_module = 1) # Example 2: Item 2 must appear somewhere in the MST panel itemcat_con(x = test_mstATA, item_ids = 2, select = TRUE) # Example 3: Item 2 must be selected in Stage 2 easy and medium modules itemcat_con(x = test_mstATA, item_ids = 2, select = TRUE, which_module = c(2,3)) # Example 4: Item 2 must be selected in the REE pathway itemcat_con(x = test_mstATA, item_ids = 2, select = TRUE, which_pathway = 1) # Example 5: Items 1 and 3 must be selected in the routing module itemcat_con(x = test_mstATA, item_ids = c(1,3), select = TRUE, which_module = 1) # Example 6: Items 1 and 3 must be selected in the REE pathway itemcat_con(x = test_mstATA, item_ids = c(1,3), select = TRUE, which_pathway = 1) # Example 7: Items 1 and 3 must appear somewhere in the panel itemcat_con(x = test_mstATA, item_ids = c(1,3), select = TRUE) # Example 8: With item_module_eligibility provided mini_itempool <- mini_itempool[order(mini_itempool$difficulty), ] item_module_eligibility <- list( `2` = 1:15, `3` = 11:25, `4` = 15:30 ) new_test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", module_length = c(6,4,4,4,3,3,3), item_module_eligibility = item_module_eligibility ) itemcat_con(new_test_mstATA, item_ids = 2, select = TRUE, which_module = 2) # This call produces an error because item 2 is not eligible for module 3 try(itemcat_con(new_test_mstATA, item_ids = 2, select = TRUE, which_module = c(2,3)))
This function constructs linear constraints enforcing that every selected item satisfies a quantitative attribute requirement (e.g., difficulty greater than c, item length less than c, discrimination within a range).
Constraints may be applied at the "Module-level", "Pathway-level", or
"Panel-level".
This function is for demonstration only and is not intended for operational use. It generates an excessively large number of rows in the constraint matrix and requires item-level attributes to be strictly positive.
The number of generated linear constraints depends on the application level:
Module-level: when which_module is provided
The number of constraints is (number of items) x (number of modules specified) x side
Pathway-level: when which_pathway is provided and
which_module = NULL
The number of constraints is (number of items) x (number of unique modules in specified pathways) x side
Panel-level: both which_module and which_pathway are NULL
The number of constraints is (number of items) x (total number of modules) x side
where side = 1 for one-sided constraints (min-only or max-only)
and side = 2 when both min and max are provided and
min is not equal to max.
itemquant_con( x, attribute, min = NULL, max = NULL, which_module = NULL, which_pathway = NULL )itemquant_con( x, attribute, min = NULL, max = NULL, which_module = NULL, which_pathway = NULL )
x |
An object of class |
attribute |
A string giving the column name in |
min |
A numeric scalar for the lower bound. |
max |
A numeric scalar for the upper bound. |
which_module |
Optional integer vector of module indices to which the constraints apply. |
which_pathway |
Optional integer vector of pathway indices to which the constraints apply. |
1. Specification
The constraint enforces:
Each selected item must satisfy the specified quantitative lower bound, upper bound, or both.
Key characteristics:
The attribute type is quantitative.
The attribute is defined at the item level in the item pool.
Application levels:
Module-level: enforce items selected in specific module(s) satisfy the quantitative requirement.
Pathway-level: enforce items selected in any module of a pathway satisfy the quantitative requirement.
Panel-level: enforce items selected in the panel satisfy the quantitative requirement.
2. Important Restriction
There are two reasons this approach is discouraged. First, item-level
quantitative constraints generate an excessively large number of
constraint rows, leading to poor computational efficiency. Second, the
formulation requires scaling item-selection variables by the attribute
value . If is zero or negative, the resulting
inequalities become invalid.
Because many commonly used item attributes (e.g., IRT difficulty parameters or centered text indices) may take zero or negative values, this function is not suitable for operational MST assembly.
Instead, per-item quantitative rules should be enforced during the design stage
using item_module_eligibility() within mst_design(),
which excludes ineligible items prior to module assembly.
This function always throws an error indicating that it is not for operational use.
It is retained solely as an illustrative example of how item-level quantitative constraints propagate through different hierarchical levels of an MST design.
Suppose the item pool contains (S - 1) stimulus-based item sets, indexed by
. Each stimulus has a designated pivot item,
indexed by . In addition, the pool contains a set of discrete
(non-stimulus-based) items, which are represented by a dummy stimulus
to allow a unified indexing scheme. Items belonging to stimulus
are indexed as .
Suppose there are modules in an MST panel. Let
denote the module index.
Let be the quantitative attribute value of item .
Upper-bound constraint:
Lower-bound constraint:
For two-sided range constraints, both inequalities are included.
(min and max both provided and not
equal), the number of constraints is doubled (side = 2).
For one-sided constraints, side = 1.
Here:
is the binary decision variable indicating whether
item is selected into module m.
(must be positive values) denote the values of a quantitative attribute for item .
and are the lower and
upper allowable bounds for the attribute .
Computes the joint (cumulative) score distribution after administering a next-stage module, conditional on routing into a branch defined by a set of reachable previous scores.
This function performs a convolution between:
the conditional score distribution from previous stages, and
the score distribution of the next module.
The returned distribution is not normalized: for each theta column, the column sum equals the probability of routing into this branch at that theta, which does not necessarily have to be 1.
joint_module_score_dist( cdist_by_prev, prev_scores, icc_by_next_mod, possible_joint_score )joint_module_score_dist( cdist_by_prev, prev_scores, icc_by_next_mod, possible_joint_score )
cdist_by_prev |
Numeric matrix.
Rows correspond to previous score values given in |
prev_scores |
Integer vector of non-negative values giving the score
values associated with the rows of |
icc_by_next_mod |
Named list of ICC matrices for the next module.
Each element corresponds to a theta point. Names must match
the column names of |
possible_joint_score |
Integer vector of non-negative cumulative scores that are reachable under this routing branch. |
Let denote the cumulative score prior to the current stage,
and the score from the next-stage module.
This function computes:
for all s in possible_joint_score.
A numeric matrix with:
rows corresponding exactly to possible_joint_score,
columns corresponding to theta points.
Each column represents the (unnormalized) joint score distribution at that theta.
## toy previous score distribution prev_scores <- 0:2 cdist_by_prev <- matrix( c(0.2, 0.3, 0.5, 0.4, 0.3, 0.3), nrow = 3, dimnames = list(NULL, c("theta=-1", "theta=0")) ) ## simple ICC: two items, dichotomous icc <- matrix( c(0.4, 0.6, 0.7, 0.3), nrow = 2, byrow = TRUE ) colnames(icc) <- c("0", "1") icc_by_next_mod <- list( "theta=-1" = icc, "theta=0" = icc ) possible_joint_score <- c(1, 2, 3) joint_module_score_dist( cdist_by_prev, prev_scores, icc_by_next_mod, possible_joint_score )## toy previous score distribution prev_scores <- 0:2 cdist_by_prev <- matrix( c(0.2, 0.3, 0.5, 0.4, 0.3, 0.3), nrow = 3, dimnames = list(NULL, c("theta=-1", "theta=0")) ) ## simple ICC: two items, dichotomous icc <- matrix( c(0.4, 0.6, 0.7, 0.3), nrow = 2, byrow = TRUE ) colnames(icc) <- c("0", "1") icc_by_next_mod <- list( "theta=-1" = icc, "theta=0" = icc ) possible_joint_score <- c(1, 2, 3) joint_module_score_dist( cdist_by_prev, prev_scores, icc_by_next_mod, possible_joint_score )
Implements a maximin objective that maximizes a common floor value
across linear objective scores .
The compiled constraints enforce:
and, if an overflow bound delta is finite for term ,
maximin_obj(x, multiple_terms, strategy_args = list())maximin_obj(x, multiple_terms, strategy_args = list())
x |
An object of class |
multiple_terms |
A list of objective terms created by |
strategy_args |
A named list of strategy-specific arguments used by the maximin aggregation. Supported fields:
|
1. Overview
The maximin strategy applies when there are two or more objective terms. Each objective term represents a linear score of the form
constructed by objective_term().
The goal is to maximize the minimum (normalized) score across all terms, ensuring balanced performance rather than optimizing any single criterion.
Key characteristics for each objective term:
(1) Attribute type
Each objective term may be defined using either:
a categorical attribute – maximizing or minimizing the number of items belonging to a specific category level; or
a quantitative attribute – maximizing or minimizing the sum of item-level attribute values (e.g., difficulty, discrimination, item information function values).
(2) Application level
Objective terms may be applied at one of three hierarchical levels:
"Module-level" – only items in a specified module contribute;
"Pathway-level" – items in all modules belonging to one pathway;
"Panel-level" – all item selections in the panel contribute.
(3) Objective type
The maximin strategy supports relative objectives only:
Relative objective: maximize .
Absolute (goal-based) objectives of the form
are not permitted under the maximin strategy.
2. Proportions and normalization
Each objective term may be associated with a positive proportion .
These proportions encode the relative scaling of each objective.
By default, for all terms.
3. Overflow control via delta
Two formulations are supported depending on the value of delta:
Without overflow control (delta = Inf):
This is the classical maximin formulation, enforcing only a lower bound on each objective score.
With overflow control (delta < Inf):
This bounded formulation limits how far any single objective score may exceed the common floor, improving balance and numerical stability.
A list of class "compiled_objective"
A character vector indicating the specifications in each row of A_binary
A data.frame including "Requirement","Attribute","Type","Application Level","Operator","Num of Constraints"
A sparse constraint matrix (class "Matrix") for binary
decision variables. Rows correspond to constraints; columns correspond to
binary decision variables.
A sparse constraint matrix (class "Matrix") for
continuous decision variables. Must have the same number of rows as
A_binary.
A character vector of constraint operators, one per row of A_binary.
A numeric vector of right-hand-side values for the constraints.
A numeric vector of objective coefficients for binary decision variables.
A numeric vector of objective coefficients for continuous decision variables.
Always "max" for the maximin strategy.
Character vector indicating the names of new decision variables, same length as ncol(A_real).
A character vector of "C" (continuous), same length as ncol(A_real).
List of metadata.
Let denote the vector of binary item-module-panel decision variables.
For each objective term , define:
Introduce a continuous auxiliary variable representing the minimum
normalized score. The maximin optimization problem is:
subject to:
and optionally,
data("mini_itempool") test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", exclude_pathway = c("1-1-3", "1-3-1"), pathway_length = 8 ) # Example 1: Maximize the minimum TIF across theta = -1, 0, 1 theta_n1 <- objective_term( x = test_mstATA, attribute = "iif(theta=-1)", applied_level = "Module-level", which_module = 1, sense = "max" ) theta_0 <- objective_term( x = test_mstATA, attribute = "iif(theta=0)", applied_level = "Module-level", which_module = 1, sense = "max" ) theta_1 <- objective_term( x = test_mstATA, attribute = "iif(theta=1)", applied_level = "Module-level", which_module = 1, sense = "max" ) maximin_obj(x = test_mstATA, multiple_terms = list(theta_n1, theta_0, theta_1))data("mini_itempool") test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", exclude_pathway = c("1-1-3", "1-3-1"), pathway_length = 8 ) # Example 1: Maximize the minimum TIF across theta = -1, 0, 1 theta_n1 <- objective_term( x = test_mstATA, attribute = "iif(theta=-1)", applied_level = "Module-level", which_module = 1, sense = "max" ) theta_0 <- objective_term( x = test_mstATA, attribute = "iif(theta=0)", applied_level = "Module-level", which_module = 1, sense = "max" ) theta_1 <- objective_term( x = test_mstATA, attribute = "iif(theta=1)", applied_level = "Module-level", which_module = 1, sense = "max" ) maximin_obj(x = test_mstATA, multiple_terms = list(theta_n1, theta_0, theta_1))
A precomputed multistage testing (MST) panel assembled using the maximin objective formulation described in the Formulation for Multiple Objectives vignette.
maximin_panelmaximin_panel
An object of class mstATA_panel.
This object is included to avoid long solver runtimes during vignette building and package checking.
Generated using mstATA::assembled_panels() and mstATA::solve_model()with the HiGHS solver.
A simulated mini item pool for demonstrating MST functionality.
data(mini_itempool)data(mini_itempool)
A data frame with 30 rows and 7 columns:
Unique identifier for each item
Content area classification (e.g., content1, content2, content3, content4).
Item format (e.g., MC, TEI).
Expected response time for the item.
Discrimination parameter () for the 3PL model.
Difficulty parameter () for the 3PL model.
Guessing parameter () for the 3PL model.
Item response theory (IRT) model used for the item (3PL).
Integer specifying the maximum number of response categories generated for the item.
enemy information 2
enemy information 1
associated stimulus information
item information value at -1
item information value at 0
item information value at 1
data(mini_itempool)data(mini_itempool)
Implements a minimax (goal-based) objective that minimizes a common ceiling on deviations from multiple target values.
Let there be objective terms with linear scores
and target values .
The minimax objective minimizes the largest deviation from these targets
across all terms.
A common deviation variable is introduced so that no objective deviates from its target by more than this value.
minimax_obj(x, multiple_terms, strategy_args = list())minimax_obj(x, multiple_terms, strategy_args = list())
x |
An object of class |
multiple_terms |
A list of objective terms created by |
strategy_args |
A named list of strategy-specific arguments used by the minimax aggregation. Supported fields:
|
1. Overview
Each objective term is created using objective_term() and represents
a linear score of the form:
where is a coefficient vector defined by the attribute,
attribute level, and application scope, and denotes the
item-module-panel decision variables.
Each term has an associated target value .
The minimax strategy seeks a solution that minimizes the worst-case deviation across all objective terms.
Key characteristics for each objective term:
(1) Categorical or Quantitative
Categorical: deviation from a target number of items belonging to a specified category level;
Quantitative: deviation from a target sum of quantitative item attributes (e.g., difficulty, discrimination, or item information).
(2) Applied at One of Three Levels
"Module-level" – only items in a specified module contribute;
"Pathway-level" – items in all modules belonging to a pathway;
"Panel-level" – all item selections in the panel contribute.
(3) Only Absolute Objectives
The minimax strategy applies only to absolute (goal-based) objectives. Relative objectives without targets are not supported.
2. Deviation modes
Two equivalent deviation formulations are supported via
strategy_args$mode:
One-deviation mode (mode = "one_dev"):
Introduces a single nonnegative deviation variable
representing the largest absolute deviation across all objectives.
For each objective term:
The optimization problem is:
Two-deviation mode (mode = "two_dev"):
Introduces two nonnegative deviation variables:
(maximum overflow) and
(maximum shortage).
For each objective term:
The optimization problem is:
Interpretation
(one-dev) measures the largest absolute deviation from any target;
measures the largest amount by which any objective exceeds its target;
measures the largest amount by which any objective falls short of its target.
An object of S3 class "compiled_objective" with named elements:
A string indicating the objective function name.
A sparse constraint matrix (class "Matrix") for binary
decision variables. Rows correspond to constraints; columns correspond to
binary decision variables.
A sparse constraint matrix (class "Matrix") for
continuous decision variables. Must have the same number of rows as
A_binary.
A character vector of constraint operators, one per row of A_binary.
A numeric vector of right-hand-side values for the constraints.
A numeric vector of objective coefficients for binary decision variables.
A numeric vector of objective coefficients for continuous decision variables.
Always "min" for the minimax strategy.
Types of auxiliary variables (continuous).
Names of auxiliary variables.
Metadata including strategy name and deviation mode.
For , let
where:
is the coefficient vector defined by the objective term;
is the vector of binary item-module-panel decision variables;
is the target value specified by the test developer.
The minimax objective minimizes the maximum deviation across all objectives by introducing auxiliary deviation variables and solving a linear program that controls the worst-case mismatch.
data("mini_itempool") test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", exclude_pathway = c("1-1-3", "1-3-1"), pathway_length = 8 ) obj1 <- objective_term( x = test_mstATA, attribute = "iif(theta=-1)", applied_level = "Module-level", which_module = 1, sense = "min", goal = 12 ) obj2 <- objective_term( x = test_mstATA, attribute = "iif(theta=0)", applied_level = "Module-level", which_module = 1, sense = "min", goal = 15 ) obj3 <- objective_term( x = test_mstATA, attribute = "iif(theta=1)", applied_level = "Module-level", which_module = 1, sense = "min", goal = 12 ) # One-deviation minimax minimax_obj(x = test_mstATA, multiple_terms = list(obj1,obj2,obj3), strategy_args = list(mode = "one_dev")) # Two-deviation minimax minimax_obj(x = test_mstATA, multiple_terms = list(obj1,obj2,obj3), strategy_args = list(mode = "two_dev"))data("mini_itempool") test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", exclude_pathway = c("1-1-3", "1-3-1"), pathway_length = 8 ) obj1 <- objective_term( x = test_mstATA, attribute = "iif(theta=-1)", applied_level = "Module-level", which_module = 1, sense = "min", goal = 12 ) obj2 <- objective_term( x = test_mstATA, attribute = "iif(theta=0)", applied_level = "Module-level", which_module = 1, sense = "min", goal = 15 ) obj3 <- objective_term( x = test_mstATA, attribute = "iif(theta=1)", applied_level = "Module-level", which_module = 1, sense = "min", goal = 12 ) # One-deviation minimax minimax_obj(x = test_mstATA, multiple_terms = list(obj1,obj2,obj3), strategy_args = list(mode = "one_dev")) # Two-deviation minimax minimax_obj(x = test_mstATA, multiple_terms = list(obj1,obj2,obj3), strategy_args = list(mode = "two_dev"))
A simulated item pool containing both standalone items and stimulus-based items. This dataset is designed to demonstrate multistage testing (MST) functionality under a mixed-format item pool, including stimulus-based selection, multiple-objective formulations, and multiple-panel assembly.
data(mixed_format_pool)data(mixed_format_pool)
A data frame with 1000 rows and the following variables:
Unique identifier for each item.
Identifier(s) of items that cannot be administered together (enemy-item information).
Content area classification (e.g., content 1, content 2, content 3, content 4).
Depth-of-Knowledge (DOK) level (dok 1, dok 2, or dok 3).
Item type (e.g., MC for multiple choice, TEI for technology-enhanced item).
Estimated item response time.
Discrimination parameter () for the 2PL model.
Difficulty parameter () for the 2PL model.
Item response theory (IRT) model for all items (2PL).
Identifier of the associated stimulus (if applicable).
Indicator for pivot items. A pivot item is selected if and only if its associated stimulus is selected; non-pivot items are NA.
Stimulus type (e.g., graphic-based, text-based).
complexity score of the associated stimulus.
data(mixed_format_pool)data(mixed_format_pool)
Compute the conditional score distributions in a module given
one or more ability values ().
This function assumes that item category probabilities have already been computed and are provided on a common category scale.
module_score_dist(icc)module_score_dist(icc)
icc |
A named list of item-by-category probability matrices evaluated
at one or more ability values. Each element corresponds to a single
ability value For mixed dichotomous and polytomous modules, dichotomous items must be padded so that all matrices share the same set of category columns, with higher-category probabilities set to zero. |
Consider a module consisting of items. Let the score for item
be a discrete random variable taking values
. Conditional on ability , assume
local independence:
The total module score is
with support . For a fixed ability level
, the conditional distribution of is obtained by
discrete convolution of the item-level category probability vectors:
where and
denotes convolution.
This function applies the above operation independently at each ability level.
A numeric matrix giving conditional module score distributions at target theta values.
Rows correspond to total scores
. Columns correspond to ability values
. Each column sums to one.
## Example 1: Dichotomous model data("mini_itempool") icc_mat<-compute_icc(mini_itempool,list("3PL"=c("discrimination","difficulty","guessing")), theta = 0,model_col = "model",D = 1.7) icc_list<-compute_icc(mini_itempool,list("3PL"=c("discrimination","difficulty","guessing")), theta = seq(-5,5,0.1),model_col = "model",D = 1.7) module_score_dist(icc_mat[[1]]) module_score_dist(icc_list) ## Example 2: Polytomous model (PCM) data("poly_itempool") icc_mat<-compute_icc(poly_itempool,list("PCM"=c("deltaj1","deltaj2","deltaj3")), theta = 0,model_col = "model") icc_list<-compute_icc(poly_itempool,list("PCM"=c("deltaj1","deltaj2","deltaj3")), theta = seq(-5,5,0.1),model_col = "model") module_score_dist(icc_mat[[1]]) module_score_dist(icc_list) ## Example 3: multiple IRT models (3PL + GPCM + GRM) data("Rmst_pool") icc_mat<-compute_icc(Rmst_pool, item_par_cols = list("3PL"=c("a","b","c"), "GPCM" = c("alpha","delta1","delta2","delta3"), "GRM" = c("alpha","beta1","beta2")), theta = 0,model_col = "model") icc_list<-compute_icc(Rmst_pool, item_par_cols = list("3PL"=c("a","b","c"), "GPCM" = c("alpha","delta1","delta2","delta3"), "GRM" = c("alpha","beta1","beta2")), theta = 0,model_col = "model") module_score_dist(icc_mat[[1]]) module_score_dist(icc_list)## Example 1: Dichotomous model data("mini_itempool") icc_mat<-compute_icc(mini_itempool,list("3PL"=c("discrimination","difficulty","guessing")), theta = 0,model_col = "model",D = 1.7) icc_list<-compute_icc(mini_itempool,list("3PL"=c("discrimination","difficulty","guessing")), theta = seq(-5,5,0.1),model_col = "model",D = 1.7) module_score_dist(icc_mat[[1]]) module_score_dist(icc_list) ## Example 2: Polytomous model (PCM) data("poly_itempool") icc_mat<-compute_icc(poly_itempool,list("PCM"=c("deltaj1","deltaj2","deltaj3")), theta = 0,model_col = "model") icc_list<-compute_icc(poly_itempool,list("PCM"=c("deltaj1","deltaj2","deltaj3")), theta = seq(-5,5,0.1),model_col = "model") module_score_dist(icc_mat[[1]]) module_score_dist(icc_list) ## Example 3: multiple IRT models (3PL + GPCM + GRM) data("Rmst_pool") icc_mat<-compute_icc(Rmst_pool, item_par_cols = list("3PL"=c("a","b","c"), "GPCM" = c("alpha","delta1","delta2","delta3"), "GRM" = c("alpha","beta1","beta2")), theta = 0,model_col = "model") icc_list<-compute_icc(Rmst_pool, item_par_cols = list("3PL"=c("a","b","c"), "GPCM" = c("alpha","delta1","delta2","delta3"), "GRM" = c("alpha","beta1","beta2")), theta = 0,model_col = "model") module_score_dist(icc_mat[[1]]) module_score_dist(icc_list)
Constructs an mstATA_design object from an item pool and a multistage test (MST)
design. The resulting object encodes the full structural
information required for automated test assembly, including module structure,
pathway structure, decision variables, and optional preprocessing artifacts
such as stimulus mappings and enemy relationships.
mst_design( itempool, item_id_col = "item_id", design, rdps = NULL, diff_levels = NULL, exclude_pathways = NULL, module_length = NULL, pathway_length = NULL, item_module_eligibility = NULL, pivot_stim_map = NULL, enemyitem_set = NULL, enemystim_set = NULL )mst_design( itempool, item_id_col = "item_id", design, rdps = NULL, diff_levels = NULL, exclude_pathways = NULL, module_length = NULL, pathway_length = NULL, item_module_eligibility = NULL, pivot_stim_map = NULL, enemyitem_set = NULL, enemystim_set = NULL )
itempool |
A |
item_id_col |
A character string giving the column name in |
design |
A character string specifying the MST design. The string encodes the number of modules per stage and may use commas, dashes, or slashes as separators. For example, "1-3-3", "1,3,3", and "1/3/3" all define an MST with 1 module in stage 1, 3 modules in stage 2, and 3 modules in stage 3. |
rdps |
Optional list specifying routing decision points for each stage transition in a multistage test. Default is NULL. See Details. |
diff_levels |
Optional named list of difficulty labels, indexed by the number
of modules in each stage. If |
exclude_pathways |
An optional character vector identifying disallowed
pathways. Each element must be a string of the form "x-y-z", where
each number denotes the module selected at a given stage. Module indices
must correspond to those implied by the MST design. If |
module_length |
Optional numeric vector giving the number of items in each
module. The length must match the number of modules implied by |
pathway_length |
Optional numeric scalar specifying the total number of items in each pathway. All pathways must have equal length if this argument is used. |
item_module_eligibility |
Optional named list specifying item eligibility by module. List names correspond to (a subset of) module indices (within a single panel), and each element is a vector of item indices eligible for that module. If omitted, all items are eligible for that module. |
pivot_stim_map |
Optional. A precomputed stimulus-item mapping created by create_pivot_stimulus_map(). Required for stimulus-based constraints. |
enemyitem_set |
Optional. A precomputed enemy item set created by create_enemy_sets() and optionally combined via concat_enemy_sets(). Required for enemy-item constraints. |
enemystim_set |
Optional. A precomputed enemy stimulus set created by create_enemy_sets() and optionally combined via concat_enemy_sets(). Required for enemy-stimulus constraints. |
1. Routing decision points
The list must have length NumStages - 1. Each element corresponds
to routing after a given stage and must be a numeric vector whose length
equals the number of modules in the next stage minus one.
For example, in a three-stage 1-3-3 design:
rdps = list( c(-0.5, 0.5), # routing after stage 1 c(-1, 1) # routing after stage 2 )
The ordering of values within each vector defines adjacency among modules in the next stage.
2. module_length or pathway_length
Exactly one of module_length or pathway_length must be specified.
If module_length is provided, modules at the same stage are checked (must
have equal length). Pathway lengths are computed automatically.
If pathway_length is provided, all pathways are assumed to have
equal length and module lengths are not explicitly stored.
If both are provided, consistency between the implied and supplied pathway lengths is checked.
3. item_module_eligibility set
By default, all items are eligible for all modules, yielding a fully flexible
module-explicit formulation with decision variables
indicating whether item is selected in module
in a panel. Panel-level item exposure constraints ensure uniqueness across modules within a pathway/panel.
When item_module_eligibility is supplied, decision variables are created
only for eligible item-module combinations. This reduces model size while
preserving flexibility near module boundaries and avoids rigid item partitioning in original
hybrid assembly strategy (Xiong, 2018).
An object of class "mstATA_design" with the following components:
The original item pool.
A character string giving the column name in ItemPool
that uniquely identifies items.
Optional verified stimulus mapping object with components
pivot_item_id, stimulus_name,
stimulus_members, and numItems_stimulus.
Optional verified enemy item set containing
ExclusionPair, EnemySet, and derived ItemIndex.
Optional verified enemy stimulus set containing
ExclusionPair, EnemySet, and derived PivotIndex.
Number of stages in the MST design.
Number of modules in the MST design.
Number of allowed pathways.
Optional verified routing decision points.
A data.frame describing module structure by stage.
If module_length is supplied, includes a ModuleLength column.
A data.frame describing allowed pathways and their
total lengths. If difficulty labels are available, includes pathway labels.
Character vector of decision variable names (one panel).
Character vector of decision variable types (currently all binary).
Xiong, X. (2018). A hybrid strategy to construct multistage adaptive tests. Applied Psychological Measurement, 42(8), 630-643.doi:10.1177/0146621618762739
# mini item pool data("mini_itempool") # Example 1: 1-3-3 design with varying module lengths mst_design(itempool = mini_itempool,design = "1-3-3", module_length = c(6, 4, 4, 4, 3, 3, 3),pathway_length = NULL) # Example 2: 1-3-3 design with fixed pathway length and excluded REH and RHE pathways mst_design(itempool = mini_itempool,design = "1-3-3", exclude_pathways = c("1-1-3", "1-3-1"), module_length = NULL,pathway_length = 13) # Example 3: 1-3-3 design, with item_module_eligibility provided item_module_eligibility<-list(`1`=1:nrow(mini_itempool), `2`=which(mini_itempool$difficulty<=0), `4`=which(mini_itempool$difficulty>=0)) ### selected items in routing module no item-level requirement, ### selected items in S2E, difficulty below 0 ### selected items in S2H, difficulty above 0 mst_design(itempool = mini_itempool,design = "1-3-3", module_length = c(6,4,4,4,3,3,3), item_module_eligibility = item_module_eligibility)# mini item pool data("mini_itempool") # Example 1: 1-3-3 design with varying module lengths mst_design(itempool = mini_itempool,design = "1-3-3", module_length = c(6, 4, 4, 4, 3, 3, 3),pathway_length = NULL) # Example 2: 1-3-3 design with fixed pathway length and excluded REH and RHE pathways mst_design(itempool = mini_itempool,design = "1-3-3", exclude_pathways = c("1-1-3", "1-3-1"), module_length = NULL,pathway_length = 13) # Example 3: 1-3-3 design, with item_module_eligibility provided item_module_eligibility<-list(`1`=1:nrow(mini_itempool), `2`=which(mini_itempool$difficulty<=0), `4`=which(mini_itempool$difficulty>=0)) ### selected items in routing module no item-level requirement, ### selected items in S2E, difficulty below 0 ### selected items in S2H, difficulty above 0 mst_design(itempool = mini_itempool,design = "1-3-3", module_length = c(6,4,4,4,3,3,3), item_module_eligibility = item_module_eligibility)
Translates the structural specifications of a MST panel into a set of mandatory linear constraints that must be satisfied regardless of the assembly strategy (e.g., bottom-up, top-down, or hybrid).
The resulting constraints enforce:
Module-level item count requirements or Pathway-level item count + module min/max + equal module length within each stage requirements
Information balance at routing decision points (RDPs), if specified.
These constraints are intrinsic to the MST panel configuration and are independent of the assembly strategy.
mst_structure_con(x, stage_length_bound = NULL, info_tol = 0.5)mst_structure_con(x, stage_length_bound = NULL, info_tol = 0.5)
x |
An object of class |
stage_length_bound |
Optional bounds on the total number of items in each stage. This argument is passed to test_itemcount_con(). |
info_tol |
A single positive numeric value specifying the allowable difference in information between adjacent modules at each routing decision point. This argument is passed to test_rdp_con(). |
This function bundles structural constraints that are required for all MST panel assembly problems.
When routing constraints are requested, the item pool must already contain
item-level information functions of the form
iif(theta = theta_point). These can be prepared using
compute_iif().
An object of S3 class "mstATA_constraint" with named elements:
A character vector indicating the specifications in each row of A_binary
A data.frame summarizing the constraint specification, including
the requirement name, attribute, constraint type, application level,
operator, and the number of constraint rows generated.
A sparse binary matrix representing the linear constraint coefficients.
NULL for 'mstATA_constraint' object
A character vector of constraint operators, one per row of A_binary.
A numeric vector of right-hand-side values for the constraints.
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
data("mini_itempool") iif_matrix<-compute_iif(mini_itempool, item_par_cols = list("3PL"=c("discrimination","difficulty","guessing")), theta = c(-0.5,0.5),model_col = "model") mini_itempool[,paste0("iif(theta=",c(-0.5,0.5),")")]<-iif_matrix test_mstATA <- mst_design( itempool = mini_itempool,module_length = c(3,4,4,4), design = "1-3",rdps = list(c(-0.5,0.5)) ) ## build mandatory structural constraints: module-level item count and rdp constraint mst_structure_con(x = test_mstATA,info_tol = 0.4)data("mini_itempool") iif_matrix<-compute_iif(mini_itempool, item_par_cols = list("3PL"=c("discrimination","difficulty","guessing")), theta = c(-0.5,0.5),model_col = "model") mini_itempool[,paste0("iif(theta=",c(-0.5,0.5),")")]<-iif_matrix test_mstATA <- mst_design( itempool = mini_itempool,module_length = c(3,4,4,4), design = "1-3",rdps = list(c(-0.5,0.5)) ) ## build mandatory structural constraints: module-level item count and rdp constraint mst_structure_con(x = test_mstATA,info_tol = 0.4)
Constructs a multi-panel ATA model by expanding single-panel specifications to multiple panels and turning it into a solver-ready formulation.
Solution-level constraints and decision-variable linking between item-module-panel variables and solution-level variables are handled at this stage.
multipanel_spec( x, panel_model, num_panels, solution_con = NULL, global_min_use = 0, global_max_use = Inf, item_min_use = NULL, item_max_use = NULL )multipanel_spec( x, panel_model, num_panels, solution_con = NULL, global_min_use = 0, global_max_use = Inf, item_min_use = NULL, item_max_use = NULL )
x |
An object of class |
panel_model |
An object of class |
num_panels |
Integer. Number of panels to be assembled. |
solution_con |
Optional list of |
global_min_use |
Scalar. Minimum number of times any item may be used
across panels. Default = |
global_max_use |
Scalar. Maximum number of times any item may be used
across panels. Default = |
item_min_use |
Optional data frame with columns |
item_max_use |
Optional data frame with columns |
1. Parallel Panels
The single-panel specification is
expanded to num_panels panels by replicating constraint matrices
in a block-diagonal structure. All panels share identical constraints
and objectives.
Solution-level constraints, if provided, are appended after panel expansion.
Specification traceability
The returned model contains an expanded specification table that records, for each requirement:
the originating panel,
the number of constraints generated,
the contiguous row ranges in the final solver matrix.
This information can be used to diagnose infeasibility and to prioritize or relax groups of constraints programmatically.
2. Consistency between item-module-panel selection and solution-level item indicators
The decision-variable linking constraints (e.g., dvlink_item_solution()) are automatically added to link item-module-panel selection and solution-level item selection.
The constraint enforces:
Each item can be used at least a specified minimum number of times and/or no more than a specified maximum number of times across all panels.
Key characteristics:
Attribute: itemset level (item-itself set) logical (if selected, then increment reuse).
Constraints are applied at the "Solution-level".
Global reuse limits are supplied via global_min_use and
global_max_use. These bounds apply to all items unless overridden.
Item-specific reuse limits may be supplied through:
item_min_use: a data frame with columns item_id and min
item_max_use: a data frame with columns item_id and max
The total number of constraints generated is always
where is the pool size, corresponding to one minimum and one maximum
constraint per item.
An object of class "mstATA_model", represented as a named list
containing constraint matrices, objective coefficients, decision variable
metadata, bounds, and optimization sense.
A character vector indicating the specifications in each row of A_binary
A data.frame summarizing the constraint specification, including
the requirement name, attribute, constraint type, application level,
operator, and the number of constraint rows generated.
A sparse constraint matrix (class "Matrix") for binary
decision variables. Rows correspond to constraints; columns correspond to
binary decision variables.
A sparse constraint matrix (class "Matrix") for
continuous decision variables. Must have the same number of rows as
A_binary.
Constraint coefficient matrix (sparse or dense).
A numeric vector of objective coefficients for binary decision variables.
A numeric vector of objective coefficients for continuous decision variables.
Objective function coefficient vector.
Right-hand-side vector of constraints.
Constraint operators (e.g., "<=", ">=", "=").
Decision variable types ("B" for binary, "C" for continuous).
Decision variable names.
Lower bounds for decision variables.
Upper bounds for decision variables.
Optimization sense ("min" or "max").
Creates a linear objective term of the form , where the vector
represents categorical or quantitative attribute values for the
involved items (or stimuli), and the decision variables represent
item selections within a single MST panel.
Depending on the attribute supplied, the objective can target:
maximize or minimize the number of items belong to a specific category level, or
maximize or minimize the sum of quantitative attribute values across items (e.g., difficulty, IIF values, discrimination).
Objective terms may be applied at three hierarchical levels:
"Module-level" – aggregates only items belonging to one specific module;
"Pathway-level" – aggregates items in all modules that compose a single MST pathway; and
"Panel-level" – aggregates all item selections across all modules in a panel.
The function supports two types of objectives:
Relative objective - maximize or minimize .
Absolute deviation objective - minimize where is the target value.
objective_term( x, attribute, cat_level = NULL, applied_level = c("Module-level", "Pathway-level", "Panel-level"), which_module = NULL, which_pathway = NULL, sense = "max", goal = NULL )objective_term( x, attribute, cat_level = NULL, applied_level = c("Module-level", "Pathway-level", "Panel-level"), which_module = NULL, which_pathway = NULL, sense = "max", goal = NULL )
x |
An object of class |
attribute |
A string giving the column name in |
cat_level |
A character string or |
applied_level |
One of:
|
which_module |
Integer scalar specifying the module to which the
objective applies (only permitted when |
which_pathway |
Integer scalar specifying the pathway to which the
objective applies (only permitted when |
sense |
One of |
goal |
Optional numeric scalar. If supplied, the objective minimizes the
absolute deviation from the target:
|
1. Application scope
Module-level:
which_module must be supplied and must be a scalar.
which_pathway must be NULL.
Pathway-level:
which_pathway must be supplied and must be a scalar.
which_module must be NULL.
Panel-level:
Neither which_module nor which_pathway may be supplied.
2. Objective meaning
If cat_level = NULL, the vector consists of quantitative attribute
values.
If cat_level is specified, is an indicator vector for items in the
corresponding category.
The objective term therefore represents:
the sum of attribute values (quantitative), or
the count of items in a category (categorical).
An object of class "mstATA_objective" with components:
Character description of the objective term.
A 1-row sparse matrix containing the objective coefficients.
The target value for absolute deviation objectives, or NULL.
The optimization direction ("max" or "min").
data("mini_itempool") test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", exclude_pathway = c("1-1-3","1-3-1"), pathway_length = 8 ) # Example 1: Maximize information at ability = 0 in the routing module objective_term( x = test_mstATA, attribute = "iif(theta=0)", cat_level = NULL, applied_level = "Module-level", which_module = 1, sense = "max" ) # Example 2: Target a test information value at ability = -1 for pathway 1 objective_term( x = test_mstATA, attribute = "iif(theta=-1)", cat_level = NULL, applied_level = "Pathway-level", which_pathway = 1, sense = "max", goal = 10 ) # Example 3: Maximize the number of MC items in a panel objective_term( x = test_mstATA, attribute = "itemtype", cat_level = "MC", applied_level = "Panel-level", sense = "max" )data("mini_itempool") test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", exclude_pathway = c("1-1-3","1-3-1"), pathway_length = 8 ) # Example 1: Maximize information at ability = 0 in the routing module objective_term( x = test_mstATA, attribute = "iif(theta=0)", cat_level = NULL, applied_level = "Module-level", which_module = 1, sense = "max" ) # Example 2: Target a test information value at ability = -1 for pathway 1 objective_term( x = test_mstATA, attribute = "iif(theta=-1)", cat_level = NULL, applied_level = "Pathway-level", which_pathway = 1, sense = "max", goal = 10 ) # Example 3: Maximize the number of MC items in a panel objective_term( x = test_mstATA, attribute = "itemtype", cat_level = "MC", applied_level = "Panel-level", sense = "max" )
Constructs a single-panel ATA specification by assembling constraints, optional objective formulations, and required decision-variable linking rules into a solver-ready model with full semantic traceability.
This function validates that all supplied constraints apply to a single panel, automatically injects decision-variable linking constraints when required, and records row-index ranges that map semantic requirements to solver constraint rows.
onepanel_spec(x, constraints, objective = NULL)onepanel_spec(x, constraints, objective = NULL)
x |
An object of class |
constraints |
A list of |
objective |
Optional compiled objective of class
|
1. Constraint scope
All constraints supplied to onepanel_spec() must apply to a
single panel. This includes requirements defined at the item, stimulus,
itemset, module, pathway, or panel level.
Constraints that operate across panels (solution-level reuse or exposure constraints) must be specified during multi-panel expansion and are not permitted in a single-panel specification.
2. Automatic decision-variable linking
If module-level logical constraints involving item-stimulus relationships
are detected, and stim_itemcount_con() is not included,
onepanel_spec() automatically injects item-stimulus gating constraints
via all-in/all-out selection. This ensures that item-level and stimulus-level selections remain
logically consistent.
3. Row-index traceability
All constraint rows–including those introduced by objectives and automatically injected decision-variable linking constraints–are assigned contiguous row-index ranges in the compiled constraint matrix.
These ranges are recorded in the returned specification table,
allowing users to:
diagnose infeasibility,
identify binding constraint groups, and
programmatically relax or prioritize subsets of constraints.
An object of class "mstATA_model", represented as a named list
containing constraint matrices, objective coefficients, decision variable
metadata, bounds, and optimization sense.
A character vector indicating the specifications in each row of A_binary
A data.frame summarizing the constraint specification, including
the requirement name, attribute, constraint type, application level,
operator, and the number of constraint rows generated.
A sparse constraint matrix (class "Matrix") for binary
decision variables. Rows correspond to constraints; columns correspond to
binary decision variables.
A sparse constraint matrix (class "Matrix") for
continuous decision variables. Must have the same number of rows as
A_binary.
Constraint coefficient matrix (sparse or dense).
A numeric vector of objective coefficients for binary decision variables.
A numeric vector of objective coefficients for continuous decision variables.
Objective function coefficient vector.
Right-hand-side vector of constraints.
Constraint operators (e.g., "<=", ">=", "=").
Decision variable types ("B" for binary, "C" for continuous).
Decision variable names.
Lower bounds for decision variables.
Upper bounds for decision variables.
Optimization sense ("min" or "max").
data("reading_itempool") pivot_stim_map <- create_pivot_stimulus_map( itempool = reading_itempool, stimulus = "stimulus", pivot_item = "pivot_item" ) test_mstATA <- mst_design( itempool = reading_itempool, design = "1-3-3", module_length = c(14,12,12,12,12,12,12), pivot_stim_map = pivot_stim_map ) spec1<-test_itemcount_con(x=test_mstATA) spec2<-test_stimcat_con( x = test_mstATA, attribute = "stimulus_type", cat_levels = c("history","social studies"), operator = "=", target_num = c(1,1), which_module = 1) spec3<-test_stimcat_con( x = test_mstATA, attribute = "stimulus_type", cat_levels = "history", operator = "=", target_num = 2, which_module = 2:4) spec4<-test_stimcat_con( x = test_mstATA, attribute = "stimulus_type", cat_levels = "social studies", operator = "=", target_num = 2, which_module = 5:7) spec5<-stim_itemcount_con( x = test_mstATA, min = 5, max = 7 ) obj_term<-objective_term(x = test_mstATA,attribute = "discrimination", applied_level = "Module-level",which_module = 1,sense = "max") panel_spec <- onepanel_spec( x = test_mstATA, constraints = list(spec1,spec2,spec3,spec4,spec5), objective = single_obj(x=test_mstATA,single_term = obj_term) )data("reading_itempool") pivot_stim_map <- create_pivot_stimulus_map( itempool = reading_itempool, stimulus = "stimulus", pivot_item = "pivot_item" ) test_mstATA <- mst_design( itempool = reading_itempool, design = "1-3-3", module_length = c(14,12,12,12,12,12,12), pivot_stim_map = pivot_stim_map ) spec1<-test_itemcount_con(x=test_mstATA) spec2<-test_stimcat_con( x = test_mstATA, attribute = "stimulus_type", cat_levels = c("history","social studies"), operator = "=", target_num = c(1,1), which_module = 1) spec3<-test_stimcat_con( x = test_mstATA, attribute = "stimulus_type", cat_levels = "history", operator = "=", target_num = 2, which_module = 2:4) spec4<-test_stimcat_con( x = test_mstATA, attribute = "stimulus_type", cat_levels = "social studies", operator = "=", target_num = 2, which_module = 5:7) spec5<-stim_itemcount_con( x = test_mstATA, min = 5, max = 7 ) obj_term<-objective_term(x = test_mstATA,attribute = "discrimination", applied_level = "Module-level",which_module = 1,sense = "max") panel_spec <- onepanel_spec( x = test_mstATA, constraints = list(spec1,spec2,spec3,spec4,spec5), objective = single_obj(x=test_mstATA,single_term = obj_term) )
This function generates a linear constraint matrix that restricts the number of items belonging to specified categorical levels (e.g., content area, format type) across all modules/pathways in an MST panel.
The constraint may enforce:
a minimum number of items in category c,
a maximum number of items in category c, or
an exact (equality) requirement for category c.
The total number of constraints equals the number of category levels supplied
in cat_levels.
panel_itemcat_con(x, attribute, cat_levels, operator, target_num)panel_itemcat_con(x, attribute, cat_levels, operator, target_num)
x |
An object of class |
attribute |
A string giving the column name in |
cat_levels |
A character string or vector of categorical attribute levels. These define the item categories being constrained. |
operator |
A character string indicating the type of constraint.
Must be one of |
target_num |
A scalar or vector specifying the required number of items
for each category in |
1. Specification
The constraint enforces:
A minimum, exact, or maximum number of items from specified categorical levels must be selected within a panel.
Key characteristics:
The attribute type is categorical.
The attribute is defined at the item level in the item pool.
The constraints are applied at the Panel-level.
Users may restrict the constraints to any subset of categories via the
cat_levels argument.
An object of S3 class "constraint" with named elements:
A character vector indicating the specifications in each row of A_binary
A data.frame summarizing the constraint specification, including
the requirement name, attribute, constraint type, application level,
operator, and the number of constraint rows generated.
A sparse binary matrix representing the linear constraint coefficients.
NULL for 'mstATA_constraint' object
A character vector of constraint operators, one per row of A_binary.
A numeric vector of right-hand-side values for the constraints.
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
Suppose the item pool contains (S - 1) stimulus-based item sets, indexed by
. Each stimulus has a designated pivot item,
indexed by . In addition, the pool contains a set of discrete
(non-stimulus-based) items, which are represented by a dummy stimulus
to allow a unified indexing scheme. Items belonging to stimulus
are indexed as .
Suppose there are modules in an MST panel. Let
denote the module index.
Let denote the set of
items that belong to category c.
Here:
is the binary decision variable indicating whether
item is selected into module m.
The stacked operator, denotes that the specification may take the form of an upper bound, lower bound, or exact value.
specify the required number of items from category level c in a panel.
data("mini_itempool") test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", module_length = c(4,2,2,2,2,2,2) ) # Example 1: Require at least 10 multiple-choice items in the panel panel_itemcat_con( x = test_mstATA, attribute = "itemtype", cat_levels = "MC", operator = ">=", target_num = 10 ) # Example 2: Require at least 10 multiple-choice items, at least 3 TEI items in the panel panel_itemcat_con( x = test_mstATA, attribute = "itemtype", cat_levels = c("MC","TEI"), operator = ">=", target_num = c(10,5) )data("mini_itempool") test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", module_length = c(4,2,2,2,2,2,2) ) # Example 1: Require at least 10 multiple-choice items in the panel panel_itemcat_con( x = test_mstATA, attribute = "itemtype", cat_levels = "MC", operator = ">=", target_num = 10 ) # Example 2: Require at least 10 multiple-choice items, at least 3 TEI items in the panel panel_itemcat_con( x = test_mstATA, attribute = "itemtype", cat_levels = c("MC","TEI"), operator = ">=", target_num = c(10,5) )
This function constructs panel-level constraints that limit how many times an item may be selected across the modules and pathways contained within a single MST panel.
Two reuse-control modes are supported via overlap:
overlap = FALSE – No item reuse anywhere in the panel (the item may appear in at most one module across the entire panel).
overlap = TRUE – Item reuse is permitted across adaptive modules within the same stage, but items must remain unique within each individual pathway.
If item_module_eligibility = NULL in mst_design(),
the total number of constraints depends on overlap:
overlap = FALSE:
The number of constraints = number of items in the item pool.
overlap = TRUE:
The number of constraints = (number of items) x (number of pathways).
panel_itemreuse_con(x, overlap = FALSE)panel_itemreuse_con(x, overlap = FALSE)
x |
An object of class |
overlap |
Logical.
If |
1. Specification
The constraint enforces:
An item can be selected at most once within a pathway/panel.
Key characteristics:
The attribute type is logical (if..., then...) with item identifier: each item has an unique ID.
The attribute is defined at the itemset level (item-itself set) in the item pool.
The constraint is enforced at the Panel-level, i.e., across all modules and pathways in a panel.
2. Interpretation of overlap
overlap = FALSE – Strict item uniqueness within the entire panelUnder this condition:
An item may appear in at most one module anywhere in the panel.
Selecting the item in any module automatically prevents its selection in all other modules of the panel.
The overlap among pathways are only due to the MST structure.
overlap = TRUE – Item reuse allowed within stage, but not within pathwayUnder this condition:
Items may be reused across adaptive modules in the same stage.
Items must not be reused within the same pathway (i.e., an item may appear at most once per pathway).
The overlap among pathways not only due to the MST structure, but also due to some common items across modules in the same stage.
(1) If an item is selected in the routing module implies it cannot appear in any S2 or S3 module.
(2) If selected in an S2 module implies it may appear in other S2 modules (same stage), but not in S1R or any S3 module.
(3) If selected in an S3 module implies it may appear in other S3 modules, but not in S1R or any S2 module.
3. Why This Is a Panel-Level Constraint
Although the constraint logic differs for the two overlap conditions, both versions govern item allocation across the set of modules that comprise a full panel. In other words, the constraint concerns how an item may or may not appear within the assembled panel as a whole, rather than applying to a specific module or pathway in isolation. For this reason, both cases are formally categorized as Panel-level item-reuse constraints.
An object of S3 class "constraint" with named elements:
A character vector indicating the specifications in each row of A_binary
A data.frame summarizing the constraint specification, including
the requirement name, attribute, constraint type, application level,
operator, and the number of constraint rows generated.
A sparse binary matrix representing the linear constraint coefficients.
NULL for 'mstATA_constraint' object
A character vector of constraint operators, one per row of A_binary.
A numeric vector of right-hand-side values for the constraints.
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
Suppose the item pool contains (S - 1) stimulus-based item sets, indexed by
. Each stimulus has a designated pivot item,
indexed by . In addition, the pool contains a set of discrete
(non-stimulus-based) items, which are represented by a dummy stimulus
to allow a unified indexing scheme. Items belonging to stimulus
are indexed as .
Suppose there are modules in an MST panel. Let
denote the module index.
Case 1: overlap = TRUE
Item must be unique within each pathway:
Case 2: overlap = FALSE
Item must be unique across the entire panel:
Here:
is the binary decision variable indicating whether
item is selected into module m.
denote modules belonging to pathway r.
data("mini_itempool") test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", module_length = c(4,2,2,2,2,2,2) ) # Example 1: No item overlap within a panel panel_itemreuse_con(x = test_mstATA, overlap = FALSE) # Example 2: Allow item reuse within the same stage panel_itemreuse_con(x = test_mstATA, overlap = TRUE) # Example 3: item_module_eligibility supplied -- disjoint module eligibility # No need for panel_itemreuse_con() in this case item_module_eligibility <- list( `1` = intersect(which(mini_itempool$difficulty >= -1), which(mini_itempool$difficulty < 0)), `2` = intersect(which(mini_itempool$difficulty >= -2), which(mini_itempool$difficulty < -1)), `3` = intersect(which(mini_itempool$difficulty >= 0), which(mini_itempool$difficulty < 1)), `4` = intersect(which(mini_itempool$difficulty >= 1), which(mini_itempool$difficulty < 2)) ) new_test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3", module_length = c(6,7,7,7), item_module_eligibility = item_module_eligibility ) ## The generated constraint matrix are redundant and will be omitted in the ATA model. try(panel_itemreuse_con(x = new_test_mstATA, overlap = FALSE)) # Example 4: Overlapping module eligibility -- reuse constraints required item_module_eligibility <- list( `1` = which(mini_itempool$difficulty < 2), `2` = which(mini_itempool$difficulty < 0), `3` = intersect(which(mini_itempool$difficulty >= -1), which(mini_itempool$difficulty < 1)), `4` = intersect(which(mini_itempool$difficulty >= 0), which(mini_itempool$difficulty < 2)) ) new_test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3", module_length = c(6,7,7,7), item_module_eligibility = item_module_eligibility ) # Items eligible for multiple modules require reuse control panel_itemreuse_con(x = new_test_mstATA, overlap = FALSE) # Overlap within stage implies item may appear in more modules panel_itemreuse_con(x = new_test_mstATA, overlap = TRUE)data("mini_itempool") test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", module_length = c(4,2,2,2,2,2,2) ) # Example 1: No item overlap within a panel panel_itemreuse_con(x = test_mstATA, overlap = FALSE) # Example 2: Allow item reuse within the same stage panel_itemreuse_con(x = test_mstATA, overlap = TRUE) # Example 3: item_module_eligibility supplied -- disjoint module eligibility # No need for panel_itemreuse_con() in this case item_module_eligibility <- list( `1` = intersect(which(mini_itempool$difficulty >= -1), which(mini_itempool$difficulty < 0)), `2` = intersect(which(mini_itempool$difficulty >= -2), which(mini_itempool$difficulty < -1)), `3` = intersect(which(mini_itempool$difficulty >= 0), which(mini_itempool$difficulty < 1)), `4` = intersect(which(mini_itempool$difficulty >= 1), which(mini_itempool$difficulty < 2)) ) new_test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3", module_length = c(6,7,7,7), item_module_eligibility = item_module_eligibility ) ## The generated constraint matrix are redundant and will be omitted in the ATA model. try(panel_itemreuse_con(x = new_test_mstATA, overlap = FALSE)) # Example 4: Overlapping module eligibility -- reuse constraints required item_module_eligibility <- list( `1` = which(mini_itempool$difficulty < 2), `2` = which(mini_itempool$difficulty < 0), `3` = intersect(which(mini_itempool$difficulty >= -1), which(mini_itempool$difficulty < 1)), `4` = intersect(which(mini_itempool$difficulty >= 0), which(mini_itempool$difficulty < 2)) ) new_test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3", module_length = c(6,7,7,7), item_module_eligibility = item_module_eligibility ) # Items eligible for multiple modules require reuse control panel_itemreuse_con(x = new_test_mstATA, overlap = FALSE) # Overlap within stage implies item may appear in more modules panel_itemreuse_con(x = new_test_mstATA, overlap = TRUE)
This function generates a linear constraint matrix based on a stimulus-level categorical attribute (e.g., stimulus type, passage theme) across all modules and pathways within a single panel.
The constraint may enforce:
a minimum number of stimuli in category c,
a maximum number of stimuli in category c, or
an exact (equality) requirement in category c.
The number of linear constraints generated equals the number of category
levels supplied in levels.
panel_stimcat_con(x, attribute, cat_levels, operator, target_num)panel_stimcat_con(x, attribute, cat_levels, operator, target_num)
x |
An object of class |
attribute |
A string giving the column name in |
cat_levels |
A character vector of category levels to be constrained.
Must match the unique values in the specified |
operator |
A character string specifying the constraint direction:
one of |
target_num |
A scalar or vector giving the required number of stimuli
in each category listed in |
1. Specification
The constraint enforces:
A minimum, exact, or maximum number of stimuli from specified categories must be selected somewhere within a panel.
Key characteristics:
The attribute type is categorical.
The attribute is defined at stimulus-level in the item pool.
The constraints are applied at the Panel-level.
Users may restrict the constraint to specific categories using the cat_levels argument.
An object of S3 class "mstATA_constraint" with named elements:
A character vector indicating the specifications in each row of A_binary
A data.frame summarizing the constraint specification, including
the requirement name, attribute, constraint type, application level,
operator, and the number of constraint rows generated.
A sparse binary matrix representing the linear constraint coefficients.
NULL for 'mstATA_constraint' object
A character vector of constraint operators, one per row of A_binary.
A numeric vector of right-hand-side values for the constraints.
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
Suppose the item pool contains (S - 1) stimulus-based item sets, indexed by
. Each stimulus has a designated pivot item,
indexed by . In addition, the pool contains a set of discrete
(non-stimulus-based) items, which are represented by a dummy stimulus
to allow a unified indexing scheme. Items belonging to stimulus
are indexed as .
Suppose there are modules in an MST panel. Let
denote the module index.
Let denote the set of
stimuli that belong to category c.
Here:
indicates whether the pivot item for stimulus
s is selected into module m, thereby indicating whether the
stimulus s is selected in that module.
The stacked operator, denotes that the specification may take the form of an upper bound, lower bound, or exact value.
specify the required number of stimuli from category level c across modules/pathways in a panel.
data("reading_itempool") pivot_stim_map <- create_pivot_stimulus_map( itempool = reading_itempool, stimulus = "stimulus", pivot_item = "pivot_item" ) # Example: Require at most 4 history passages in an assembled panel test_mstATA <- mst_design( itempool = reading_itempool, design = "1-3-3", module_length = c(10,12,12,12,15,15,15), exclude_pathway = c("1-1-3", "1-3-1"), pivot_stim_map = pivot_stim_map ) panel_stimcat_con( x = test_mstATA, attribute = "stimulus_type", cat_levels = "history", operator = "<=", target_num = 4 )data("reading_itempool") pivot_stim_map <- create_pivot_stimulus_map( itempool = reading_itempool, stimulus = "stimulus", pivot_item = "pivot_item" ) # Example: Require at most 4 history passages in an assembled panel test_mstATA <- mst_design( itempool = reading_itempool, design = "1-3-3", module_length = c(10,12,12,12,15,15,15), exclude_pathway = c("1-1-3", "1-3-1"), pivot_stim_map = pivot_stim_map ) panel_stimcat_con( x = test_mstATA, attribute = "stimulus_type", cat_levels = "history", operator = "<=", target_num = 4 )
Computes item response category probabilities under various IRT models
at a given ability value .
Pi_internal(theta, itempar_mat, model = NULL, D = 1)Pi_internal(theta, itempar_mat, model = NULL, D = 1)
theta |
A numeric scalar specifying the ability value at which probabilities are evaluated. |
itempar_mat |
A numeric matrix with one row per item and columns
corresponding to the required parameters for the specified IRT model.
The required structure depends on |
model |
A character string specifying the IRT model. Supported models are:
|
D |
Scaling constant used in the IRT model. Default is D=1 (for logistic metric); D=1.702 yields approximately the normal metric. |
(1) Dichotomous IRT models
For the models "1PL", "RASCH", "2PL",
"3PL", and "4PL", the argument itempar_mat
must be a numeric matrix with one row per item and four columns:
discrimination (), difficulty (),
guessing (),upper ().
(2) Polytomous IRT models
For a polytomous item j, let denote the maximum score,
so that the possible response categories are
.
The number of response categories may vary across items under the
"GRM", "PCM", "GPCM", and "NRM" models.
In contrast, under the "MGRM" and "RSM" models,
the number of response categories is assumed to be the same for all items.
The argument itempar_mat must be a numeric matrix with one row per item
and a number of columns determined by the specified IRT model. The required
structure is:
GRM:
A matrix with columns, containing parameters
,
where is the discrimination parameter and
are the ordered threshold parameters.
MGRM:
A matrix with columns, containing parameters
,
where is the discrimination parameter,
is the location parameter, and
are category step parameters.
PCM:
A matrix with columns, containing step parameters
.
GPCM:
A matrix with columns, containing parameters
,
where is the discrimination parameter and
are step parameters.
RSM:
A matrix with columns, containing parameters
,
where is the item location parameter and
are common step parameters across items.
NRM:
A matrix with columns, containing parameters
,
where and are the slope and intercept
parameters for category .
A list with components:
A matrix of category response probabilities. Rows correspond to items and columns correspond to categories.
Matrix of first derivatives
.
Plots category probability curves aggregated at the module or pathway level.
The function supports both single-panel and multi-panel visualization and automatically adjusts color and faceting to facilitate meaningful comparisons across modules, pathways, and panels.
plot_panel_tcc( assembled_panel, item_par_cols, model_col, D = 1, theta = seq(-5, 5, 0.1), unit = "module", mode = "within_panel", legend = TRUE )plot_panel_tcc( assembled_panel, item_par_cols, model_col, D = 1, theta = seq(-5, 5, 0.1), unit = "module", mode = "within_panel", legend = TRUE )
assembled_panel |
A |
item_par_cols |
A named list defining the IRT parameter columns
required for each supported model. The list names must exactly match
the model identifiers specified in |
model_col |
A character string specifying the column name in
either |
D |
Scaling constant used in the IRT model. Default is D=1 (for logistic metric); D=1.702 yields approximately the normal metric. |
theta |
A numeric vector of ability values. Default is |
unit |
The aggregation unit to display. Must be either
|
mode |
Plotting mode for multi-panel results. Must be either
|
legend |
Logical; whether to display the legend (default is TRUE). |
For a single panel, category probability curves are colored by module or pathway.
For multiple panels, two visualization modes are supported:
"within_panel": curves are colored by module or pathway
and faceted by panel.
"across_panel": curves are colored by panel and faceted
by module or pathway.
For dichotomously-scored items (two response categories), only the
probability curve for the correct-response category (cat1) is
displayed.
For polytomously-scored items (more than two response categories), probability curves for all response categories are displayed.
Category probability curves represent the average probability of each response category across items within the selected module or pathway at each ability value.
A ggplot object.
Plots test information functions (TIFs) aggregated at the module or pathway level.
The function supports both single-panel and multi-panel visualization and automatically adjusts color and faceting to facilitate meaningful comparisons across modules, pathways, and panels.
plot_panel_tif( assembled_panel, item_par_cols, model_col, D = 1, theta = seq(-5, 5, 0.1), unit = "module", mode = "within_panel", legend = TRUE )plot_panel_tif( assembled_panel, item_par_cols, model_col, D = 1, theta = seq(-5, 5, 0.1), unit = "module", mode = "within_panel", legend = TRUE )
assembled_panel |
A |
item_par_cols |
A named list defining the IRT parameter columns
required for each supported model. The list names must exactly match
the model identifiers specified in |
model_col |
A character string specifying the column name in
either |
D |
Scaling constant used in the IRT model. Default is D=1 (for logistic metric); D=1.702 yields approximately the normal metric. |
theta |
A numeric vector of ability values. |
unit |
The aggregation unit to display. Must be either
|
mode |
Plotting mode for multi-panel results. Must be either
|
legend |
Logical; whether to display the legend (default is TRUE). |
For a single panel, information curves are colored by module or pathway.
For multiple panels, two visualization modes are supported:
"within_panel": curves are colored by module or pathway
and faceted by panel.
"across_panel": curves are colored by panel and faceted
by module or pathway.
A ggplot object.
Plots testing information functions (TIFs).
plot_tif(items, item_par_cols, theta = seq(-3, 3, 0.1), model_col, D = 1)plot_tif(items, item_par_cols, theta = seq(-3, 3, 0.1), model_col, D = 1)
items |
A data frame containing item metadata.
Each row represents an item. The data frame must include a column
specifying the item model (see |
item_par_cols |
A named list defining the IRT parameter columns
required for each supported model. The list names must exactly match
the model identifiers specified in |
theta |
A numeric vector of ability values at which the IIFs are evaluated. |
model_col |
A character string specifying the column name in
|
D |
Scaling constant used in the IRT model. Default is D=1 (for logistic metric); D=1.702 yields approximately the normal metric. |
A ggplot object.
A simulated item pool consisting exclusively of polytomously scored items, designed to demonstrate multistage testing (MST) functionality under a partial credit modeling framework.
data(poly_itempool)data(poly_itempool)
A data frame with 50 rows and the following columns:
Unique identifier for each item.
Content area classification (e.g., content1, content2, content3, content4).
First step (threshold) parameter in the Partial Credit Model (PCM).
Second step (threshold) parameter in the Partial Credit Model (PCM).
Third step (threshold) parameter in the Partial Credit Model (PCM).
Item response theory (IRT) model used for all items (PCM).
Integer specifying the maximum number of response categories generated for the item.
data(poly_itempool)data(poly_itempool)
Prints a concise, human-readable summary of a compiled
mstATA_model object which is produced by
onepanel_spec() or multipanel_spec().
This print method is a diagnostic and inspection utility. It reports:
the number of binary and continuous decision variables,
the total number of linear constraints,
the objective sense ("min" or "max"),
and a formatted specification table mapping semantic requirements to solver constraint rows.
The specification table provides row-range traceability for debugging infeasibility and constraint prioritization.
## S3 method for class 'mstATA_model' print(x, ...)## S3 method for class 'mstATA_model' print(x, ...)
x |
An object of class |
... |
Further arguments passed to or from other methods. |
The input object x, returned invisibly.
A reading item pool for demonstrating MST functionality.
data(reading_itempool)data(reading_itempool)
A data frame with 500 rows and 15 columns:
Unique identifier for each item.
Content area classification (e.g., content1, content2, content3, content4).
Item format (e.g., MC, TEI).
Expected response time for the item.
Discrimination parameter () for the 3PL model.
Difficulty parameter () for the 3PL model.
Guessing parameter () for the 3PL model.
Item response theory (IRT) model used for the item (3PL).
Integer specifying the maximum number of response categories generated for the item.
enemy item pairs/sets information
associated stimulus information
the indicator of pivot items. A pivot item is defined as an item that is always selected for the test if and only if its stimulus is selected
enemy stimulus pairs/sets information
Stimulus types: history, social studies
Stimulus words
data(reading_itempool)data(reading_itempool)
A precomputed MST panel assembled with the HiGHS solver demonstrated in Stimulus Based Assessment vignettes.
reading_panelreading_panel
An object of class mstATA_panel.
Generated using mstATA::assembled_panels() and mstATA::solve_model()with the HiGHS solver.
Summarizes the number of selected items belonging to specified categorical attribute levels (e.g., content area, item type) within assembled MST panels. Summaries can be produced at the module level or pathway level, depending on the constraint scope.
report_test_itemcat( assembled_panel, attribute, cat_levels, which_module = NULL, which_pathway = NULL )report_test_itemcat( assembled_panel, attribute, cat_levels, which_module = NULL, which_pathway = NULL )
assembled_panel |
A |
attribute |
A character string specifying the name of a categorical
attribute in the item pool (e.g., |
cat_levels |
A character vector specifying the attribute levels
to be summarized (e.g., |
which_module |
Optional integer vector specifying module indices for module-level summaries. |
which_pathway |
Optional integer vector specifying pathway indices for pathway-level summaries. |
This function operates on the output of assembled_panel() and is
primarily intended for evaluating categorical test constraints.
The scope of the summary is determined by which_module and
which_pathway:
If which_module is provided, a module-level summary is returned
for the specified modules.
If which_pathway is provided, a pathway-level summary is returned
for the specified pathways.
If both which_module and which_pathway are NULL,
the function defaults to a module-level summary over all modules.
The attribute specified by attribute must be a categorical attribute.
This is verified internally using check_attribute_column(), and an
error is thrown if the attribute is not categorical.
Counts are reported separately for each requested attribute level.
For example, if cat_levels = c("MC", "TEI"), the output will
contain separate rows for MC and TEI items within each module or pathway.
A data frame with one row per panel-module (or panel-pathway) combination. The returned data frame contains:
Panel identifier.
Module or pathway identifier.
Number of selected items belonging to each specified categorical level within the corresponding module or pathway. Each category level appears as a separate column.
Summarizes quantitative item attributes (e.g., test information, time, difficulty) within assembled multistage test (MST) panels. The summary can be computed as either the sum or the average of the attribute values, at the module level or pathway level, depending on the constraint scope.
report_test_itemquant( assembled_panel, attribute, statistic = c("average", "sum"), which_module = NULL, which_pathway = NULL )report_test_itemquant( assembled_panel, attribute, statistic = c("average", "sum"), which_module = NULL, which_pathway = NULL )
assembled_panel |
A |
attribute |
A character string specifying the name of a
quantitative attribute in the item pool (e.g., |
statistic |
A character string specifying the summary statistic to
compute. One of |
which_module |
Optional integer vector specifying module indices for module-level summaries. |
which_pathway |
Optional integer vector specifying pathway indices for pathway-level summaries. |
This function operates on the output of assembled_panel() and is
primarily intended for evaluating quantitative test constraints.
The scope of the summary is determined by which_module and
which_pathway:
If which_module is provided, a module-level summary is returned
for the specified modules.
If which_pathway is provided, a pathway-level summary is returned
for the specified pathways.
If both which_module and which_pathway are NULL,
the function defaults to a module-level summary over all modules.
The attribute specified by attribute must be a quantitative attribute.
This is verified internally using check_attribute_column(), and an
error is thrown if the attribute is not quantitative.
A data frame with one row per panel-module (or panel-pathway) combination. The returned data frame contains:
Panel identifier.
Module or pathway identifier.
The name of the quantitative attribute being summarized.
The computed summary statistic (sum or average) of the specified quantitative attribute within the corresponding module or pathway.
Computes and reports TCC curves aggregated at the module or pathway level for assembled MST panels.
Item-level category probabilities are obtained from compute_icc().
report_test_tcc( assembled_panel, theta, item_par_cols, model_col, D = 1, which_module = NULL, which_pathway = NULL )report_test_tcc( assembled_panel, theta, item_par_cols, model_col, D = 1, which_module = NULL, which_pathway = NULL )
assembled_panel |
A |
theta |
A numeric vector of ability values. |
item_par_cols |
A named list defining the IRT parameter columns
required for each supported model. The list names must exactly match
the model identifiers specified in |
model_col |
A character string specifying the column name in
either |
D |
Scaling constant used in the IRT model. Default is D=1 (for logistic metric); D=1.702 yields approximately the normal metric. |
which_module |
Optional vector specifying which modules to include. |
which_pathway |
Optional vector specifying which pathways to include. |
A data frame containing the following columns:
Identifier of the assembled panel.
Identifier of the module or pathway.
Ability level at which the statistics are evaluated.
Test characteristic curve value, defined as the expected total score
.
Maximum possible score for the module or pathway.
Normalized TCC value defined as TCC / max_score.
Computes and reports test information functions aggregated at the module or pathway level for assembled MST panels.
Item information functions are computed using compute_iif(),
and then summed across items within specified module or pathway.
report_test_tif( assembled_panel, theta, item_par_cols, model_col, D = 1, which_module = NULL, which_pathway = NULL )report_test_tif( assembled_panel, theta, item_par_cols, model_col, D = 1, which_module = NULL, which_pathway = NULL )
assembled_panel |
A |
theta |
A numeric vector of ability values at which information functions are evaluated. |
item_par_cols |
A named list defining the IRT parameter columns
required for each supported model. The list names must exactly match
the model identifiers specified in |
model_col |
A character string specifying the column name in
either |
D |
Scaling constant used in the IRT model. Default is D=1 (for logistic metric); D=1.702 yields approximately the normal metric. |
which_module |
Optional integer vector specifying which modules to include. |
which_pathway |
Optional integer vector specifying which pathways to include. |
A data frame with one row per panel-module (or panel-pathway)-ability combination. The returned data frame contains:
Panel identifier.
Module or pathway identifier.
Ability value at which test information is evaluated.
Sum of item information functions for all selected items within the corresponding module or pathway, evaluated at the given ability value.
A data frame containing 400 3PL items, 20 GPCM items, and 20 GRM items. This item pool is adapted from the example item pool used to demonstrate multistage test assembly in the Rmst package.
data(Rmst_pool)data(Rmst_pool)
A data frame with 440 rows and 14 variables:
Unique identifier for each item.
IRT model specification for the item (e.g. "3PL", "GPCM", "GRM").
Discrimination parameter () for the 3PL model.
Difficulty parameter () for the 3PL model.
Guessing parameter () for the 3PL model.
Discrimination parameter () for GPCM and GRM models.
First step parameter () for the GPCM model.
Second step parameter () for the GPCM model.
Third step parameter () for the GPCM model.
First threshold parameter () for the GRM model.
Second threshold parameter () for the GRM model.
Content category classification of the item.
Item time.
Item group identifier.
Luo, X. (2019). Rmst: Computerized Adaptive Multistage Testing. R package version 0.0.3. doi:10.32614/CRAN.package.Rmst. https://CRAN.R-project.org/package=Rmst
data(Rmst_pool)data(Rmst_pool)
This function compiles a single-objective optimization problem for MST assembly. The optimization is to maximize or minimize a single linear score.
or
where is the linear objective term created by
objective_term().
single_obj(x, single_term)single_obj(x, single_term)
x |
An object of class |
single_term |
A single objective term created by |
1. Overview
There is only one objective term, representing a linear score of the form
, constructed by objective_term().
Key characteristics for the objective term:
(1) Categorical or Quantitative
maximize or minimize the number of items belonging to a specific categorical level, or
maximize or minimize the sum of quantitative item-level attribute values, such as difficulty, discrimination, or item information function values.
(2) Module-, Pathway- or Panel-level
"Module-level" – only items in a specified module contribute to the objective;
"Pathway-level" – items in all modules belonging to one pathway contribute; and
"Panel-level" – all item selections in the panel contribute.
(3) Relative or Absolute Objective
Relative objective: maximize/minimize .
Absolute deviation objective: minimize the deviation from
a specified target: , where is the target value.
Examples include:
Relative objective – "Maximize the number of items in category
selected in Module 1."
Absolute objective – "Minimize the deviation between the test
information at and the target value 15."
A list of class "compiled_objective"
A character vector indicating the specifications in each row of A_binary
A data.frame summarizing the constraint specification, including
the requirement name, attribute, constraint type, application level,
operator, and the number of constraint rows generated.
A sparse constraint matrix (class "Matrix") for binary
decision variables. Rows correspond to constraints; columns correspond to
binary decision variables.
A sparse constraint matrix (class "Matrix") for
continuous decision variables. Must have the same number of rows as
A_binary.
A character vector of constraint operators, one per row of A_binary.
A numeric vector of right-hand-side values for the constraints.
A numeric vector of objective coefficients for binary decision variables.
A numeric vector of objective coefficients for continuous decision variables.
"min" or "max"
Character vector indicating the names of new decision variables, same length as ncol(A_real).
A character vector of "C" (continuous), same length as ncol(A_real).
A list containing the strategy name, strategy arguments, and y_bounds.
Suppose the item pool contains (S - 1) stimulus-based item sets, indexed by
. Each stimulus has a designated pivot item,
indexed by . In addition, the pool contains a set of discrete
(non-stimulus-based) items, which are represented by a dummy stimulus
to allow a unified indexing scheme. Items belonging to stimulus
are indexed as .
Let denote the set of
items that belong to category c and
be the quantitative attribute value of item .
For absolute-deviation objectives, let be the target value and
be a non-negative deviation variable.
Suppose there are M modules in an MST panel, Let
denote the module id.
)(1a) Categorical attribute – relative objective
Specification: maximize or minimize the number of items from category in module .
(1b) Quantitative attribute – relative objective
Specification: maximize or minimize the sum of item-level quantitative attribute values in module .
(1c) Categorical attribute – absolute deviation objective
Specification: minimize deviation between the number of items from
category in module and the target value .
subject to
(1d) Quantitative attribute – absolute deviation objective
Specification: minimize deviation between the sum of item-level attribute values
and the target value .
subject to
)Let denote the set of modules belonging to pathway .
(2a) Categorical attribute – relative objective
(2b) Quantitative attribute – relative objective
(2c) Categorical attribute – absolute deviation objective
subject to
(2d) Quantitative attribute – absolute deviation objective
subject to
(3a) Categorical attribute – relative objective
(3b) Quantitative attribute – relative objective
(3c) Categorical attribute – absolute deviation objective
subject to
(3d) Quantitative attribute – absolute deviation objective
subject to
Let denote the set of
stimuli that belong to category c and
be the quantitative attribute value of stimulus .
The Module-/Pathway-/Panel level requirements can also be related with stimulus-level categorical/quantitative requirements.
data("mini_itempool") test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", exclude_pathway = c("1-1-3", "1-3-1"), pathway_length = 8 ) # Example 1: relative objective for information at theta = 0 in the routing module single_term <- objective_term( x = test_mstATA, attribute = "iif(theta=0)", cat_level = NULL, applied_level = "Module-level", which_module = 1, sense = "max" ) single_obj(x = test_mstATA, single_term = single_term) # Example 2: absolute objective for information at theta = 0 in the routing module single_term <- objective_term( x = test_mstATA, attribute = "iif(theta=0)", cat_level = NULL, applied_level = "Module-level", which_module = 1, sense = "min", goal = 10 ) single_obj(x = test_mstATA, single_term = single_term)data("mini_itempool") test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", exclude_pathway = c("1-1-3", "1-3-1"), pathway_length = 8 ) # Example 1: relative objective for information at theta = 0 in the routing module single_term <- objective_term( x = test_mstATA, attribute = "iif(theta=0)", cat_level = NULL, applied_level = "Module-level", which_module = 1, sense = "max" ) single_obj(x = test_mstATA, single_term = single_term) # Example 2: absolute objective for information at theta = 0 in the routing module single_term <- objective_term( x = test_mstATA, attribute = "iif(theta=0)", cat_level = NULL, applied_level = "Module-level", which_module = 1, sense = "min", goal = 10 ) single_obj(x = test_mstATA, single_term = single_term)
This function constructs solution-level constraints that regulate the number of unique items–across all panels–that belong to specified categorical levels.
This constraint may enforce:
a minimum number of unique items in category c,
a maximum number of unique items in category c, or
an exact number of unique items in category c
across the entire multi-panel MST solution.
Constraints are evaluated at the Solution-level, meaning that an item is considered 'selected' if it appears in any module of any panel.
The total number of constraints equals the number of categories in
cat_levels.
solution_itemcat_con(x, attribute, cat_levels, operator, target_num)solution_itemcat_con(x, attribute, cat_levels, operator, target_num)
x |
An object of class |
attribute |
A string giving the column name in |
cat_levels |
A character string or vector of category levels to constrain. These must be present in the unique values of the attribute column. |
operator |
A character string specifying the constraint type.
Must be one of |
target_num |
A scalar or vector giving the required number of unique
items for each category level in |
1. Specification
The constraint enforces:
A minimum, exact, or maximum number of unique items from specified categories must be selected across all assembled panels.
Key characteristics:
The attribute is type is categorical.
The attribute is defined at the item level in the item pool.
The constraint is applied at the Solution-level, i.e., across all panels.
Users may limit the constraint to a subset of categories using cat_levels.
An object of S3 class "mstATA_constraint" with named elements:
A character vector indicating the specifications in each row of A_binary
A data.frame summarizing the constraint specification, including
the requirement name, attribute, constraint type, application level,
operator, and the number of constraint rows generated.
A sparse binary matrix representing the linear constraint coefficients.
NULL for 'mstATA_constraint' object
A character vector of constraint operators, one per row of A_binary.
A numeric vector of right-hand-side values for the constraints.
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
Suppose the item pool contains (S - 1) stimulus-based item sets, indexed by
. Each stimulus has a designated pivot item,
indexed by . In addition, the pool contains a set of discrete
(non-stimulus-based) items, which are represented by a dummy stimulus
to allow a unified indexing scheme. Items belonging to stimulus
are indexed as .
For each item , if item is used in any module in any panel.
otherwise.
The solution-level variables track whether an item appears anywhere in the assembled multi-panel solution.
Let denote the set of
items that belong to category c.
Here:
is the binary decision variable indicating whether
item is used at least once across all panels.
denotes that the specification may take the form of an
upper bound, lower bound, or exact value.
is the required number of unique item from category c
across all panels.
data("mini_itempool") test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", module_length = c(4,2,2,2,2,2,2) ) # Require at least 2 unique content1 items and at least 6 unique content3 items solution_itemcat_con( x = test_mstATA, attribute = "content", cat_levels = c("content1", "content3"), operator = ">=", target_num = c(2, 6) )data("mini_itempool") test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", module_length = c(4,2,2,2,2,2,2) ) # Require at least 2 unique content1 items and at least 6 unique content3 items solution_itemcat_con( x = test_mstATA, attribute = "content", cat_levels = c("content1", "content3"), operator = ">=", target_num = c(2, 6) )
Constructs solution-level constraints on the total number of distinct items selected across all panels in a multistage test (MST) assembly.
This requirement enforces a user-specified:
minimum number of unique items,
maximum number of unique items, or
exact (fixed) number of unique items
that may appear anywhere across all assembled panels.
These constraints operate at the solution level, using decision variables that indicate whether an item appears in any module of any panel.
The number of constraints generated is 1. If both a range needs to be specified, call this function twice.
solution_itemcount_con(x, operator, target_num)solution_itemcount_con(x, operator, target_num)
x |
An object of class |
operator |
A character string specifying the constraint type.
Must be one of |
target_num |
A scalar giving the required number of unique items across panels. |
1. Specification
This constraint enforces:
A minimum, exact, or maximum number of unique items must be selected across all panels in one solution.
Key characteristics:
The attribute type is categorical: each item is assigned a unique ID.
The attribute is defined at the item level in the item pool.
The constraint is applied at the Solution-level, i.e., across all panels.
An object of S3 class "mstATA_constraint" with named elements:
A character vector indicating the specifications in each row of A_binary
A data.frame summarizing the constraint specification, including
the requirement name, attribute, constraint type, application level,
operator, and the number of constraint rows generated.
A sparse binary matrix representing the linear constraint coefficients.
NULL for 'mstATA_constraint' object
A character vector of constraint operators, one per row of A_binary.
A numeric vector of right-hand-side values for the constraints.
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
Suppose the item pool contains (S - 1) stimulus-based item sets, indexed by
. Each stimulus has a designated pivot item,
indexed by . In addition, the pool contains a set of discrete
(non-stimulus-based) items, which are represented by a dummy stimulus
to allow a unified indexing scheme. Items belonging to stimulus
are indexed as .
For each item , if item is used in any module in any panel.
otherwise.
The solution-level variables track whether an item appears anywhere in the assembled multi-panel solution.
The total number of unique item selected at the solution level is controlled through:
Here:
is the binary decision variable indicating whether
item is used at least once across all panels.
denotes that the specification may take the form of an
upper bound, lower bound, or exact value.
is the user-specified minimum, exact, or maximum number of unique items.
data("mini_itempool") test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3", module_length = c(3,4,4,4) ) # Require at least 20 unique items across all panels solution_itemcount_con(test_mstATA, operator = ">=",target_num = 20) # Require at least 20 at most 30 unique items across all panels con1<-solution_itemcount_con(test_mstATA, operator = ">=",target_num = 20) con2<-solution_itemcount_con(test_mstATA, operator = "<=",target_num = 30)data("mini_itempool") test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3", module_length = c(3,4,4,4) ) # Require at least 20 unique items across all panels solution_itemcount_con(test_mstATA, operator = ">=",target_num = 20) # Require at least 20 at most 30 unique items across all panels con1<-solution_itemcount_con(test_mstATA, operator = ">=",target_num = 20) con2<-solution_itemcount_con(test_mstATA, operator = "<=",target_num = 30)
This function constructs solution-level constraints that regulate the number of unique stimuli–across all panels–that belong to specified categorical levels.
The constraint may enforce:
a minimum number of stimuli in category c,
a maximum number of stimuli in category c, or
an exact (equality) requirement in category c.
across the entire multi-panel MST solution.
Constraints are evaluated at the Solution-level, meaning that a stimulus is considered 'selected' if it appears in any module of any panel.
The total number of constraints equals the number of categories in
cat_levels.
solution_stimcat_con(x, attribute, cat_levels, operator, target_num)solution_stimcat_con(x, attribute, cat_levels, operator, target_num)
x |
An object of class |
attribute |
A string giving the column name in |
cat_levels |
A character vector of category levels to be constrained.
Must match the unique values in the specified |
operator |
A character string specifying the constraint direction:
one of |
target_num |
A scalar or vector giving the required number of stimuli
in each category listed in |
1. Specification
The constraint enforces:
A minimum, exact, or maximum number of unique stimuli belonging to specified categories must be selected across all panels in the multi-panel MST assembly.
Key characteristics:
The attribute type is categorical.
The attribute is defined at stimulus level in the item pool.
The constraint is applied at the Solution-level, i.e., across all panels.
Users may limit the constraint to a subset of categories using cat_levels.
An object of S3 class "mstATA_constraint" with named elements:
A character vector indicating the specifications in each row of A_binary
A data.frame summarizing the constraint specification, including
the requirement name, attribute, constraint type, application level,
operator, and the number of constraint rows generated.
A sparse binary matrix representing the linear constraint coefficients.
NULL for 'mstATA_constraint' object
A character vector of constraint operators, one per row of A_binary.
A numeric vector of right-hand-side values for the constraints.
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
Suppose the item pool contains (S - 1) stimulus-based item sets, indexed by
. Each stimulus has a designated pivot item,
indexed by . In addition, the pool contains a set of discrete
(non-stimulus-based) items, which are represented by a dummy stimulus
to allow a unified indexing scheme. Items belonging to stimulus
are indexed as .
For each item , if item is used in any module in any panel.
otherwise.
The solution-level variables track whether an item appears anywhere in the assembled multi-panel solution.
Let denote the set of
stimuli that belong to category c.
Here:
indicates whether the pivot item for stimulus
s is selected in any panel, thereby indicating whether the stimulus s
is selected in any panel.
denotes that the specification may take the form of an
upper bound, lower bound, or exact value.
is the required number of unique stimuli from category c
across all panels.
data("reading_itempool") pivot_stim_map <- create_pivot_stimulus_map( itempool = reading_itempool, stimulus = "stimulus", pivot_item = "pivot_item" ) test_mstATA <- mst_design( itempool = reading_itempool, design = "1-3-3", module_length = c(14,12,12,12,12,12,12), pivot_stim_map = pivot_stim_map ) # Require at least 3 history passages and 4 social studies passages solution_stimcat_con( x = test_mstATA, attribute = "stimulus_type", cat_levels = c("history", "social studies"), operator = ">=", target_num = c(3, 4) )data("reading_itempool") pivot_stim_map <- create_pivot_stimulus_map( itempool = reading_itempool, stimulus = "stimulus", pivot_item = "pivot_item" ) test_mstATA <- mst_design( itempool = reading_itempool, design = "1-3-3", module_length = c(14,12,12,12,12,12,12), pivot_stim_map = pivot_stim_map ) # Require at least 3 history passages and 4 social studies passages solution_stimcat_con( x = test_mstATA, attribute = "stimulus_type", cat_levels = c("history", "social studies"), operator = ">=", target_num = c(3, 4) )
This function constructs a solution-level constraint that controls the number of distinct stimuli appearing in the final multi-panel MST assembly.
The constraint may impose a:
minimum number of unique stimuli,
maximum number of unique stimuli, or
fixed (exact) number of unique stimuli.
that may appear anywhere across all assembled panels.
The number of constraints generated is 1. If both a range needs to be specified, call this function twice.
solution_stimcount_con(x, operator, target_num)solution_stimcount_con(x, operator, target_num)
x |
An object of class |
operator |
A character string specifying the constraint type.
Must be one of |
target_num |
A scalar giving the required number of unique stimuli across panels. |
1. Specification
This constraint enforces:
A minimum, exact, or maximum number of unique stimuli must be selected across all panels in the assembled MST solution.
Key characteristics:
The attribute type is categorical: each stimulus is assigned a unique ID.
The attribute is defined at stimulus level in the item pool.
The constraint is enforced at the Solution-level, i.e., across all panels.
An object of S3 class "mstATA_constraint" with named elements:
A character vector indicating the specifications in each row of A_binary
A data.frame summarizing the constraint specification, including
the requirement name, attribute, constraint type, application level,
operator, and the number of constraint rows generated.
A sparse binary matrix representing the linear constraint coefficients.
NULL for 'mstATA_constraint' object
A character vector of constraint operators, one per row of A_binary.
A numeric vector of right-hand-side values for the constraints.
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
Suppose the item pool contains (S - 1) stimulus-based item sets, indexed by
. Each stimulus has a designated pivot item,
indexed by . In addition, the pool contains a set of discrete
(non-stimulus-based) items, which are represented by a dummy stimulus
to allow a unified indexing scheme. Items belonging to stimulus
are indexed as .
For each item ,
if item is used in any module in any panel.
otherwise.
The solution-level variables track whether an item appears anywhere in the assembled multi-panel solution.
The total number of unique stimuli selected at the solution level is controlled through:
Here:
indicates whether the pivot item for stimulus
s is selected in any panel, thereby indicating whether the stimulus s
is selected in any panel.
denotes that the specification may take the form of an
upper bound, lower bound, or exact value.
data("reading_itempool") pivot_stim_map <- create_pivot_stimulus_map( itempool = reading_itempool, stimulus = "stimulus", pivot_item = "pivot_item" ) test_mstATA <- mst_design( itempool = reading_itempool, design = "1-3-3", module_length = c(5,7,7,7,8,8,8), pivot_stim_map = pivot_stim_map ) # Require between 5 and 10 unique stimuli across all assembled panels con1<-solution_stimcount_con(test_mstATA,">=",5) con2<-solution_stimcount_con(test_mstATA,"<=",10)data("reading_itempool") pivot_stim_map <- create_pivot_stimulus_map( itempool = reading_itempool, stimulus = "stimulus", pivot_item = "pivot_item" ) test_mstATA <- mst_design( itempool = reading_itempool, design = "1-3-3", module_length = c(5,7,7,7,8,8,8), pivot_stim_map = pivot_stim_map ) # Require between 5 and 10 unique stimuli across all assembled panels con1<-solution_stimcount_con(test_mstATA,">=",5) con2<-solution_stimcount_con(test_mstATA,"<=",10)
Solves an automated test assembly (ATA) model in the mstATA framework. The input model specification is optionally presolved to remove redundant rows and columns, checked for feasibility, and then solved using the requested solver.
solve_model( model_spec, continuous_bound_source = "compiled", continuous_bounds = NULL, solver = c("gurobi", "lpsolve", "HiGHS", "Symphony", "GLPK"), time_limit = 99999, check_feasibility = FALSE, show_progress = FALSE )solve_model( model_spec, continuous_bound_source = "compiled", continuous_bounds = NULL, solver = c("gurobi", "lpsolve", "HiGHS", "Symphony", "GLPK"), time_limit = 99999, check_feasibility = FALSE, show_progress = FALSE )
model_spec |
An assembly model specification of class
|
continuous_bound_source |
Character string specifying how lower and
upper bounds for continuous decision variables are determined.
Must be one of
The default is |
continuous_bounds |
A named list specifying user-defined bounds for
continuous decision variables when
The length of each vector must equal the number of continuous variables (not slack variables)
in the model. Each element of |
solver |
A character string indicating which solver to use.
One of |
time_limit |
The maximum amount of computation time allocated to the solver. Default is 99999 seconds. |
check_feasibility |
Logical. Default is |
show_progress |
Logical. Whether to display solver progress information (e.g., incumbent
solutions, node counts, and optimality gap) during optimization. Note that the level of
detail depends on the underlying solver. Default is |
A list with the following components:
A list containing the solver results with the following elements:
A character string indicating the solver status
(e.g., "OPTIMAL", "FEASIBLE", or "INFEASIBLE",
or "UNBOUNDED" or "TIME_LIMIT" or "OTHER").
A numeric vector of decision variable values corresponding to the best solution found.
The objective function value associated with
best_solution.
Either NULL or a list of optimal solutions.
If multiple optimal solutions exist, only the "gurobi" solver
may return more than one solution.
Either NULL or a data frame summarizing constraint
evaluation at the solution, including left-hand side values,
constraint operators, right-hand side values, and residual values.
The total runtime of the solver in seconds.
If solver = "gurobi" and
model is infeasible, an irreducible inconsistent subsystem (IIS) will also be returned.
It should be mentioned that an infeasible model may have multiple IISs.
The one returned by Gurobi is not necessarily the smallest one;
there may exist others with fewer constraints or bounds.
An object of class "mstATA_model" representing the
MILP formulation used by the solver. This includes the constraint
matrix A, right-hand side rhs, constraint senses,
objective coefficients, bounds, variable types, variable names,
model sense, and row names.
A character string indicating the solver used (as requested
by solver).
Attempts to recover feasibility for an infeasible mstATA_model by
relaxing selected non-core constraint blocks using slack variables with
user-specified penalties. A single continuous slack variable is introduced
for each relaxable constraint block, allowing controlled violations while
preserving the core structure of the MST design.
This function is intended as a diagnostic and fallback tool rather than a replacement for strict feasibility checks.
solve_with_slack( model_spec, cat_penalty, quant_penalty, solver = c("gurobi", "lpsolve", "HiGHS", "Symphony", "GLPK"), time_limit = 99999 )solve_with_slack( model_spec, cat_penalty, quant_penalty, solver = c("gurobi", "lpsolve", "HiGHS", "Symphony", "GLPK"), time_limit = 99999 )
model_spec |
An object of class |
cat_penalty |
Numeric scalar giving the penalty coefficient applied to slack variables associated with categorical constraint blocks. Larger values discourage violations of categorical requirements. |
quant_penalty |
Numeric scalar giving the penalty coefficient applied to slack variables associated with quantitative constraint blocks. |
solver |
A character string indicating which solver to use.
One of |
time_limit |
The maximum amount of computation time allocated to the solver. Default is 99999 seconds. |
The relaxed model is constructed as follows:
Hard constraints (never relaxed):
Objective-related constraints.
Essential MST structure constraints (e.g., module- and pathway-level item count constraints, optional requirements for routing decision points).
Logical constraints (e.g., enemy relationships, item-stimulus grouping relationships, item exposure control).
Equality constraints, identified by
specification$Operator == "(exact)" at the block level.
Soft constraints (relaxed with slack):
Categorical constraint blocks.
Quantitative constraint blocks.
For each relaxable constraint block, one nonnegative continuous slack variable is introduced and shared across all rows in that block. Slack coefficients are assigned according to the row operator:
For "<=" rows, the slack enters with coefficient .
For ">=" rows, the slack enters with coefficient .
Soft constraint blocks must contain only "<=" or ">=" rows.
The objective function is augmented by adding penalty terms for each slack variable. Categorical slack variables are penalized more heavily than quantitative slack variables to reflect their higher priority.
A solver result object returned by solve_model(), containing the
optimized solution, solver status, and objective value for the relaxed model.
Slack variable values indicate the magnitude of constraint violations at the
block level.
Consider an infeasible mstATA model consisting of a set of constraint blocks
indexed by . Each block corresponds to one row in
the specification table and may contain multiple linear constraint rows
indexed by .
For each constraint row, let denote the left-hand side
linear expression and the right-hand side constant.
Soft constraint blocks and slack variables.
For each relaxable constraint block (categorical or quantitative),
a single nonnegative continuous slack variable is introduced
and shared across all rows in that block.
Original (hard) constraints.
For a row , the original linear constraint takes one
of the following forms:
Upper-bound constraint:
Lower-bound constraint:
Equality constraints () are not relaxable and therefore
are excluded from slack construction.
Relaxed constraints with block-level slack.
For a relaxable block , each row is modified
as follows:
If the original row is , the relaxed form is
If the original row is , the relaxed form is
Equivalently, in matrix form, the slack variable enters each row
with coefficient for "<=" constraints and for
">=" constraints. A single slack variable therefore bounds the maximum
violation across all rows in the block.
Categorical vs quantitative constraints. The mathematical relaxation is identical for categorical and quantitative constraint. They differ only in the penalty applied to their slack variables in the objective function. Categorical constraints are penalized more heavily to reflect higher priority.
Objective function with slack penalties.
Let and denote
the sets of categorical and quantitative soft constraint blocks, respectively.
The relaxed optimization problem augments the original objective by adding
slack penalties:
where denotes the original objective function, and
are user-specified
penalty coefficients.
If the original problem is a maximization problem, the equivalent formulation is obtained by subtracting the slack penalties from the objective:
The resulting solution represents a best-compromise feasible design that minimizes violations of high-priority constraints before lower-priority ones.
This function constructs linear constraints ensuring that, for every selected stimulus, the items associated with that stimulus meet the required minimum, exact, or maximum counts from specified categorical levels (e.g., content area, skill type, item format).
The total number of generated linear constraints =
(number of stimuli) x (number of category levels) x (number of involved modules)
For a range constraint (i.e., both a minimum and a maximum number of items requirement), the function must be called twice:
once with target_num = min and operator = ">=", and
once with target_num = max and operator = "<=".
stim_itemcat_con( x, attribute, cat_levels, operator, target_num, which_module = NULL, which_pathway = NULL )stim_itemcat_con( x, attribute, cat_levels, operator, target_num, which_module = NULL, which_pathway = NULL )
x |
An object of class |
attribute |
A string giving the column name in |
cat_levels |
Character vector of category levels to constrain. Must match values
in |
operator |
A character string specifying the inequality or equality
operator. Must be one of |
target_num |
A scalar/vector specifying the required number of items for
the category levels in |
which_module |
Integer vector of modules. Must be consistent with the choices made in:
|
which_pathway |
Integer vector of pathways. Must be consistent with the choices made in:
|
The constraint enforced is:
If a stimulus is selected, a minimum, exact, or maximum number of its linked items must belong to the specified category level.
The key properties of this constraint are:
The attribute type is logical: a conditional "if-then" relationship between the selection of a stimulus and the required selection of its associated items.
The attribute is defined at the itemset level: set size for each stimulus in the item pool through the mapping between a stimulus and the items that belong to it.
Conditional stimulus-item constraints (such as
stim_itemcount_con(), stim_itemcat_con(),
stim_itemquant_con()) must be applied at the "Module-level" because
items linked to a selected stimulus cannot be distributed across multiple modules: if the stimulus is
selected in a module, all items required from that stimulus must appear in
the same module.
Important: The arguments which_module and
which_pathway must be consistent with the choices made in
test_stimcount_con(), test_stimcat_con(),
and test_stimquant_con().
An object of S3 class "mstATA_constraint" with named elements:
A character vector indicating the specifications in each row of A_binary
A data.frame summarizing the constraint specification, including
the requirement name, attribute, constraint type, application level,
operator, and the number of constraint rows generated.
A sparse binary matrix representing the linear constraint coefficients.
NULL for 'mstATA_constraint' object
A character vector of constraint operators, one per row of A_binary.
A numeric vector of right-hand-side values for the constraints.
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
Suppose the item pool contains (S - 1) stimulus-based item sets, indexed by
. Each stimulus has a designated pivot item,
indexed by . In addition, the pool contains a set of discrete
(non-stimulus-based) items, which are represented by a dummy stimulus
to allow a unified indexing scheme. Items belonging to stimulus
are indexed as .
Suppose there are modules in an MST panel. Let
denote the module index.
Let denote the set of
items that belong to category c.
Here:
is the binary decision variable indicating whether
item is selected into module m.
indicates whether the pivot item for stimulus
s is selected into module m, thereby indicating whether the
stimulus s is selected in that module.
and are the required minimum and maximum
number of stimulus-based items from category level c if stimulus s is selected.
data("reading_itempool") pivot_stim_map <- create_pivot_stimulus_map( itempool = reading_itempool, stimulus = "stimulus", pivot_item = "pivot_item" ) test_mstATA <- mst_design( itempool = reading_itempool, design = "1-3-3", module_length = c(14,12,12,12,12,12,12), pivot_stim_map = pivot_stim_map ) # Example 1: At least 2 MC and at least 1 TEI item must be selected when the stimulus is selected. stim_itemcat_con( x = test_mstATA, attribute = "itemtype", cat_levels = c("MC","TEI"), operator = ">=", target_num = c(2,1) ) # Example 2: At most 5 MC and at most 3 TEI items may be selected from each stimulus. stim_itemcat_con( x = test_mstATA, attribute = "itemtype", cat_levels = c("MC","TEI"), operator = "<=", target_num = c(5,3) ) # Example 3: Exactly 4 MC and 2 TEI items must be selected from each stimulus. stim_itemcat_con( x = test_mstATA, attribute = "itemtype", cat_levels = c("MC","TEI"), operator = "=", target_num = c(4,2) )data("reading_itempool") pivot_stim_map <- create_pivot_stimulus_map( itempool = reading_itempool, stimulus = "stimulus", pivot_item = "pivot_item" ) test_mstATA <- mst_design( itempool = reading_itempool, design = "1-3-3", module_length = c(14,12,12,12,12,12,12), pivot_stim_map = pivot_stim_map ) # Example 1: At least 2 MC and at least 1 TEI item must be selected when the stimulus is selected. stim_itemcat_con( x = test_mstATA, attribute = "itemtype", cat_levels = c("MC","TEI"), operator = ">=", target_num = c(2,1) ) # Example 2: At most 5 MC and at most 3 TEI items may be selected from each stimulus. stim_itemcat_con( x = test_mstATA, attribute = "itemtype", cat_levels = c("MC","TEI"), operator = "<=", target_num = c(5,3) ) # Example 3: Exactly 4 MC and 2 TEI items must be selected from each stimulus. stim_itemcat_con( x = test_mstATA, attribute = "itemtype", cat_levels = c("MC","TEI"), operator = "=", target_num = c(4,2) )
This function constructs linear constraints that enforce minimum, exact, or maximum counts on the number of items associated with a selected stimulus. It supports both full selection (all items linked to a stimulus must be selected if the stimulus is selected) and partial selection (only a subset of linked items must be selected).
The total number of generated linear constraints depends on the provided values of
min and max.
Full selection (min = NULL and max = NULL): All items linked to a stimulus must either all be selected or all not be selected.
The number of constraints is 2 x (number of stimuli) x (number of involved modules).
For each stimulus, the lower bound and the upper bound is the number of items linked to the stimulus.
Only max is specified: An upper bound is imposed, but no lower bound.
The number of constraints is (number of stimuli) x (number of involved modules).
Only min is specified: A lower bound is imposed; the upper bound defaults to the total number of items belonging to that stimulus.
The number of constraints is 2 x (number of stimuli) x (number of involved modules).
Both min and max are specified:
The number of constraints is 2 x (number of stimuli) x (number of invovle modules).
stim_itemcount_con( x, min = NULL, max = NULL, which_module = NULL, which_pathway = NULL )stim_itemcount_con( x, min = NULL, max = NULL, which_module = NULL, which_pathway = NULL )
x |
An object of class |
min |
An optional scalar specifying the minimum number of items to be included conditional on the selection of its stimulus. |
max |
An optional scalar specifying the maximum number of items to be included conditional on the selection of its stimulus. |
which_module |
Integer vector of modules. Must be consistent with the choices made in:
|
which_pathway |
Integer vector of pathways. Must be consistent with the choices made in:
|
The constraint enforced is:
If a stimulus is selected, then a minimum, exact, or maximum number of items linked to that stimulus must also be selected.
The key properties of this constraint are:
The attribute type is logical: a conditional "if-then" relationship between the selection of a stimulus and the required selection of its associated items.
The attribute is defined at the itemset level: set size for each stimulus in the item pool through the mapping between a stimulus and the items that belong to it.
Conditional stimulus-item constraints (such as
stim_itemcount_con(), stim_itemcat_con(),
stim_itemquant_con()) must be applied at the "Module-level" because
items linked to a selected stimulus cannot be distributed across multiple modules: if the stimulus is
selected in a module, all items required from that stimulus must appear in
the same module.
Important: The arguments which_module and
which_pathway must be consistent with the choices made in
test_stimcount_con(), test_stimcat_con(),
and test_stimquant_con().
An object of S3 class "mstATA_constraint" with named elements:
A character vector indicating the specifications in each row of A_binary
A data.frame summarizing the constraint specification, including
the requirement name, attribute, constraint type, application level,
operator, and the number of constraint rows generated.
A sparse binary matrix representing the linear constraint coefficients.
NULL for 'mstATA_constraint' object
A character vector of constraint operators, one per row of A_binary.
A numeric vector of right-hand-side values for the constraints.
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
Suppose the item pool contains (S - 1) stimulus-based item sets, indexed by
. Each stimulus has a designated pivot item,
indexed by . In addition, the pool contains a set of discrete
(non-stimulus-based) items, which are represented by a dummy stimulus
to allow a unified indexing scheme. Items belonging to stimulus
are indexed as .
Suppose there are modules in an MST panel. Let
denote the module index.
Partial selection with min and max constraints
Here:
is the binary decision variable indicating whether
item is selected into module m.
indicates whether the pivot item for stimulus
s is selected into module m, thereby indicating whether the
stimulus is selected in that module.
and specify the minimum and maximum
allowable number of items that must be selected if its stimulus is selected.
All-in/All-out selection:
where is the number of items linked to stimulus s.
Partial selection with min constraints
where specifies the minimum number of items that must be selected if its stimulus is selected.
is the number of items linked to stimulus s. The requirement that a maximum number of items that must
be selected if its stimulus is selected is automatically added.
This produces a safe gating constraint: if the pivot item is not selected
(meaning the stimulus is not selected), then
forces all corresponding item-selection variables ,
ensuring that no items from an unselected stimulus can be selected.
Partial selection with max constraints
where specifies the minimum and maximum
number of items that must be selected if its stimulus is selected.
When the pivot item is not selected
(meaning the stimulus is not selected),
forces all corresponding item-selection variables ,
ensuring that no items from an unselected stimulus can be selected.
data("reading_itempool") pivot_stim_map <- create_pivot_stimulus_map( itempool = reading_itempool, stimulus = "stimulus", pivot_item = "pivot_item" ) test_mstATA <- mst_design( itempool = reading_itempool, design = "1-3-3", module_length = c(14, 12, 12, 12, 12, 12, 12), pivot_stim_map = pivot_stim_map ) # Example 1: Full selection. # If a stimulus is selected, all items linked to that stimulus must also be selected. stim_itemcount_con(x = test_mstATA) # Example 2: Range selection (min and max). # If a stimulus is selected, between 2 and 5 of its linked items must be selected. stim_itemcount_con( x = test_mstATA, min = 2, max = 5 ) # Example 3: Minimum-only selection. # If a stimulus is selected, at least 5 of its items must be selected. # Upper bound defaults to total items per stimulus stim_itemcount_con( x = test_mstATA, min = 5 ) # Example 4: Maximum-only selection. # If a stimulus is selected, at most 8 of its items may be selected. # Only upper bound active stim_itemcount_con( x = test_mstATA, max = 8 ) # Example 5: Exact selection. # If a stimulus is selected, exactly 6 of its items must be selected (min = max = 6). stim_itemcount_con( x = test_mstATA, min = 6, max = 6 )data("reading_itempool") pivot_stim_map <- create_pivot_stimulus_map( itempool = reading_itempool, stimulus = "stimulus", pivot_item = "pivot_item" ) test_mstATA <- mst_design( itempool = reading_itempool, design = "1-3-3", module_length = c(14, 12, 12, 12, 12, 12, 12), pivot_stim_map = pivot_stim_map ) # Example 1: Full selection. # If a stimulus is selected, all items linked to that stimulus must also be selected. stim_itemcount_con(x = test_mstATA) # Example 2: Range selection (min and max). # If a stimulus is selected, between 2 and 5 of its linked items must be selected. stim_itemcount_con( x = test_mstATA, min = 2, max = 5 ) # Example 3: Minimum-only selection. # If a stimulus is selected, at least 5 of its items must be selected. # Upper bound defaults to total items per stimulus stim_itemcount_con( x = test_mstATA, min = 5 ) # Example 4: Maximum-only selection. # If a stimulus is selected, at most 8 of its items may be selected. # Only upper bound active stim_itemcount_con( x = test_mstATA, max = 8 ) # Example 5: Exact selection. # If a stimulus is selected, exactly 6 of its items must be selected (min = max = 6). stim_itemcount_con( x = test_mstATA, min = 6, max = 6 )
Creates a conditional quantitative constraint requiring that, if a stimulus is selected, the sum of quantitative attribute values of the items linked to that stimulus must satisfy a user-specified lower bound, upper bound, or exact value.
This function enforces a logical "if-then" relationship between stimulus selection and the quantitative properties (difficulty, response time) of its associated items.
The total number of generated linear constraints = (number of stimuli) x (number of involved modules)
For a range constraint (i.e., both a minimum and a maximum quantitative requirement), the function must be called twice:
once with target_value = min and operator = ">=", and
once with target_value = max and operator = "<=".
stim_itemquant_con( x, attribute, operator, target_value, which_module = NULL, which_pathway = NULL )stim_itemquant_con( x, attribute, operator, target_value, which_module = NULL, which_pathway = NULL )
x |
An object of class |
attribute |
A string giving the column name in |
operator |
A character string of constraint operators, one of
|
target_value |
Target values in specific module/pathway ( |
which_module |
Integer vector of modules. Must be consistent with the choices made in:
|
which_pathway |
Integer vector of pathways. Must be consistent with the choices made in:
|
The constraint enforced is:
If a stimulus is selected, then the items linked to it must collectively satisfy a minimum, maximum, or exact sum of a quantitative item attribute.
The key properties of this constraint are:
The attribute type is logical: a conditional "if-then" relationship between the selection of a stimulus and the required selection of its associated items.
The attribute is defined at the itemset level: set size for each stimulus in the item pool through the mapping between a stimulus and the items that belong to it.
Conditional stimulus-item constraints (such as
stim_itemcount_con(), stim_itemcat_con(),
stim_itemquant_con()) must be applied at the "Module-level" because
items linked to a selected stimulus cannot be distributed across multiple modules: if the stimulus is
selected in a module, all items required from that stimulus must appear in
the same module.
Important: The arguments which_module and
which_pathway must be consistent with the choices made in
test_stimcount_con(), test_stimcat_con(),
and test_stimquant_con().
An object of S3 class "mstATA_constraint" with named elements:
A character vector indicating the specifications in each row of A_binary
A data.frame summarizing the constraint specification, including
the requirement name, attribute, constraint type, application level,
operator, and the number of constraint rows generated.
A sparse binary matrix representing the linear constraint coefficients.
NULL for 'mstATA_constraint' object
A character vector of constraint operators, one per row of A_binary.
A numeric vector of right-hand-side values for the constraints.
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
Suppose the item pool contains (S - 1) stimulus-based item sets, indexed by
. Each stimulus has a designated pivot item,
indexed by . In addition, the pool contains a set of discrete
(non-stimulus-based) items, which are represented by a dummy stimulus
to allow a unified indexing scheme. Items belonging to stimulus
are indexed as .
Suppose there are modules in an MST panel. Let
denote the module index.
Let be the quantitative attribute value of item . Then for
module m, the conditional constraint is:
Here:
is the binary decision variable indicating whether
item is selected into module m.
indicates whether the pivot item for stimulus
s is selected into module m, thereby indicating whether the
stimulus s is selected in that module.
is the required quantitative bound for the sum of
item-level quantitative attribute linked to every stimulus
in module m (minimum, maximum, or exact value).
data("reading_itempool") pivot_stim_map<-create_pivot_stimulus_map(itempool = reading_itempool, stimulus = "stimulus", pivot_item = "pivot_item") # Example 1: if a stimulus is chosen, the sum difficulty of its linked items # may be required to be smaller than 0.5. test_mstATA<-mst_design(itempool = reading_itempool,design = "1-3-3", module_length = c(14,12,12,12,12,12,12), pivot_stim_map = pivot_stim_map) stim_itemquant_con(x = test_mstATA,attribute = "difficulty", operator = "<=",target_value = 0.5, which_module = NULL,which_pathway = NULL)data("reading_itempool") pivot_stim_map<-create_pivot_stimulus_map(itempool = reading_itempool, stimulus = "stimulus", pivot_item = "pivot_item") # Example 1: if a stimulus is chosen, the sum difficulty of its linked items # may be required to be smaller than 0.5. test_mstATA<-mst_design(itempool = reading_itempool,design = "1-3-3", module_length = c(14,12,12,12,12,12,12), pivot_stim_map = pivot_stim_map) stim_itemquant_con(x = test_mstATA,attribute = "difficulty", operator = "<=",target_value = 0.5, which_module = NULL,which_pathway = NULL)
This function generates linear constraints that force specific stimuli to be either selected or not selected in the MST panel assembly.
This constraint can be enforced at the "Module-level", "Pathway-level", or
"Panel-level".
The number of generated linear constraints depends on the application level:
Module-level: when which_module is provided and
which_pathway = NULL
The number of constraints is (number of stimuli in stim_ids) x (number of modules specified)
Pathway-level: when which_pathway is provided and
which_module = NULL
The number of constraints is (number of stimuli in stim_ids) x (number of pathways specified)
Panel-level: both which_module and which_pathway are NULL
The number of constraints is (number of stimuli in stim_ids)
stimcat_con( x, stim_ids, select = TRUE, which_module = NULL, which_pathway = NULL )stimcat_con( x, stim_ids, select = TRUE, which_module = NULL, which_pathway = NULL )
x |
An object of class |
stim_ids |
A numeric vector of stimuli indices or a character vector of stimuli names |
select |
Logical. Default is TRUE. |
which_module |
Integer vector of modules. Must be consistent with the choices made in:
|
which_pathway |
Integer vector of pathways. Must be consistent with the choices made in:
|
1. Specification
The constraint enforced by this function is:
The specified stimuli must be selected or not selected in the chosen set of modules, pathways, or across the entire panel.
The key properties of this constraint are:
The attribute type is categorical: each stimulus has a unique ID and may be treated as an unique category.
The constraint is defined at the stimulus level in the item pool (each stimulus is a distinct entity).
The constraint can be applied at:
"Module-level" implies stimulus must be selected/not selected in the
specified module(s).
"Pathway-level" implies stimulus must be selected/not selected in one
of the modules composing that pathway.
"Panel-level" implies stimulus must be selected/not selected somewhere in the
panel (but placement is not specified).
2. Interaction with panel_itemreuse_con()
When overlap = FALSE in panel_itemreuse_con(), each item can at most be selected once
in a panel. This also indicates that each stimulus pivot item–may appear in at most one module in the
panel.
Therefore:
which_module or which_pathway must be a scalar (not
a vector).
If both are NULL, the constraint simply enforces that the
stimulus must appear somewhere in the panel, without specifying the
module/pathway.
An object of S3 class "mstATA_constraint" with named elements:
A character vector indicating the specifications in each row of A_binary
A data.frame summarizing the constraint specification, including
the requirement name, attribute, constraint type, application level,
operator, and the number of constraint rows generated.
A sparse binary matrix representing the linear constraint coefficients.
NULL for 'mstATA_constraint' object
A character vector of constraint operators, one per row of A_binary.
A right-hand-side vector of 1s or 0s depending on whether select is TRUE or FALSE.
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
Suppose the item pool contains (S - 1) stimulus-based item sets, indexed by
. Each stimulus has a designated pivot item,
indexed by . In addition, the pool contains a set of discrete
(non-stimulus-based) items, which are represented by a dummy stimulus
to allow a unified indexing scheme. Items belonging to stimulus
are indexed as .
Suppose there are modules in an MST panel. Let
denote the module index.
1. Module-level stimulus selection/not selection
In specified module m: for all (s= 1,2...,S-1) specified in stim_ids
2. Pathway-level stimulus selection/not selection
In specified pathway r: for all (s= 1,2...,S-1) specified in stim_ids
3. Panel-level stimulus selection/not selection
In a panel: for all (s= 1,2...,S-1) specified in stim_ids
Here:
indicates whether the pivot item for stimulus
s is selected into module m, thereby indicating whether the
stimulus is selected in that module.
denote modules belonging to pathway r.
data("reading_itempool") pivot_stim_map <- create_pivot_stimulus_map( itempool = reading_itempool, stimulus = "stimulus", pivot_item = "pivot_item" ) test_mstATA <- mst_design( itempool = reading_itempool, design = "1-3-3", module_length = c(5,7,7,7,8,8,8), pivot_stim_map = pivot_stim_map ) # Example 1: Force stimulus 1 to be selected in the routing module stimcat_con( x = test_mstATA, stim_ids = 1, select = TRUE, which_module = 1 ) # Example 2: Force stimulus 1 to be included somewhere in the MST panel stimcat_con( x = test_mstATA, stim_ids = 1, select = TRUE ) # Example 3: Stimulus 1 must appear in stage-2 easy and medium modules stimcat_con( x = test_mstATA, stim_ids = 1, select = TRUE, which_module = c(2,3) ) # Example 4: Stimulus 1 must appear in the REE pathway stimcat_con( x = test_mstATA, stim_ids = 1, select = TRUE, which_pathway = 1 ) # Example 5: Stimuli 1 and 3 must appear in the routing module stimcat_con( x = test_mstATA, stim_ids = c(1,3), select = TRUE, which_module = 1 ) # Example 6: Stimuli 1 and 3 must appear in the REE pathway stimcat_con( x = test_mstATA, stim_ids = c(1,3), select = TRUE, which_pathway = 1 ) # Example 7: Stimuli 1 and 3 must appear somewhere in the panel stimcat_con( x = test_mstATA, stim_ids = c(1,3), select = TRUE )data("reading_itempool") pivot_stim_map <- create_pivot_stimulus_map( itempool = reading_itempool, stimulus = "stimulus", pivot_item = "pivot_item" ) test_mstATA <- mst_design( itempool = reading_itempool, design = "1-3-3", module_length = c(5,7,7,7,8,8,8), pivot_stim_map = pivot_stim_map ) # Example 1: Force stimulus 1 to be selected in the routing module stimcat_con( x = test_mstATA, stim_ids = 1, select = TRUE, which_module = 1 ) # Example 2: Force stimulus 1 to be included somewhere in the MST panel stimcat_con( x = test_mstATA, stim_ids = 1, select = TRUE ) # Example 3: Stimulus 1 must appear in stage-2 easy and medium modules stimcat_con( x = test_mstATA, stim_ids = 1, select = TRUE, which_module = c(2,3) ) # Example 4: Stimulus 1 must appear in the REE pathway stimcat_con( x = test_mstATA, stim_ids = 1, select = TRUE, which_pathway = 1 ) # Example 5: Stimuli 1 and 3 must appear in the routing module stimcat_con( x = test_mstATA, stim_ids = c(1,3), select = TRUE, which_module = 1 ) # Example 6: Stimuli 1 and 3 must appear in the REE pathway stimcat_con( x = test_mstATA, stim_ids = c(1,3), select = TRUE, which_pathway = 1 ) # Example 7: Stimuli 1 and 3 must appear somewhere in the panel stimcat_con( x = test_mstATA, stim_ids = c(1,3), select = TRUE )
This function generates linear constraints ensuring that each selected stimulus satisfies a specified quantitative requirement (e.g., stimulus word count, stimulus difficulty, readability index).
This constraint can be enforced at the "Module-level", "Pathway-level", or
"Panel-level". It should be mentioned that the formulation requires
stimulus-level attributes to be strictly positive.
The number of generated linear constraints depends on the application level:
Module-level: when which_module is provided and
which_pathway = NULL
The number of constraints is (number of stimuli) x (number of modules specified) x side
Pathway-level: when which_pathway is provided and
which_module = NULL
The number of constraints is (number of stimuli) x (number of unique modules in specified pathways) x side
Panel-level: both which_module and which_pathway are NULL
The number of constraints is (number of stimuli) x (total number of modules) x side
where side = 1 for one-sided constraints (min-only or max-only)
and side = 2 when both min and max are provided and
min is not equal to max.
stimquant_con( x, attribute, min = NULL, max = NULL, which_module = NULL, which_pathway = NULL )stimquant_con( x, attribute, min = NULL, max = NULL, which_module = NULL, which_pathway = NULL )
x |
An object of class |
attribute |
A string giving the column name in |
min |
A numeric scalar for the lower bound. |
max |
A numeric scalar for the upper bound. |
which_module |
Integer vector of modules. Must be consistent with the choices made in:
|
which_pathway |
Integer vector of pathways. Must be consistent with the choices made in:
|
1. Specification
The constraint enforced is:
Every selected stimulus must satisfy the required stimulus-level quantitative attribute bound(s).
The attribute type is quantitative.
The attribute is defined at the stimulus level in the item pool.
Application levels:
Module-level: enforce stimuli selected in specific module(s) satisfy the quantitative requirement.
Pathway-level: enforce stimuli selected in any module of a pathway satisfy the quantitative requirement.
Panel-level: enforce stimuli selected in the panel satisfy the quantitative requirement.
2. Important Restriction
This function assumes that all stimulus-level quantitative attributes
are strictly positive.
If stimulus attributes may be zero or negative (e.g., stimulus-level difficulty,
centered difficulty values), this constraint formulation does not correctly enforce quantitative
bounds. In such cases, users should instead apply stimulus-level selection
logic using item_module_eligibility() inside mst_design(), which
filters eligible stimuli (and linked items) before assembly.
For example, to require all routing-module stimuli to have text feature scores
between and , users should filter stimuli into the routing
module eligibility set using item_module_eligibility().
An object of S3 class "mstATA_constraint" with named elements:
A character vector indicating the specifications in each row of A_binary
A data.frame summarizing the constraint specification, including
the requirement name, attribute, constraint type, application level,
operator, and the number of constraint rows generated.
A sparse binary matrix representing the linear constraint coefficients.
NULL for 'mstATA_constraint' object
A character vector of constraint operators, one per row of A_binary.
A right-hand-side vector of 1s or 0s depending on whether select is TRUE or FALSE.
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
Suppose the item pool contains (S - 1) stimulus-based item sets, indexed by
. Each stimulus has a designated pivot item,
indexed by . In addition, the pool contains a set of discrete
(non-stimulus-based) items, which are represented by a dummy stimulus
to allow a unified indexing scheme. Items belonging to stimulus
are indexed as .
Suppose there are modules in an MST panel. Let
denote the module index.
Let be the quantitative attribute value of stimulus .
One-sided upper-bound constraint:
One-sided lower-bound constraint:
For two-sided range constraints, both inequalities are included.
(min and max both provided and not
equal), the number of constraints is doubled (side = 2).
For one-sided constraints, side = 1.
Here:
indicates whether the pivot item for stimulus
s is selected into module m, thereby indicating whether the
stimulus s is selected in that module.
(must be positive values) denote the values of the quantitative attribute for stimulus s.
and are the lower and
upper allowable bounds for the attribute .
data("reading_itempool") pivot_stim_map <- create_pivot_stimulus_map( itempool = reading_itempool, stimulus = "stimulus", pivot_item = "pivot_item" ) test_mstATA <- mst_design( itempool = reading_itempool, design = "1-3-3", module_length = c(14, 12, 12, 12, 12, 12, 12), pivot_stim_map = pivot_stim_map ) # Every selected stimulus in the routing module has 80-110 words. stimquant_con( x = test_mstATA, attribute = "stimulus_words", min = 80, max = 110, which_module =1 )data("reading_itempool") pivot_stim_map <- create_pivot_stimulus_map( itempool = reading_itempool, stimulus = "stimulus", pivot_item = "pivot_item" ) test_mstATA <- mst_design( itempool = reading_itempool, design = "1-3-3", module_length = c(14, 12, 12, 12, 12, 12, 12), pivot_stim_map = pivot_stim_map ) # Every selected stimulus in the routing module has 80-110 words. stimquant_con( x = test_mstATA, attribute = "stimulus_words", min = 80, max = 110, which_module =1 )
A precomputed MST panel assembled using the top-down strategy with the HiGHS solver demonstrated in the Three ATA Strategies Vignette.
TD12_panelTD12_panel
An object of class mstATA_panel.
Generated using mstATA::assembled_panels() and mstATA::solve_model()with the HiGHS solver.
A precomputed MST panel assembled using the top-down strategy with the HiGHS solver. Included to avoid long runtime during vignette building.
TD123_panelTD123_panel
An object of class mstATA_panel.
Generated using mstATA::assembled_panels() and mstATA::solve_model()with the HiGHS solver.
This function generates a linear constraint matrix enforcing a minimum, exact, or maximum number of items from specified categorical levels (e.g., content area, item format).
Constraints may apply at the:
"Module-level" – each module is treated as an independent test form
"Pathway-level" – each pathway is treated as an independent test form
The total number of constraints depends on the application level and the
number of category levels specified in cat_levels:
Module-level: when which_module is provided
OR both which_module and which_pathway are NULL
The number of constraints is (number of category levels)x (number of modules specified)
Pathway-level: when which_pathway is provided and
which_module = NULL
The number of constraints is (number of category levels) x (number of pathways specified)
Users may constrain a subset of modules or pathways using the
which_module or which_pathway arguments, and may restrict the
constraint to specific categories using cat_levels.
test_itemcat_con( x, attribute, cat_levels, operator, target_num, which_module = NULL, which_pathway = NULL )test_itemcat_con( x, attribute, cat_levels, operator, target_num, which_module = NULL, which_pathway = NULL )
x |
An object of class |
attribute |
A string giving the column name in |
cat_levels |
A character string or vector of categorical levels to be constrained. |
operator |
A character string specifying the inequality or equality
operator. Must be one of |
target_num |
A matrix or scalar/vector specifying the required number of items for
the category levels in |
which_module |
Optional integer vector of module indices to which the constraints apply. |
which_pathway |
Optional integer vector of pathway indices to which the constraints apply. |
1. Specification
The constraint enforces:
The test must meet a minimum, exact, or maximum number of items from the specified categories.
Key characteristics:
The attribute type is categorical.
The attribute is defined at the item level in the item pool.
The constraints are applied at either "Module-level" or "Pathway-level".
2. target_num
The constraint level is determined by which selection argument is provided:
Module-level:
Requires the minimum/exact/maximum number of items from specified category levels to be selected in specified module.
Expanded target_num matrix:
each row = one specified module, each column = one specified category.
Pathway-level:
Requires the minimum/exact/maximum number of items from specified category levels to be selected across the modules belonging to specified pathway.
Expanded target_num matrix:
each row = one specified pathway, each column = one specified category.
An object of S3 class "mstATA_constraint" with named elements:
A character vector indicating the specifications in each row of A_binary
A data.frame summarizing the constraint specification, including
the requirement name, attribute, constraint type, application level,
operator, and the number of constraint rows generated.
A sparse binary matrix representing the linear constraint coefficients.
NULL for 'mstATA_constraint' object
A character vector of constraint operators, one per row of A_binary.
A numeric vector of right-hand-side values for the constraints.
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
Suppose the item pool contains (S - 1) stimulus-based item sets, indexed by
. Each stimulus has a designated pivot item,
indexed by . In addition, the pool contains a set of discrete
(non-stimulus-based) items, which are represented by a dummy stimulus
to allow a unified indexing scheme. Items belonging to stimulus
are indexed as .
Suppose there are modules in an MST panel. Let
denote the module index.
Let denote the set of
items that belong to category c.
1. Module-level constraint (for module m)
2. Pathway-level constraint (for pathway r)
Here:
is the binary decision variable indicating whether
item is selected into module m.
denote modules belonging to pathway r.
The stacked operator, denotes that the specification may take the form of an upper bound, lower bound, or exact value.
specify the required number of items from category level c in module m.
specify the required number of items from category level c in pathway r.
data("mini_itempool") test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", module_length = c(4,2,2,2,2,2,2) ) # Example 1: category constraints across modules in the same stage con1<-test_itemcat_con(x = test_mstATA,attribute = "itemtype",cat_levels = c("MC","TEI"), operator = "=",target_num = c(3,1), which_module = 1,which_pathway = NULL) con2<-test_itemcat_con(x = test_mstATA,attribute = "itemtype",cat_levels = c("MC","TEI"), operator = "=",target_num = c(2,0), which_module = 2:4,which_pathway = NULL) con3<-test_itemcat_con(x = test_mstATA,attribute = "itemtype",cat_levels = c("MC","TEI"), operator = "=",target_num = c(2,0), which_module = 5:7,which_pathway = NULL) # Example 2: category constraints per pathway test_mstATA<-mst_design(itempool = mini_itempool,design = "1-3-3", exclude_pathways = c("1-1-3","1-3-1"),pathway_length = 8) test_itemcat_con(x = test_mstATA, attribute ="itemtype",cat_levels = c("MC","TEI"), operator = "=", target_num = c(7,1), which_pathway = 1:7) # Example 3: constraints on combinations of categorical attributes mini_itempool$content_itemtype <- paste(mini_itempool$content, mini_itempool$itemtype) test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", exclude_pathways = c("1-1-3","1-3-1"), pathway_length = 8 ) test_itemcat_con( x = test_mstATA, attribute = "content_itemtype", cat_levels = paste0("content", rep(1:4, each = 2)," ", c("MC","TEI")), operator = "=", target_num = c(1,1, 1,1, 1,0, 2,1), which_pathway = 1:7 )data("mini_itempool") test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", module_length = c(4,2,2,2,2,2,2) ) # Example 1: category constraints across modules in the same stage con1<-test_itemcat_con(x = test_mstATA,attribute = "itemtype",cat_levels = c("MC","TEI"), operator = "=",target_num = c(3,1), which_module = 1,which_pathway = NULL) con2<-test_itemcat_con(x = test_mstATA,attribute = "itemtype",cat_levels = c("MC","TEI"), operator = "=",target_num = c(2,0), which_module = 2:4,which_pathway = NULL) con3<-test_itemcat_con(x = test_mstATA,attribute = "itemtype",cat_levels = c("MC","TEI"), operator = "=",target_num = c(2,0), which_module = 5:7,which_pathway = NULL) # Example 2: category constraints per pathway test_mstATA<-mst_design(itempool = mini_itempool,design = "1-3-3", exclude_pathways = c("1-1-3","1-3-1"),pathway_length = 8) test_itemcat_con(x = test_mstATA, attribute ="itemtype",cat_levels = c("MC","TEI"), operator = "=", target_num = c(7,1), which_pathway = 1:7) # Example 3: constraints on combinations of categorical attributes mini_itempool$content_itemtype <- paste(mini_itempool$content, mini_itempool$itemtype) test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", exclude_pathways = c("1-1-3","1-3-1"), pathway_length = 8 ) test_itemcat_con( x = test_mstATA, attribute = "content_itemtype", cat_levels = paste0("content", rep(1:4, each = 2)," ", c("MC","TEI")), operator = "=", target_num = c(1,1, 1,1, 1,0, 2,1), which_pathway = 1:7 )
This function generates constraint matrices that enforce lower and upper bounds on the number of selected items belonging to specific categorical attribute levels (e.g., content area, item format) within modules or pathways.
It supports two specification formats:
Direct range constraints: min and/or max
Target plus or minus deviation constraints: target and deviation
Constraints may apply at the:
"Module-level" – each module is treated as an independent test form
"Pathway-level" – each pathway is treated as an independent test form
The total number of constraints depends on the application level and the
number of category levels in cat_levels:
Module-level: when which_module is provided,
or both which_module and which_pathway are NULL
The number of constraints = (number of category levels) x (number of modules specified) x side
Pathway-level: when which_pathway is provided and which_module = NULL
The number of constraints = (number of category levels) x (number of pathways specified) x side
Here, side = 2 for range constraints (lower + upper bound) and
side = 1 when only one bound is active.
test_itemcat_range_con( x, attribute, cat_levels, min = NULL, max = NULL, target = NULL, deviation = NULL, which_module = NULL, which_pathway = NULL )test_itemcat_range_con( x, attribute, cat_levels, min = NULL, max = NULL, target = NULL, deviation = NULL, which_module = NULL, which_pathway = NULL )
x |
An object of class |
attribute |
A string giving the column name in |
cat_levels |
Character vector of category levels to be constrained. |
min |
Optional minimum number of items (scalar, vector, or matrix). |
max |
Optional maximum number of items (scalar, vector, or matrix). |
target |
Optional target number of items (scalar, vector, or matrix). |
deviation |
Optional allowable deviation from |
which_module |
Optional integer vector of module indices to which the constraints apply. |
which_pathway |
Optional integer vector of pathway indices to which the constraints apply. |
1. Specification
The constraint enforces:
The number of selected items in each specified category must fall within an allowable range.
Key characteristics:
The attribute type is categorical.
The attribute is defined at the item level in the item pool.
The constraints are applied at either "Module-level" or "Pathway-level".
2. Range specification: min, max, target, deviation
Each of the four range-specification arguments may be:
NULL, scalar, vector, or matrix.
Interpretation:
min: minimum number of items per category per module/pathway
max: maximum number of items per category per module/pathway
target: desired number of items per category per module/pathway
deviation: allowable deviation from target
When only target and deviation are provided:
min = target - deviation.
max = target + deviation.
An object of S3 class "mstATA_constraint" with named elements:
A string indicating the specification name
A data.frame summarizing the constraint specification, including
the requirement name, attribute, constraint type, application level,
operator, and the number of constraint rows generated.
A sparse binary matrix representing the linear constraint coefficients.
NULL for 'mstATA_constraint' object
A character vector of constraint operators, one per row of A_binary.
A numeric vector of right-hand-side values for the constraints.
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
Suppose the item pool contains (S - 1) stimulus-based item sets, indexed by
. Each stimulus has a designated pivot item,
indexed by . In addition, the pool contains a set of discrete
(non-stimulus-based) items, which are represented by a dummy stimulus
to allow a unified indexing scheme. Items belonging to stimulus
are indexed as .
Suppose there are modules in an MST panel. Let
denote the module index.
Let denote the set of
items that belong to category c.
1. Module-level constraint (for module m)
2. Pathway-level constraint (for pathway r)
Here:
is the binary decision variable indicating whether
item is selected into module m.
denote modules belonging to pathway r.
and specify the minimum and maximum
required number of items from category level c in module m.
and specify the minimum and maximum
required number of items from category level c in pathway r.
data("mini_itempool") # Example 1: same category ranges across all modules # MST 1-3-3 design, 7 modules, 2 categories (MC, TEI). test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", module_length = c(4,3,3,3,4,4,4) ) test_itemcat_range_con( x = test_mstATA, attribute = "itemtype", cat_levels = c("MC","TEI"), min = matrix(c(2,1, rep(c(1,0),3), rep(c(1,0),3)), ncol = 2, byrow = TRUE), max = matrix(c(3,3, rep(c(6,1),3), rep(c(7,1),3)), ncol = 2, byrow = TRUE), target = NULL, deviation = NULL ) # Example 2: different category ranges for each module test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", module_length = c(4,3,3,3,4,4,4) ) test_itemcat_range_con( x = test_mstATA, attribute = "itemtype", cat_levels = c("MC","TEI"), min = matrix(c(2,1, 1,0, 2,0, 1,0, 2,0, 3,1, 2,0), ncol = 2, byrow = TRUE), max = matrix(c(3,3, 2,2, 3,2, 3,1, 4,2, 4,2, 4,2), ncol = 2, byrow = TRUE), which_module = 1:7 ) # Example 3: same category range per pathway (target plus or minus deviation) test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", module_length = c(4,3,3,3,4,4,4), exclude_pathways = c("1-1-3","1-3-1") ) test_itemcat_range_con( x = test_mstATA, attribute = "itemtype", cat_levels = c("MC","TEI"), target = c(9,2), deviation = 1, which_pathway = 1:7 )data("mini_itempool") # Example 1: same category ranges across all modules # MST 1-3-3 design, 7 modules, 2 categories (MC, TEI). test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", module_length = c(4,3,3,3,4,4,4) ) test_itemcat_range_con( x = test_mstATA, attribute = "itemtype", cat_levels = c("MC","TEI"), min = matrix(c(2,1, rep(c(1,0),3), rep(c(1,0),3)), ncol = 2, byrow = TRUE), max = matrix(c(3,3, rep(c(6,1),3), rep(c(7,1),3)), ncol = 2, byrow = TRUE), target = NULL, deviation = NULL ) # Example 2: different category ranges for each module test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", module_length = c(4,3,3,3,4,4,4) ) test_itemcat_range_con( x = test_mstATA, attribute = "itemtype", cat_levels = c("MC","TEI"), min = matrix(c(2,1, 1,0, 2,0, 1,0, 2,0, 3,1, 2,0), ncol = 2, byrow = TRUE), max = matrix(c(3,3, 2,2, 3,2, 3,1, 4,2, 4,2, 4,2), ncol = 2, byrow = TRUE), which_module = 1:7 ) # Example 3: same category range per pathway (target plus or minus deviation) test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", module_length = c(4,3,3,3,4,4,4), exclude_pathways = c("1-1-3","1-3-1") ) test_itemcat_range_con( x = test_mstATA, attribute = "itemtype", cat_levels = c("MC","TEI"), target = c(9,2), deviation = 1, which_pathway = 1:7 )
This function generates linear constraints controlling the number of selected items in each module or pathway of a MST panel.
Depending on the MST design provided in mst_design(), the constraints
enforce either:
Module-level item counts - each module is treated as an independent test form
Pathway-level item counts - each pathway is treated as an independent test form
The total number of constraints depends on the MST design and whether stage-level bounds are used:
Module-level constraints: The number of constraints is (number of modules)
Pathway-level constraints: The number of constraints is (number of pathways) + (number of modules with a min bound) + (number of modules with a max bound) + (number of equality constraints enforcing equal module lengths within each stage)
test_itemcount_con(x, stage_length_bound = NULL)test_itemcount_con(x, stage_length_bound = NULL)
x |
An object of class |
stage_length_bound |
Optional |
1. Specification
The constraint enforces:
the test must include the exact number of items..
Key characteristics:
The attribute type is categorical: each item has a unique ID.
The attribute is defined at item level in the item pool.
The constraint can be enforced at either "Module-level" or "Pathway-level".
It depends on whether module_length or
pathway_length was specified in mst_design().
2. Module-level constraints
These are generated when module_length was provided in mst_design().
The required number of items per module is given by
x$ModuleIndex$ModuleLength.
One constraint is created per module.
Each module must contain exactly the specified number of items.
3. Pathway-level constraints
These are generated when pathway_length was provided in mst_design().
The required number of items per pathway is given by
x$PathwayIndex$PathwayLength.
Optional stage-level constraints may enforce:
Minimum items per stage
Maximum items per stage
If stage_length_bound = NULL
Each stage must contain at least one item
All modules within a stage must have equal length
An object of S3 class "mstATA_constraint" with named elements:
A character vector indicating the specifications in each row of A_binary
A data.frame summarizing the constraint specification, including
the requirement name, attribute, constraint type, application level,
operator, and the number of constraint rows generated.
A sparse binary matrix representing the linear constraint coefficients.
NULL for 'mstATA_constraint' object
A character vector of constraint operators, one per row of A_binary.
A numeric vector of right-hand-side values for the constraints.
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
Suppose the item pool contains (S - 1) stimulus-based item sets, indexed by
. Each stimulus has a designated pivot item,
indexed by . In addition, the pool contains a set of discrete
(non-stimulus-based) items, which are represented by a dummy stimulus
to allow a unified indexing scheme. Items belonging to stimulus
are indexed as .
Suppose there are modules in an MST panel. Let
denote the module index.
1. Module-level constraint
2. Pathway-level constraint
Stage-level minimum:
for all modules m in stage t.
Stage-level maximum:
for all modules m in stage t.
Equal-length constraint for modules (m, m') in the same stage:
Here:
is the binary decision variable indicating whether
item is selected into module m.
denote modules belonging to pathway r.
specify the required number of items in module m.
specify the required number of items in pathway r.
specify the minimum number of items in stage t.
specify the maximum number of items in stage t.
, and are a pair of modules in stage t.
data("mini_itempool") # Example 1: module-level test length # Routing module: 3 items; Stage 2 modules: 4 items each test_mstATA <- mst_design( itempool = mini_itempool,module_length = c(3,4,4,4), design = "1-3" ) test_itemcount_con(test_mstATA) # Example 2: pathway-level test length: each pathway contains 7 items, test_mstATA <- mst_design( itempool = mini_itempool,pathway_length = 7, design = "1-3" ) # It will also constrain that each module has at least 1 item and modules # in the stage 2 have the same module length. test_itemcount_con(test_mstATA) # Example 3: pathway-level with stage-level max bound for Stage 1 test_itemcount_con( test_mstATA, stage_length_bound = data.frame(stage = 1, min = 1, max = 2) )data("mini_itempool") # Example 1: module-level test length # Routing module: 3 items; Stage 2 modules: 4 items each test_mstATA <- mst_design( itempool = mini_itempool,module_length = c(3,4,4,4), design = "1-3" ) test_itemcount_con(test_mstATA) # Example 2: pathway-level test length: each pathway contains 7 items, test_mstATA <- mst_design( itempool = mini_itempool,pathway_length = 7, design = "1-3" ) # It will also constrain that each module has at least 1 item and modules # in the stage 2 have the same module length. test_itemcount_con(test_mstATA) # Example 3: pathway-level with stage-level max bound for Stage 1 test_itemcount_con( test_mstATA, stage_length_bound = data.frame(stage = 1, min = 1, max = 2) )
This function generates linear constraints on the sum of item-level quantitative attributes (e.g., total time, word count, item difficulty) within specified module or pathway of a multistage test (MST).
Users may specify:
minimum total item-level attribute values,
maximum total item-level attribute values, or
exact (equal-to) total item-level attribute values.
Constraints may apply at the:
"Module-level" – each module is treated as a separate test form, or
"Pathway-level" – each pathway is treated as a complete test form.
The total number of constraints depends on the application level:
Module-level: when which_module is provided
OR both which_module and which_pathway are NULL
The number of constraints is (number of modules specified)
Pathway-level: when which_pathway is provided and
which_module = NULL
The number of constraints is (number of pathways specified)
test_itemquant_con( x, attribute, operator, target_value, which_module = NULL, which_pathway = NULL )test_itemquant_con( x, attribute, operator, target_value, which_module = NULL, which_pathway = NULL )
x |
An object of class |
attribute |
A string giving the column name in |
operator |
A character string specifying the constraint type.
Must be one of |
target_value |
A numeric scalar or vector giving the target sum of item quantitative attributes for each module/pathway being constrained. |
which_module |
Optional integer vector of module indices to which the constraints apply. |
which_pathway |
Optional integer vector of pathway indices to which the constraints apply. |
1. Specification
The constraint enforced is:
The total sum of the item quantitative attribute must meet a minimum, exact, or maximum bound for specific module or pathway.
Key characteristics:
The attribute type is quantitative.
The attribute is defined at the item level in the item pool.
The constraints are applied at either "Module-level" or "Pathway-level".
An object of S3 class "mstATA_constraint" with named elements:
A character vector indicating the specifications in each row of A_binary
A data.frame summarizing the constraint specification, including
the requirement name, attribute, constraint type, application level,
operator, and the number of constraint rows generated.
A sparse binary matrix representing the linear constraint coefficients.
NULL for 'mstATA_constraint' object
A character vector of constraint operators, one per row of A_binary.
A numeric vector of right-hand-side values for the constraints.
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
Suppose the item pool contains (S - 1) stimulus-based item sets, indexed by
. Each stimulus has a designated pivot item,
indexed by . In addition, the pool contains a set of discrete
(non-stimulus-based) items, which are represented by a dummy stimulus
to allow a unified indexing scheme. Items belonging to stimulus
are indexed as .
Suppose there are modules in an MST panel. Let
denote the module index.
Let be the quantitative attribute value of item .
1. Module-level constraint (for module m)
2. Pathway-level constraint (for pathway r)
Here:
is the binary decision variable indicating whether
item is selected into module m.
denote modules belonging to pathway r.
The stacked operator, denotes that the specification may take the form of an upper bound, lower bound, or exact value.
is the required bound for the sum of item-level quantitative attribute values in module m (minimum, maximum, or exact value).
is the required bound for the sum of item-level quantitative attribute values in pathway r (minimum, maximum, or exact value).
data("mini_itempool") # Example 1: Upper bound on total difficulty per module test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", module_length = c(4,2,2,2,2,2,2) ) # Mean difficulty upper bound per module: # difficulty_mean * module_length = difficulty_sum_target test_itemquant_con( x = test_mstATA, attribute = "difficulty", operator = "<=", target_value = c(0, -0.5, 0, 0.5, -1, 0, 1) * c(4,2,2,2,2,2,2), which_module = NULL ) # Example 2: Difficulty boundaries for different pathways # Assume three subpopulations: low, medium, high ability. # Pathways targeting low ability: mean difficulty <= -0.44 # Pathways targeting high ability: mean difficulty >= 0.44 test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", exclude_pathways = c("1-1-3","1-3-1"), pathway_length = 8 ) # Low-difficulty pathways test_itemquant_con( x = test_mstATA, attribute = "difficulty", operator = "<=", target_value = -0.44 * 8, which_pathway = c(1,2) ) # High-difficulty pathways test_itemquant_con( x = test_mstATA, attribute = "difficulty", operator = ">=", target_value = 0.44 * 8, which_pathway = c(6,7) )data("mini_itempool") # Example 1: Upper bound on total difficulty per module test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", module_length = c(4,2,2,2,2,2,2) ) # Mean difficulty upper bound per module: # difficulty_mean * module_length = difficulty_sum_target test_itemquant_con( x = test_mstATA, attribute = "difficulty", operator = "<=", target_value = c(0, -0.5, 0, 0.5, -1, 0, 1) * c(4,2,2,2,2,2,2), which_module = NULL ) # Example 2: Difficulty boundaries for different pathways # Assume three subpopulations: low, medium, high ability. # Pathways targeting low ability: mean difficulty <= -0.44 # Pathways targeting high ability: mean difficulty >= 0.44 test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", exclude_pathways = c("1-1-3","1-3-1"), pathway_length = 8 ) # Low-difficulty pathways test_itemquant_con( x = test_mstATA, attribute = "difficulty", operator = "<=", target_value = -0.44 * 8, which_pathway = c(1,2) ) # High-difficulty pathways test_itemquant_con( x = test_mstATA, attribute = "difficulty", operator = ">=", target_value = 0.44 * 8, which_pathway = c(6,7) )
This function generates linear constraints on the sum of item-level quantitative attributes (e.g., total time, word count, difficulty) within specified module or pathway of a multistage test (MST).
It supports two specification formats:
Direct range constraints: using min and/or max
Target plus or minus deviation constraints: using target and deviation
Constraints may apply at the:
"Module-level" – each module is treated as a separate test form, or
"Pathway-level" – each pathway is treated as a complete test form.
The total number of constraints depends on the application level:
Module-level: when which_module is provided,
or both which_module and which_pathway are NULL
Number of constraints = (number of modules) x side
Pathway-level: when which_pathway is provided and which_module = NULL
Number of constraints = (number of pathways) x side
Here, side = 2 for range constraints (lower + upper bound) and
side = 1 when only one bound is active.
test_itemquant_range_con( x, attribute, min = NULL, max = NULL, target = NULL, deviation = NULL, which_module = NULL, which_pathway = NULL )test_itemquant_range_con( x, attribute, min = NULL, max = NULL, target = NULL, deviation = NULL, which_module = NULL, which_pathway = NULL )
x |
An object of class |
attribute |
A string giving the column name in |
min |
Optional numeric scalar or vector of lower bounds. |
max |
Optional numeric scalar or vector of upper bounds. |
target |
Optional numeric scalar or vector of target values. |
deviation |
Optional numeric scalar or vector of allowed deviations from the target. |
which_module |
Optional integer vector of module indices to which the constraints apply. |
which_pathway |
Optional integer vector of pathway indices to which the constraints apply. |
1. Constraint Specification
This function enforces:
The total sum of item quantitative attributes must lie within specified ranges for specified module or pathway.
The key properties of this constraint are:
The attribute type is quantitative.
The attribute is defined at the item level in the item pool.
Constraints may be applied at the module or pathway level.
2. Range specification: min, max, target, deviation
Each of the four range-specification arguments may be:
NULL, scalar or vector
Interpretation:
min: minimum sum of item quantitative values
max: maximum sum of item quantitative values
target: desired sum of item quantitative values
deviation: allowable deviation
When only target and deviation are provided:
min = target - deviation.
max = target + deviation.
A combined constraint object of class "mstATA_constraint", consisting of one or more quantitative constraints.
A string indicating the specification name.
A data.frame summarizing the constraint specification, including
the requirement name, attribute, constraint type, application level,
operator, and the number of constraint rows generated.
A sparse binary matrix representing the linear constraint coefficients.
NULL for 'mstATA_constraint' object
A character vector of constraint operators, one per row of A_binary.
A numeric vector of right-hand-side values for the constraints.
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
Suppose the item pool contains (S - 1) stimulus-based item sets, indexed by
. Each stimulus has a designated pivot item,
indexed by . In addition, the pool contains a set of discrete
(non-stimulus-based) items, which are represented by a dummy stimulus
to allow a unified indexing scheme. Items belonging to stimulus
are indexed as .
Suppose there are modules in an MST panel. Let
denote the module index.
Let be the quantitative attribute value of item .
1. Module-level constraint (for module m)
2. Pathway-level constraint (for pathway r)
Here:
is the binary decision variable indicating whether
item is selected into module m.
denote modules belonging to pathway r.
and specify the lower and upper bounds for
the sum of item quantitative attribute in module m
and specify the lower and upper bounds for
the sum of item quantitative attribute in pathway r
data("mini_itempool") ## Example 1: Difficulty range per module test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", module_length = c(4,3,3,3,4,4,4) ) test_itemquant_range_con( x = test_mstATA, attribute = "difficulty", min = c(-0.2*4, -0.7*2, -0.2*2, 0.3*2, -1.2*2, -0.2*2, 0.8*2), max = c( 0.2*4, -0.3*2, 0.2*2, 0.7*2, -0.8*2, 0.2*2, 1.2*2), which_module = NULL ) ## Example 2: Difficulty range per pathway test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", exclude_pathways = c("1-1-3", "1-3-1"), pathway_length = 8 ) test_itemquant_range_con( x = test_mstATA, attribute = "difficulty", target = c(-1.2,-0.7,-0.2,0,0.2,0.7,1.2) * 8, deviation = 0.1 * 8, which_pathway = 1:7 )data("mini_itempool") ## Example 1: Difficulty range per module test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", module_length = c(4,3,3,3,4,4,4) ) test_itemquant_range_con( x = test_mstATA, attribute = "difficulty", min = c(-0.2*4, -0.7*2, -0.2*2, 0.3*2, -1.2*2, -0.2*2, 0.8*2), max = c( 0.2*4, -0.3*2, 0.2*2, 0.7*2, -0.8*2, 0.2*2, 1.2*2), which_module = NULL ) ## Example 2: Difficulty range per pathway test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", exclude_pathways = c("1-1-3", "1-3-1"), pathway_length = 8 ) test_itemquant_range_con( x = test_mstATA, attribute = "difficulty", target = c(-1.2,-0.7,-0.2,0,0.2,0.7,1.2) * 8, deviation = 0.1 * 8, which_pathway = 1:7 )
Enforces similarity of test information at routing decision points (RDPs)
between adjacent modules in the next stage of a multistage test (MST).
Routing is assumed to occur after examinees complete which_stage,
and constraints are imposed on modules at stage which_stage + 1.
test_rdp_con(x, rdp, which_stage, info_tol = 0.5)test_rdp_con(x, rdp, which_stage, info_tol = 0.5)
x |
An object of class |
rdp |
A numeric vector of routing decision points (theta values).
The length of |
which_stage |
A single integer indicating the stage after which
routing occurs. Routing constraints are applied to modules at
stage |
info_tol |
A single positive numeric value specifying the maximum allowable difference in information between adjacent modules at each routing decision point. |
For each routing decision point , this function constrains
the difference in test information functions (TIFs) between adjacent
next-stage modules to be within a specified tolerance:
where is the information tolerance.
Adjacency is defined by ordering of modules within the same stage. This ensures correct behavior even when some pathways are excluded from the design.
The constraint enforces:
The test information at the routing decision point between adjacent modules in the next stage is similar within a specified tolerance.
Key characteristics:
The attribute type is quantitative.
The attribute is defined at the item level in the item pool.
The constraints are applied at the "Module-level".
This function requires that item-level information functions
iif(theta = theta_point) already exist in the item pool.
These attributes can be prepared in advance using
compute_iif.
The constraint is implemented as a pair of linear inequalities for each routing decision point, resulting in two constraint rows per routing decision point.
An object of S3 class "mstATA_constraint" with named elements:
A character vector indicating the specifications in each row of A_binary
A data.frame summarizing the constraint specification, including
the requirement name, attribute, constraint type, application level,
operator, and the number of constraint rows generated.
A sparse binary matrix representing the linear constraint coefficients.
NULL for 'mstATA_constraint' object
A character vector of constraint operators, one per row of A_binary.
A numeric vector of right-hand-side values for the constraints.
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
Suppose the item pool contains (S - 1) stimulus-based item sets, indexed by
. Each stimulus has a designated pivot item,
indexed by . In addition, the pool contains a set of discrete
(non-stimulus-based) items, which are represented by a dummy stimulus
to allow a unified indexing scheme. Items belonging to stimulus
are indexed as .
Suppose there are modules in an MST panel. Let
denote the module index. Let
be a binary decision variable indicating whether item
from stimulus is selected into module .
Let denote a routing decision point (RDP) at which examinees
are routed to different modules in the next stage of the test. The item
information function of item at ability level is
denoted by , and the corresponding module-level test
information function is given by
Consider routing after stage . Let denote the
ordered set of modules at stage . For each pair of adjacent modules
in , a routing decision point
is specified. The routing information balance constraint
requires that the difference in test information between adjacent modules at
the routing decision point be bounded by a user-specified tolerance
:
Each absolute-value constraint is implemented as a pair of linear inequalities, resulting in two constraint rows per routing decision point.
data("mini_itempool") mini_itempool[,paste0("iif(theta=",c(-0.5,0.5),")")]<-compute_iif(mini_itempool, item_par_cols = list("3PL"=c("discrimination","difficulty","guessing")), theta = c(-0.5,0.5),model_col = "model") test_mstATA <- mst_design( itempool = mini_itempool,module_length = c(3,4,4,4), design = "1-3" ) test_rdp_con(x = test_mstATA,rdp = c(-0.5, 0.5), which_stage = 1,info_tol = 0.4)data("mini_itempool") mini_itempool[,paste0("iif(theta=",c(-0.5,0.5),")")]<-compute_iif(mini_itempool, item_par_cols = list("3PL"=c("discrimination","difficulty","guessing")), theta = c(-0.5,0.5),model_col = "model") test_mstATA <- mst_design( itempool = mini_itempool,module_length = c(3,4,4,4), design = "1-3" ) test_rdp_con(x = test_mstATA,rdp = c(-0.5, 0.5), which_stage = 1,info_tol = 0.4)
This function generates linear constraints on the number of stimuli belonging to specified categorical levels (e.g., passage type, theme, genre) in a multistage test (MST).
Constraints may be applied at:
"Module-level" – each module is treated as an independent form.
"Pathway-level" – each pathway is treated as an independent form.
The application level is determined by which of
which_module or which_pathway is supplied.
The total number of constraints depends on the application level and on the
number of categorical levels included in cat_levels:
Module-level: when which_module is provided
OR both which_module and which_pathway are NULL
The number of constraints is (number of category levels) x (number of modules specified)
Pathway-level: when which_pathway is provided and
which_module = NULL
The number of constraints is (number of category levels) x (number of pathways specified)
Users may constrain only a subset of modules or pathways using
which_module or which_pathway, and may restrict the constraints
to a subset of stimulus categories using cat_levels.
test_stimcat_con( x, attribute, cat_levels, operator, target_num, which_module = NULL, which_pathway = NULL )test_stimcat_con( x, attribute, cat_levels, operator, target_num, which_module = NULL, which_pathway = NULL )
x |
An object of class |
attribute |
A string giving the column name in |
cat_levels |
Character string or vector of category levels to constrain. |
operator |
A character string indicating the type of constraint.
Must be one of |
target_num |
Target number of stimuli per category per module/pathway. Can be a scalar, vector, or matrix (see Details). |
which_module |
Optional integer vector of module indices to which the constraints apply. |
which_pathway |
Optional integer vector of pathway indices to which the constraints apply. |
1. Specification
The constraint enforces:
The test must meet a minimum, exact, or maximum number of stimuli belonging to each specified categorical level.
Key characteristics:
The attribute type is categorical.
The attribute is defined at the stimulus level in the item pool.
The constraints are applied at either "Module-level" or "Pathway-level".
2. Pivot-Item Method
MST assembly uses the pivot-item formulation (van der Linden, 2005):
Each stimulus has one designated pivot item .
A stimulus is considered selected if and only if its pivot item is selected.
An object of S3 class "mstATA_constraint" with named elements:
A character vector indicating the specifications in each row of A_binary
A data.frame summarizing the constraint specification, including
the requirement name, attribute, constraint type, application level,
operator, and the number of constraint rows generated.
A sparse binary matrix representing the linear constraint coefficients.
NULL for 'mstATA_constraint' object
A character vector of constraint operators, one per row of A_binary.
A numeric vector of right-hand-side values for the constraints.
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
Suppose the item pool contains (S - 1) stimulus-based item sets, indexed by
. Each stimulus has a designated pivot item,
indexed by . In addition, the pool contains a set of discrete
(non-stimulus-based) items, which are represented by a dummy stimulus
to allow a unified indexing scheme. Items belonging to stimulus
are indexed as .
Suppose there are modules in an MST panel. Let
denote the module index.
Let denote the set of
stimuli that belong to category c.
1. Module-level constraint (for module m)
2. Pathway-level constraint (for pathway r)
Here:
indicates whether the pivot item for stimulus
s is selected into module m, thereby indicating whether the
stimulus is selected in that module.
denote modules belonging to pathway r.
The stacked operator, denotes that the specification may take the form of an upper bound, lower bound, or exact value.
specify the required number of stimuli from category level c in module m.
specify the required number of stimuli from category level c in pathway r.
data("reading_itempool") pivot_stim_map <- create_pivot_stimulus_map( itempool = reading_itempool, stimulus = "stimulus", pivot_item = "pivot_item" ) # Example 1: # MST 1-3-3 design, 7 modules, 2 stimulus categories (history, social studies). # Stage 1: less than 1 history passage. # Stage 2 & 3: less than 1 history and less than 1 social studies passage in each module. test_mstATA <- mst_design( itempool = reading_itempool, design = "1-3-3", module_length = c(14,12,12,12,12,12,12), pivot_stim_map = pivot_stim_map ) test_stimcat_con( x = test_mstATA, attribute = "stimulus_type", cat_levels = c("history","social studies"), operator = "<=", target_num = matrix( c(1,0, rep(c(1,1), 3), rep(c(1,1), 3)), nrow = 7, ncol = 2, byrow = TRUE ) ) # Example 2: # Pathway REE requires between 1 and 3 history passages. con1<-test_stimcat_con( x = test_mstATA, attribute = "stimulus_type", cat_levels = "history", operator = ">=", target_num = 1, which_pathway = 1 ) con2<-test_stimcat_con( x = test_mstATA, attribute = "stimulus_type", cat_levels = "history", operator = "<=", target_num = 3, which_pathway = 1 )data("reading_itempool") pivot_stim_map <- create_pivot_stimulus_map( itempool = reading_itempool, stimulus = "stimulus", pivot_item = "pivot_item" ) # Example 1: # MST 1-3-3 design, 7 modules, 2 stimulus categories (history, social studies). # Stage 1: less than 1 history passage. # Stage 2 & 3: less than 1 history and less than 1 social studies passage in each module. test_mstATA <- mst_design( itempool = reading_itempool, design = "1-3-3", module_length = c(14,12,12,12,12,12,12), pivot_stim_map = pivot_stim_map ) test_stimcat_con( x = test_mstATA, attribute = "stimulus_type", cat_levels = c("history","social studies"), operator = "<=", target_num = matrix( c(1,0, rep(c(1,1), 3), rep(c(1,1), 3)), nrow = 7, ncol = 2, byrow = TRUE ) ) # Example 2: # Pathway REE requires between 1 and 3 history passages. con1<-test_stimcat_con( x = test_mstATA, attribute = "stimulus_type", cat_levels = "history", operator = ">=", target_num = 1, which_pathway = 1 ) con2<-test_stimcat_con( x = test_mstATA, attribute = "stimulus_type", cat_levels = "history", operator = "<=", target_num = 3, which_pathway = 1 )
This function generates linear constraints on the number of stimuli selected in a multistage test (MST).
Constraints may be applied at:
"Module-level" – each module is treated as an independent form.
"Pathway-level" – each pathway is treated as an independent form.
The application level is determined by which of
which_module or which_pathway is supplied.
The total number of constraints is:
Module-level: when which_module is provided, or when both
which_module and which_pathway are NULL
The number of constraints is (number of modules specified)
Pathway-level: when which_pathway is provided and which_module = NULL
The number of constraints is (number of pathways specified)
test_stimcount_con( x, operator, target_num, which_module = NULL, which_pathway = NULL )test_stimcount_con( x, operator, target_num, which_module = NULL, which_pathway = NULL )
x |
An object of class |
operator |
A character string indicating the type of constraint.
Must be one of |
target_num |
The number of stimuli in specific module/pathway ( |
which_module |
Optional integer vector of module indices to which the constraints apply. |
which_pathway |
Optional integer vector of pathway indices to which the constraints apply. |
1. Specification
The constraint enforces:
The test must meet a minimum, exact, or maximum number of stimuli.
Key characteristics:
The attribute type is categorical (each stimulus has a unique ID).
The attribute is defined at the stimulus level in the item pool.
The constraints are applied at either "Module-level" or "Pathway-level".
2. Pivot-Item Method
MST assembly uses the pivot-item formulation (van der Linden, 2005):
Each stimulus has one designated pivot item .
A stimulus is considered selected if and only if its pivot item is selected.
An object of S3 class "mstATA_constraint" with named elements:
A character vector indicating the specifications in each row of A_binary
A data.frame summarizing the constraint specification, including
the requirement name, attribute, constraint type, application level,
operator, and the number of constraint rows generated.
A sparse binary matrix representing the linear constraint coefficients.
NULL for 'mstATA_constraint' object
A character vector of constraint operators, one per row of A_binary.
A numeric vector of right-hand-side values for the constraints.
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
Suppose the item pool contains (S - 1) stimulus-based item sets, indexed by
. Each stimulus has a designated pivot item,
indexed by . In addition, the pool contains a set of discrete
(non-stimulus-based) items, which are represented by a dummy stimulus
to allow a unified indexing scheme. Items belonging to stimulus
are indexed as .
Suppose there are modules in an MST panel. Let
denote the module index.
1. Module-level constraint (for module m)
2. Pathway-level constraint (for pathway r)
Here:
indicates whether the pivot item for stimulus
s is selected into module m, thereby indicating whether the
stimulus is selected in that module.
denote modules belonging to pathway r.
The stacked operator, denotes that the specification may take the form of an upper bound, lower bound, or exact value.
specify the required number of stimuli in module m.
specify the required number of stimuli in pathway r.
van der Linden, W. J. (2005). Linear Models for Optimal Test Design. Springer. doi:10.1007/0-387-29054-0.
data("reading_itempool") pivot_stim_map <- create_pivot_stimulus_map( itempool = reading_itempool, stimulus = "stimulus", pivot_item = "pivot_item" ) test_mstATA <- mst_design( itempool = reading_itempool, design = "1-3-3", module_length = c(14,12,12,12,12,12,12), pivot_stim_map = pivot_stim_map ) # Example 1: # In MST 1-3-3, the routing module must contain between 1 and 2 stimuli. con1<-test_stimcount_con( x = test_mstATA, operator = ">=", target_num = 1, which_module = 1 ) con2<-test_stimcount_con( x = test_mstATA, operator = "<=", target_num = 2, which_module = 1 ) # Example 2: # The REE pathway must contain exactly 2 stimuli. test_stimcount_con( x = test_mstATA, operator = "=", target_num = 2, which_pathway = 1 )data("reading_itempool") pivot_stim_map <- create_pivot_stimulus_map( itempool = reading_itempool, stimulus = "stimulus", pivot_item = "pivot_item" ) test_mstATA <- mst_design( itempool = reading_itempool, design = "1-3-3", module_length = c(14,12,12,12,12,12,12), pivot_stim_map = pivot_stim_map ) # Example 1: # In MST 1-3-3, the routing module must contain between 1 and 2 stimuli. con1<-test_stimcount_con( x = test_mstATA, operator = ">=", target_num = 1, which_module = 1 ) con2<-test_stimcount_con( x = test_mstATA, operator = "<=", target_num = 2, which_module = 1 ) # Example 2: # The REE pathway must contain exactly 2 stimuli. test_stimcount_con( x = test_mstATA, operator = "=", target_num = 2, which_pathway = 1 )
This function generates linear constraints on the sum of stimulus-level quantitative attribute (e.g., total word count, total reading time, total linguistic complexity) in a multistage test (MST).
Users may specify:
minimum total stimulus-level quantitative attribute values,
maximum total stimulus-level quantitative attribute values, or
exact (equal-to) total stimulus-level attribute values.
Constraints may be applied at:
"Module-level" – each module is treated as an independent form.
"Pathway-level" – each pathway is treated as an independent form.
The total number of constraints depends on the application level:
Module-level:when which_module is provided
OR both which_module and which_pathway are NULL
The number of constraints is (number of modules specified)
Pathway-level:when which_pathway is provided and
which_module = NULL
The number of constraints is (number of pathways specified)
test_stimquant_con( x, attribute, operator, target_value, which_module = NULL, which_pathway = NULL )test_stimquant_con( x, attribute, operator, target_value, which_module = NULL, which_pathway = NULL )
x |
An object of class |
attribute |
A string giving the column name in |
operator |
A character string indicating the type of constraint.
Must be one of |
target_value |
A numeric scalar or vector specifying the required total quantitative attribute value. |
which_module |
Optional integer vector of module indices to which the constraints apply. |
which_pathway |
Optional integer vector of pathway indices to which the constraints apply. |
1. Specification
The constraint enforces:
The total value of quantitative attribute across selected stimuli must meet a minimum, exact, or maximum requirement.
Example:In a stimulus-based assessment, total words in each module must not exceed 300.
Key characteristics:
The attribute type is quantitative.
The attribute is defined at the stimulus level in the item pool.
The constraints are applied at either "Module-level" or "Pathway-level".
2. Pivot-Item Method
MST assembly uses the pivot-item formulation (van der Linden, 2005):
Each stimulus has one designated pivot item .
A stimulus is considered selected if and only if its pivot item is selected.
An object of S3 class "mstATA_constraint" with named elements:
A character vector indicating the specifications in each row of A_binary
A data.frame summarizing the constraint specification, including
the requirement name, attribute, constraint type, application level,
operator, and the number of constraint rows generated.
A sparse binary matrix representing the linear constraint coefficients.
NULL for 'mstATA_constraint' object
A character vector of constraint operators, one per row of A_binary.
A numeric vector of right-hand-side values for the constraints.
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
NULL for 'mstATA_constraint' object
Suppose the item pool contains (S - 1) stimulus-based item sets, indexed by
. Each stimulus has a designated pivot item,
indexed by . In addition, the pool contains a set of discrete
(non-stimulus-based) items, which are represented by a dummy stimulus
to allow a unified indexing scheme. Items belonging to stimulus
are indexed as .
Suppose there are modules in an MST panel. Let
denote the module index.
Let be the quantitative attribute value of stimulus s.
1. Module-level constraint (for module m)
2. Pathway-level constraint (for pathway r)
Here:
indicates whether the pivot item for stimulus
s is selected into module m, thereby indicating whether the
stimulus is selected in that module.
denote modules belonging to pathway r.
The stacked operator, denotes that the specification may take the form of an upper bound, lower bound, or exact value.
is the required bound for the sum of stimulus-level quantitative attribute values in module m.
is the required bound for the sum of stimulus-level quantitative attribute values in pathway r.
data("reading_itempool") pivot_stim_map <- create_pivot_stimulus_map(reading_itempool, item_id_col="item_id", stimulus = "stimulus", pivot_item = "pivot_item") test_mstATA <- mst_design( itempool = reading_itempool, design = "1-3-3", module_length = c(14,12,12,12,12,12,12), pivot_stim_map = pivot_stim_map ) # Example 1: # The total words in each module must be less than 300. test_stimquant_con( x = test_mstATA, attribute = "stimulus_words", operator = "<=", target_value = 300, which_module = NULL ) # Example 2: # In the REE pathway, total stimulus words must be between 50 and 200. con1<-test_stimquant_con( x = test_mstATA, attribute = "stimulus_words", operator = ">=", target_value = 50, which_pathway = 1 ) con2<-test_stimquant_con( x = test_mstATA, attribute = "stimulus_words", operator = "<=", target_value = 200, which_pathway = 1 )data("reading_itempool") pivot_stim_map <- create_pivot_stimulus_map(reading_itempool, item_id_col="item_id", stimulus = "stimulus", pivot_item = "pivot_item") test_mstATA <- mst_design( itempool = reading_itempool, design = "1-3-3", module_length = c(14,12,12,12,12,12,12), pivot_stim_map = pivot_stim_map ) # Example 1: # The total words in each module must be less than 300. test_stimquant_con( x = test_mstATA, attribute = "stimulus_words", operator = "<=", target_value = 300, which_module = NULL ) # Example 2: # In the REE pathway, total stimulus words must be between 50 and 200. con1<-test_stimquant_con( x = test_mstATA, attribute = "stimulus_words", operator = ">=", target_value = 50, which_pathway = 1 ) con2<-test_stimquant_con( x = test_mstATA, attribute = "stimulus_words", operator = "<=", target_value = 200, which_pathway = 1 )
A precomputed multistage testing (MST) panel assembled using the minimax objective formulation (one_dev) described in the Formulation for Multiple Objectives vignette.
unary_minimax_panelunary_minimax_panel
An object of class mstATA_panel.
This object is included to avoid long solver runtimes during vignette building and package checking.
Generated using mstATA::assembled_panels() and mstATA::solve_model()with the HiGHS solver.
This function compiles a weighted-sum objective when multiple objective terms are present. Each objective term contributes a linear score, and the solver optimizes a weighted linear combination of these scores.
Under this strategy, multiple linear objective terms are aggregated into a single objective function by forming a weighted linear combination.
weighted_sum_obj(x, multiple_terms, strategy_args = list())weighted_sum_obj(x, multiple_terms, strategy_args = list())
x |
An object of class "mstATA_design" created by mst_design(). |
multiple_terms |
A list containing two or more objective components. Each element must be either:
Each element may represent either a relative or an absolute objective. The weighted aggregation respects the optimization sense (maximize or minimize) specified within each objective term or compiled objective. |
strategy_args |
A named list of strategy-specific arguments used by the weighted_sum aggregation. Supported fields:
|
1. Overview
There are at least two objective term.
Each objective term represents a linear score of the form
, constructed by objective_term().
Key characteristics for each objective term:
(1) Categorical or Quantitative
maximize or minimize the number of items belonging to a specific categorical level, or
maximize or minimize the sum of quantitative item-level attribute values, such as difficulty, discrimination, or item information function values.
(2) Module-, Pathway- or Panel-level
"Module-level" – only items in a specified module contribute to the objective;
"Pathway-level" – items in all modules belonging to one pathway contribute; and
"Panel-level" – all item selections in the panel contribute.
(3) Relative or Absolute Objective
Relative objective: maximize/minimize .
Absolute deviation objective: minimize the deviation from
a specified target: where is the target value.
To combine these objectives, the function introduces an auxiliary continuous
variable for each term and optimizes a weighted sum:
or
where are user-specified or default weights.
2. Handling Mixed Optimization Directions
Objective terms may have different optimization directions:
some terms are to be minimized, and
others are to be maximized.
To maintain a single optimization sense, the compiled objective always uses a minimization form internally when mixed directions are present.
For any term that is originally a maximization objective, its score is multiplied by -1. For example, if:
and are to be minimized, and
is to be maximized,
then the combined objective becomes:
This transformation preserves the intended optimization direction for each objective term while yielding a single linear objective function.
3.Practical Considerations for Choosing Weights
As discussed in van der Linden (2005, pp. 68-69), selecting weights in a multiobjective test-assembly problem can be challenging, particularly when the objective terms are measured on different scales (e.g., test information, content counts, exposure-related quantities).
Two key issues arise:
When objectives are on different scales, weights are difficult to interpret and compare meaningfully.
When several weights are chosen to be close in magnitude, the optimal solution may become unstable or unpredictable due to strong trade-offs between competing attributes.
A partial remedy suggested by van der Linden is to first solve the assembly problem separately for each objective term. These single-objective runs yield benchmark values corresponding to solutions in which the entire weight is placed on one objective and zero weight on all others.
The final weights in a weighted-sum formulation can then be selected by compromising between these benchmark values, providing a more informed and transparent basis for multiobjective trade-offs.
This strategy is especially useful during test design and exploratory phases, where understanding the attainable extremes of each objective helps guide principled weight selection.
How to use:
Define individual objective terms using objective_term(). Objective terms may be entirely relative, entirely absolute, or a mixture of both.
Combine them directly using weighted_sum_obj().
Alternatively, first construct compiled objectives using maximin_obj(), capped_maximin_obj(), minimax_obj(), or goal_programming_obj(), and then combine multiple compiled objectives using weighted_sum_obj().
A list of class "compiled_objective".
A character vector indicating the specifications in each row of "A_binary"
A data.frame including "Requirement","Attribute","Type","Application Level","Operator","Num of Constraints"
Sparse matrix of coefficients for binary decision variables.
Sparse matrix of coefficients for real decision variables.
A character vector of constraint operators, one per row of "A_binary".
A numeric vector of right-hand-side values for the constraints.
Penalty vector for binary variables (if any)
Penalty vector for real variables (if any)
"min" or "max"
Character vector indicating the names of new decision variables, same length as "ncol(A_real)".
A character vector of "C" (continuous), same length as "ncol(A_real)".
List of metadata.
For each objective term :
where:
For relative objectives:
is the coefficient vector defined by the attribute,
level, and application scope of the objective term;
is the vector of binary item-module-panel decision variables;
the objective value is .
For absolute (goal-based) objectives:
is the coefficient vector defined by the attribute,
level, and application scope of the objective term;
is the target value specified by the test developer;
the objective minimizes deviation from the target:
;
auxiliary deviation variables are introduced to linearize the absolute value.
The weighted-sum objective is then:
where:
if term k is a minimization objective.
if term k is a maximization objective.
van der Linden, W. J. (2005). Linear models for optimal test design (pp. 68–69). doi:10.1007/0-387-29054-0
data("mini_itempool") test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", exclude_pathway = c("1-1-3", "1-3-1"), pathway_length = 8 ) # Example: maximize test information at theta = -1, 0, and 1 # in the routing module, with targets at -1 and 1 obj1 <- objective_term( x = test_mstATA, attribute = "iif(theta=-1)", applied_level = "Module-level", which_module = 1, sense = "min", goal = 12 ) obj2 <- objective_term( x = test_mstATA, attribute = "iif(theta=0)", applied_level = "Module-level", which_module = 1, sense = "max" ) obj3 <- objective_term( x = test_mstATA, attribute = "iif(theta=1)", applied_level = "Module-level", which_module = 1, sense = "min", goal = 12 ) weighted_sum_obj(x = test_mstATA, multiple_terms = list(obj1,obj2,obj3))data("mini_itempool") test_mstATA <- mst_design( itempool = mini_itempool, design = "1-3-3", exclude_pathway = c("1-1-3", "1-3-1"), pathway_length = 8 ) # Example: maximize test information at theta = -1, 0, and 1 # in the routing module, with targets at -1 and 1 obj1 <- objective_term( x = test_mstATA, attribute = "iif(theta=-1)", applied_level = "Module-level", which_module = 1, sense = "min", goal = 12 ) obj2 <- objective_term( x = test_mstATA, attribute = "iif(theta=0)", applied_level = "Module-level", which_module = 1, sense = "max" ) obj3 <- objective_term( x = test_mstATA, attribute = "iif(theta=1)", applied_level = "Module-level", which_module = 1, sense = "min", goal = 12 ) weighted_sum_obj(x = test_mstATA, multiple_terms = list(obj1,obj2,obj3))
A precomputed multistage testing (MST) panel assembled using the weighted_sum objective formulation described in the Formulation for Multiple Objectives vignette.
weighted_sum_panelweighted_sum_panel
An object of class mstATA_panel.
This object is included to avoid long solver runtimes during vignette building and package checking.
Generated using mstATA::assembled_panels() and mstATA::solve_model()with the HiGHS solver.