Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ebi item selection #6

Merged
merged 14 commits into from
Jan 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: RSCAT
Title: Shadow-Test Approach to Computerized Adaptive Testing
Version: 1.0.2
Version: 1.1.0
Authors@R: c(
person("Bingnan", "Jiang", email = "bnjiangece@gmail.com", role = c("aut", "cre")),
person("ACT, Inc.", role = "cph")
Expand All @@ -21,7 +21,7 @@ Description: As an advanced approach to computerized adaptive testing (CAT),
Depends: R (>= 3.4.0), rJava, shiny, shinycssloaders, shinyjs
License: CC BY-NC 4.0
Encoding: UTF-8
RoxygenNote: 6.1.1
RoxygenNote: 7.0.2
Imports:
Metrics, ggplot2, gridExtra, grid, methods, stats, utils
Collate:
Expand Down
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ importFrom(shinyjs,disabled)
importFrom(shinyjs,enable)
importFrom(shinyjs,reset)
importFrom(shinyjs,useShinyjs)
importFrom(stats,quantile)
importFrom(stats,sd)
importFrom(utils,download.file)
importFrom(utils,read.csv)
Expand Down
6 changes: 5 additions & 1 deletion R/SimResult.R
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
#' @slot shadowTests a list of length \code{numExaminees}. Each element of
#' the list is also a list representing the shadow test assembled at each
#' adaptive stage.
#' @slot engineTime a list of length \code{numExaminees}. Each element of
#' the list is a numeric vector representing the engine time at each adaptive step.
#' the engine time includes time consumed by CAT algorithms and shadow test assembly.
SimResult <- setClass(
"SimResult",
slots = c(
Expand All @@ -37,5 +40,6 @@ SimResult <- setClass(
estThetaSEs = "list",
scores = "list",
itemsAdministered = "list",
shadowTests = "list")
shadowTests = "list",
engineTime = "list")
)
3 changes: 3 additions & 0 deletions R/configClasses.R
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ SolverConfig <- setClass(
#' @slot initialTheta the initial ability theta value.
#' @slot scalingConstant the constraint to scale a discrimination coefficient.
#' estimated with the logistic model to the normal metric.
#' @slot itemSelectionMethod a character string specifying the item selection method.
#' @slot scoreMethodConfig a rJava \code{jobjRef} object for CAT scoring method
#' configuration. It is generated by the function \code{scoreMethodConfig}.
#' @slot exposureControlType a character string specifying the exposure control
Expand All @@ -54,6 +55,7 @@ CATConfig <- setClass(
solverConfig = "SolverConfig",
initialTheta = "numeric",
scalingConstant = "numeric",
itemSelectionMethod = "character",
scoreMethodConfig = "jobjRef",
exposureControlType = "character",
exposureControlRate = "numeric",
Expand All @@ -63,6 +65,7 @@ CATConfig <- setClass(
solverConfig = SolverConfig(),
initialTheta = 0.0,
scalingConstant = 1.0,
itemSelectionMethod = "maxInfo",
scoreMethodConfig = rJava::.jnull(),
exposureControlType = "None",
exposureControlRate = 0.5,
Expand Down
11 changes: 9 additions & 2 deletions R/runSim.R
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,11 @@ runSim <- function(catConfig, testConfig, simConfig) {
method = "runSim",
rJava::.jcast(
catConfig@scoreMethodConfig,
"org/act/cat/ScoringMethodConfig"
"org/act/cat/AbstractScoringMethodConfig"
),
catConfig@initialTheta,
catConfig@scalingConstant,
catConfig@itemSelectionMethod,
catConfig@exposureControlType,
catConfig@exposureControlRate,
catConfig@lValue,
Expand Down Expand Up @@ -101,6 +102,7 @@ runSim <- function(catConfig, testConfig, simConfig) {
scoresList <- list()
itemAdministeredList <- list()
shadowTestsList <- list()
engineTimeList <- list()

# Retrive data from the Java object
for (i in 1:numExaminees) {
Expand All @@ -113,6 +115,7 @@ runSim <- function(catConfig, testConfig, simConfig) {
scores <- numeric(testConfig@testLength)
itemsAdmin <- character(testConfig@testLength)
shadowTestExamineeList <- list()
engineTime <- numeric(testConfig@testLength)

for (j in 1:testConfig@testLength) {

Expand All @@ -131,12 +134,15 @@ runSim <- function(catConfig, testConfig, simConfig) {
resultExamineeStage <- resultExaminee$getShadowTestList()$get(as.integer(j - 1))
shadowTestExamineeList[[j]] <-
unlist(strsplit(gsub("\\[|\\]", "", resultExamineeStage$toString()), ", "))
engineTime[j] <-
resultExaminee$getCatEngineTimeList()$get(as.integer(j-1))
}
estThetasList[[i]] <- thetas
estThetaSEsList[[i]] <- thetaSEs
scoresList[[i]] <- scores
itemAdministeredList[[i]] <- itemsAdmin
shadowTestsList[[i]] <- shadowTestExamineeList
engineTimeList[[i]] <- engineTime
}
return(
SimResult(
Expand All @@ -148,7 +154,8 @@ runSim <- function(catConfig, testConfig, simConfig) {
estThetaSEs = estThetaSEsList,
scores = scoresList,
itemsAdministered = itemAdministeredList,
shadowTests = shadowTestsList
shadowTests = shadowTestsList,
engineTime = engineTimeList
)
)

Expand Down
3 changes: 2 additions & 1 deletion R/shinyAppServer.R
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ shinyAppServer <- function(input, output) {
# CAT configuration
catConfig <- CATConfig(
solverConfig = solverConfig,
itemSelectionMethod = input$itemSelectionMethod,
scoreMethodConfig = scoreMethodConfig(eapConfig),
lValue = input$lValue,
exposureControlType = input$exposureType,
Expand Down Expand Up @@ -288,7 +289,7 @@ shinyAppServer <- function(input, output) {
output$simResultSummary <- NULL
resetElementIds <- c("testName", "testLength", "itemPoolFile",
"passagePoolFile", "minNumPassage", "maxNumPassage", "constraintFile",
"enemyItmesStr", "scoringMethod", "scoringAdvanced",
"enemyItmesStr", "itemSelectionMethod", "scoringMethod", "scoringAdvanced",
"numPoints", "minPoint", "maxPoint", "priorDist", "distMean", "distSd",
"aVal", "bVal", "exposureType", "goalRate", "simName", "simTestTakerNum",
"trueThetePriorDistType", "thetaMin", "thetaMax", "thetaMean", "thetaSD",
Expand Down
3 changes: 3 additions & 0 deletions R/shinyAppUI.R
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ shinyAppUI <- fluidPage(
hr(),
h4("CAT Algorithm Configuration"),

# Select item selection method
selectInput("itemSelectionMethod", "Item Selection Criterion", c("Max Information" = "maxInfo", "EBI" = "ebi")),

# Select the scoring method
selectInput("scoringMethod", "Scoring Method", c("EAP" = "eap")),

Expand Down
26 changes: 24 additions & 2 deletions R/utilFunctions.R
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,41 @@
#'
#' @param object an object of \code{SimResult}.
#' Generates the summary report of CAT simulation.
#' @importFrom stats quantile
#' @export
setMethod(
f = "summary",
signature = c("SimResult"),
definition = function(object) {
thetaBias <- Metrics::bias(object@trueThetas, object@finalThetas)
thetaRMSE <- Metrics::rmse(object@trueThetas, object@finalThetas)
engineTimeMean <- mean(unlist(object@engineTime))
engineTimeMin <- min(unlist(object@engineTime))
engineTimeMax <- max(unlist(object@engineTime))
engineTimeSd <- format(round(sd(unlist(object@engineTime)), 4), nsmall = 4)
thetaBias <- format(round(thetaBias, 4), nsmall = 4)
thetaRMSE <- format(round(thetaRMSE, 4), nsmall = 4)
metrics <- list(thetaBias = thetaBias, thetaRMSE = thetaRMSE)
quantileVal <- format(round(unname(quantile(unlist(object@engineTime),
c(0.25, 0.5, 0.75, 0.99))), 3), nsmall = 3)

metrics <- list(thetaBias = thetaBias, thetaRMSE = thetaRMSE,
engineTimeMean = engineTimeMean,
engineTimeMin = engineTimeMin,
engineTimeMax = engineTimeMax,
engineTimeSd = engineTimeSd)
msg <- paste("Numer of simulated examinees: ",
object@numExaminees, "\n",
"Theta estimate bias: ", thetaBias, "\n",
"Theta estimate RMSE: ", thetaRMSE, "\n", sep = "")
"Theta estimate RMSE: ", thetaRMSE, "\n",
"Mean engine time (step): ", engineTimeMean, "\n",
"Sd of engine time (step): ", engineTimeSd, "\n",
"Min engine time (step): ", engineTimeMin, "\n",
"Max engine time (step): ", engineTimeMax, "\n",
"Engine time 25% percentile (step): ", quantileVal[1], "\n",
"Engine time 50% percentile (step): ", quantileVal[2], "\n",
"Engine time 75% percentile (step): ", quantileVal[3], "\n",
"Engine time 99% percentile (step): ", quantileVal[4], "\n",
sep = "")
cat(msg)
ret <- list(msg = msg, metrics = metrics)
return(ret)
Expand Down Expand Up @@ -67,6 +88,7 @@ result2CSV <- function(simResult, file) {
"Score" = simResult@scores[[n]],
"Theta Estimate" = simResult@estThetas[[n]],
"Theta Estimate SE" = simResult@estThetaSEs[[n]],
"Engine Time" = simResult@engineTime[[n]],
"Shadow Test" = sapply(simResult@shadowTests[[n]], pasteWithQuote))
write.csv(examineeOverall[[n]], row.names = FALSE)
write.csv(examineeStage[[n]], row.names = FALSE)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Overview
As an advanced approach to computerized adaptive testing (CAT),
shadow testing (van der Linden(2005) <doi:10.1007/0-387-29054-0>) dynamically assembles entire shadow tests as a part of
shadow testing (van der Linden, 2005, <doi:10.1007/0-387-29054-0>) dynamically assembles entire shadow tests as a part of
selecting items throughout the testing process.
Selecting items from shadow tests guarantees the compliance of all content
constraints defined by the blueprint. RSCAT is an R package for the
Expand Down
Binary file not shown.
4 changes: 2 additions & 2 deletions java/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.act</groupId>
<artifactId>RSCAT</artifactId>
<version>1.0.2</version>
<version>1.1.0</version>
<developers>
<developer>
<id>jiangb</id>
Expand Down Expand Up @@ -59,7 +59,7 @@
<dependency>
<groupId>com.dashoptimization</groupId>
<artifactId>xprm</artifactId>
<version>5.0.0</version>
<version>5.0.2</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,48 +1,48 @@
package org.act.cat;

import org.act.util.ProbDistribution;

/**
* This class defines a scoring method configuration. Parameters in the
* configuration are applied to the scoring algorithm.
*/
public abstract class ScoringMethodConfig {

private final ProbDistribution priorDistribution;

/**
* Constructs an empty {@link ScoringMethodConfig}.
*/
public ScoringMethodConfig() {
this.priorDistribution = null;
}

/**
* Constructs a new {@link ScoringMethodConfig}.
*
* @param priorDistribution the prior distribution used in the scoring
* method.
* @see ProbDistribution
*/
public ScoringMethodConfig(ProbDistribution priorDistribution) {
this.priorDistribution = priorDistribution;
}

/**
* Returns the type of the scoring method related to the configuration.
*
* @return the type of the scoring method
*/
public abstract ScoringMethod.SUPPORTED_METHODS scoringMethod();

/**
* Returns the prior distribution used in the scoring method.
*
* @return the prior distribution
* @see ProbDistribution
*/
public ProbDistribution getPriorDistribution() {
return priorDistribution;
}

}
package org.act.cat;
import org.act.util.ProbDistribution;
/**
* This class defines a scoring method configuration. Parameters in the
* configuration are applied to the scoring algorithm.
*/
public abstract class AbstractScoringMethodConfig {
private final ProbDistribution priorDistribution;
/**
* Constructs an empty {@link AbstractScoringMethodConfig}.
*/
public AbstractScoringMethodConfig() {
this.priorDistribution = null;
}
/**
* Constructs a new {@link AbstractScoringMethodConfig}.
*
* @param priorDistribution the prior distribution used in the scoring
* method.
* @see ProbDistribution
*/
public AbstractScoringMethodConfig(ProbDistribution priorDistribution) {
this.priorDistribution = priorDistribution;
}
/**
* Returns the type of the scoring method related to the configuration.
*
* @return the type of the scoring method
*/
public abstract ScoringMethod.SUPPORTED_METHODS scoringMethod();
/**
* Returns the prior distribution used in the scoring method.
*
* @return the prior distribution
* @see ProbDistribution
*/
public ProbDistribution getPriorDistribution() {
return priorDistribution;
}
}
10 changes: 9 additions & 1 deletion java/src/main/java/org/act/cat/CatConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public interface CatConfig {
*
* @return the instance of {@link ScoringMethodConfig}
*/
ScoringMethodConfig scoringMethodConfig();
AbstractScoringMethodConfig scoringMethodConfig();

/**
* Returns the number <code>L</code> of items that are randomly administered at
Expand All @@ -54,4 +54,12 @@ public interface CatConfig {
* @return the exposure control configuration
*/
ExposureControlConfig exposureControlConfig();

/**
* Returns the type of item selection method.
*
* @return the type of item selection method.
* @see ItemSelectionMethod.SUPPORTED_METHODS
*/
ItemSelectionMethod.SUPPORTED_METHODS itemSelectionMethod();
}
Loading