DesignSpace: A GLMM Design Space

DesignSpaceR Documentation

A GLMM Design Space

Description

A GLMM Design Space

A GLMM Design Space

Details

A class-based representation of a "design space" that contains one or more glmmr[Design] objects.

An experimental study is comprised of a collection of experimental conditions, which are one or more observations made a pre-specified locations/values of covariates. A design space represents the collection of all possible experimental conditions for the study design and plausible models describing the data generating process. The main purpose of this class is to identify optimal study designs, that is the set of 'n' experimental conditions from all possible experimental conditions that minimise the variance of a parameter of interest across the specified GLMMs.

A DesignSpace object is intialised using one or more Design objects. Design objects can be added or removed from the collection. All designs must have the same number of rows in their design matrices (X and Z) and the same number of experimental conditions. The DesignSpace functions can modify the linked design objects.

**Initialisation** The experimental condition refers to the smallest "unit" of the study design that could be included in the design. For example, in a cluster randomised trial, the experimental condition may be single individuals such that we can observed any number of individuals in any cluster period (including none at all). In this case the experimental condition would be equivalent to row number. Alternatively, we may have to observe whole cluster periods, and we need to choose which cluster periods to observe, in which case the each observation in a different cluster-period would have the same experimental condition identifier. Finally, we may determine that the whole cluster in all periods (a "sequence") is either observed or not.

**Approximate c-Optimal designs** The algorithm identifies a c-optimal design of size m from the design space with N designs each with n observations. The objective function is

C^TM^{-1}C

where M is the information matrix and C is a vector. Typically C will be a vector of zeros with a single 1 in the position of the parameter of interest. For example, if the columns of X in the design are an interept, the treatment indicator, and then time period indicators, the vector C may be 'c(0,1,0,0,...)', such that the objective function is the variance of that parameter. If there are multiple designs in the design space, the C vectors do not have to be the same as the columns of X in each design might differ, in which case a list of vectors can be provided.

If the experimental conditions are correlated with one another, then a hill climbing algorithm is used to find the optimal design by using the convexity of the objective function to "climb the hill" towards the optimal design. If the experimental conditional are uncorrelated (but there is correlation between observations within the same experimental condition) then optionally a fast algorithm can be used to approximate the optimal design using a second-order cone program (see Sangol 2015 and van Dette). The approximate algorithm will return weights for each unique experimental condition representing the "proportion of effort" to spend on each design condition. There are different ways to translate these weights into integer values. Use of the approximate optimal design algorithm can be disabled used 'force_hill=TRUE'

In some cases the optimal design will not be full rank with respect to the design matrix X of the design space. This will result in a non-positive definite information matrix, and an error. The program will indicate which columns of X are likely "empty" in the optimal design. The user can then optionally remove these columns in the algorithm using the 'rm_cols' argument, which will delete the specified columns and linked observations before starting the algorithm.

The algorithm will also identify robust optimal designs if there are multiple designs in the design space. There are two options for robust optimisation. First, a weighted average of objective functions, where the weights are specified by the 'weights' field in the design space ('robust_function = "weighted"'). The weights may represent the prior probability or plausibility of each design, for example. Second, a minimax approach can be used, where the function identifies the design that minimises the maximum objective function across all designs ('robust_function = "minimax"').

Public fields

weights

A vector denoting the prior weighting of each Design in the design space. Required if robust optimisation is used based on a weighted average variance over the linked designs. If it is not specified in the call to 'new()' then designs are assumed to have equal weighting.

experimental_condition

A vector indicating the unique identifier of the experimental condition for each observation/row in the matrices X and Z.

Methods

Public methods


Method new()

Create a new Design Space

Creates a new design space from one or more glmmr designs.

Usage
DesignSpace$new(..., weights = NULL, experimental_condition = NULL)
Arguments
...

One or more glmmr glmmr[Design] objects. The designs must have an equal number of observations.

weights

Optional. A numeric vector of values between 0 and 1 indicating the prior weights to assign to each of the designs. The weights are required for optimisation, if a weighted average variance is used across the designs. If not specified then designs are assumed to have equal weighting.

experimental_condition

Optional. A vector of the same length as the number of observations in each design indicating the unique identifier of the experimental condition that observation belongs to, see Details. If not provided, then it is assumed that all observations are separate experimental conditions.

Returns

A 'DesignSpace' object

Examples
df <- nelder(~ ((int(2)*t(3)) > cl(3)) > ind(5))
df$int <- df$int - 1
mf1 <- MeanFunction$new(formula = ~ int + factor(t) - 1,
                        data=df,
                        parameters = rep(0,4),
                        family = gaussian())
cov1 <- Covariance$new(data = df,
                       formula = ~ (1|gr(cl)) + (1|gr(cl*t)),
                       parameters = c(0.25,0.1))
des <- Design$new(covariance = cov1,
                  mean.function = mf1,
                  var_par = 1)
ds <- DesignSpace$new(des)
#add another design
cov2 <- Covariance$new(data = df,
                       formula = ~ (1|gr(cl)*ar1(t)),
                       parameters = c(0.25,0.8))
des2 <- Design$new(covariance = cov2,
                  mean.function = mf1,
                  var_par = 1)
ds$add(des2)
#report the size of the design
ds$n()
#we can access specific designs
ds$show(2)$n()
#and then remove it
ds$remove(2)
#or we could add them when we construct object
ds <- DesignSpace$new(des,des2)
#we can specify weights
ds <- DesignSpace$new(des,des2,weights=c(0.1,0.9))
#and add experimental conditions
ds <- DesignSpace$new(des,des2,experimental_condition = df$cl)                   

Method add()

Add a design to the design space

Usage
DesignSpace$add(x)
Arguments
x

A 'Design' to add to the design space

Returns

Nothing

Examples
#See examples for constructing the class

Method remove()

Removes a design from the design space

Usage
DesignSpace$remove(index)
Arguments
index

Index of the design to remove

Returns

Nothing

Examples
#See examples for constructing the class

Method print()

Print method for the Design Space

Usage
DesignSpace$print()
Arguments
...

ignored

Returns

Prints to the console all the designs in the design space

Examples
#See examples for constructing the class

Method n()

Returns the size of the design space and number of observations

Usage
DesignSpace$n()
Examples
#See examples for constructing the class

Method optimal()

Approximate c-optimal design of size m

Algorithms to identify an approximate c-optimal design of size m within the design space.

Usage
DesignSpace$optimal(
  m,
  C,
  V0 = NULL,
  rm_cols = NULL,
  keep = FALSE,
  verbose = TRUE,
  algo = 1,
  force_hill = FALSE,
  p
)
Arguments
m

A positive integer specifying the number of experimental conditions to include.

C

Either a vector or a list of vectors of the same length as the number of designs, see Details.

V0

Optional. If a Bayesian c-optimality problem then this should be a list of prior covariance matrices for the model parameters the same length as the number of designs.

rm_cols

Optional. A list of vectors indicating columns of X to remove from each design, see Details.

keep

Logical indicating whether to "keep" the optimal design in the linked design objects and remove any experimental conditions and columns that are not part of the optimal design. Irreversible, so that these observations will be lost from the linked design objects. Defaults to FALSE.

verbose

Logical indicating whether to reported detailed output on the progress of the algorithm. Default is TRUE.

algo

character string, either "local" for local search algorithm, or "greedy" for greedy search

force_hill

Logical. If the experimental conditions are uncorrelated, if this option is TRUE then the hill climbing algorithm will be used, otherwise if it is FALSE, then a fast approximate alternative will be used. See Details

p

Positive integer specifying the size of the starting design for the greedy algorithm

Returns

A vector indicating the identifiers of the experimental conditions in the optimal design, or a vector indicating the weights if the approximate algorithm is used. Optionally the linked designs are also modified (see option 'keep').

Examples
df <- nelder(~(cl(6)*t(5)) > ind(5))
df$int <- 0
df[df$t >= df$cl, 'int'] <- 1
mf1 <- MeanFunction$new(
  formula = ~ factor(t) + int - 1,
  data=df,
  parameters = c(rep(0,5),0.6),
  family =gaussian()
)
cov1 <- Covariance$new(
  data = df,
  formula = ~ (1|gr(cl)),
  parameters = c(0.25)
)
des <- Design$new(
  covariance = cov1,
  mean.function = mf1,
  var_par = 1
)
ds <- DesignSpace$new(des)

#find the optimal design of size 30 individuals
opt <- ds$optimal(30,C=c(rep(0,5),1))

#let the experimental condition be the cluster
# these experimental conditions are independent of one another
ds <- DesignSpace$new(des,experimental_condition = df$cl)
#now find the optimal 4 clusters to include
# approximately, finding the weights for each condition
# note it will ignore m and just return the weights
opt <- ds$optimal(4,C=c(rep(0,5),1))
# or use the exact algorithm
opt <- ds$optimal(4,C=c(rep(0,5),1),force_hill = TRUE)

#robust optimisation using two designs
  cov2 <- Covariance$new(
  data = df,
  formula = ~ (1|gr(cl)*ar1(t)),
  parameters = c(0.25,0.8)
)
des2 <- Design$new(
  covariance = cov1,
  mean.function = mf1,
  var_par = 1
)
ds <- DesignSpace$new(des,des2)
#weighted average
opt <- ds$optimal(30,C=list(c(rep(0,5),1),c(rep(0,5),1)),
   robust_function = "weighted")
#and minimax
opt <- ds$optimal(30,C=list(c(rep(0,5),1),c(rep(0,5),1)),
   verbose=FALSE,robust_function = "minimax")

Method show()

Returns a linked design

Usage
DesignSpace$show(i)
Arguments
i

Index of the design to return

Examples
#See examples for constructing the class

Method clone()

The objects of this class are cloneable with this method.

Usage
DesignSpace$clone(deep = FALSE)
Arguments
deep

Whether to make a deep clone.

Examples


## ------------------------------------------------
## Method `DesignSpace$new`
## ------------------------------------------------

df <- nelder(~ ((int(2)*t(3)) > cl(3)) > ind(5))
df$int <- df$int - 1
mf1 <- MeanFunction$new(formula = ~ int + factor(t) - 1,
                        data=df,
                        parameters = rep(0,4),
                        family = gaussian())
cov1 <- Covariance$new(data = df,
                       formula = ~ (1|gr(cl)) + (1|gr(cl*t)),
                       parameters = c(0.25,0.1))
des <- Design$new(covariance = cov1,
                  mean.function = mf1,
                  var_par = 1)
ds <- DesignSpace$new(des)
#add another design
cov2 <- Covariance$new(data = df,
                       formula = ~ (1|gr(cl)*ar1(t)),
                       parameters = c(0.25,0.8))
des2 <- Design$new(covariance = cov2,
                  mean.function = mf1,
                  var_par = 1)
ds$add(des2)
#report the size of the design
ds$n()
#we can access specific designs
ds$show(2)$n()
#and then remove it
ds$remove(2)
#or we could add them when we construct object
ds <- DesignSpace$new(des,des2)
#we can specify weights
ds <- DesignSpace$new(des,des2,weights=c(0.1,0.9))
#and add experimental conditions
ds <- DesignSpace$new(des,des2,experimental_condition = df$cl)                   

## ------------------------------------------------
## Method `DesignSpace$add`
## ------------------------------------------------

#See examples for constructing the class

## ------------------------------------------------
## Method `DesignSpace$remove`
## ------------------------------------------------

#See examples for constructing the class

## ------------------------------------------------
## Method `DesignSpace$print`
## ------------------------------------------------

#See examples for constructing the class

## ------------------------------------------------
## Method `DesignSpace$n`
## ------------------------------------------------

#See examples for constructing the class

## ------------------------------------------------
## Method `DesignSpace$optimal`
## ------------------------------------------------

df <- nelder(~(cl(6)*t(5)) > ind(5))
df$int <- 0
df[df$t >= df$cl, 'int'] <- 1
mf1 <- MeanFunction$new(
  formula = ~ factor(t) + int - 1,
  data=df,
  parameters = c(rep(0,5),0.6),
  family =gaussian()
)
cov1 <- Covariance$new(
  data = df,
  formula = ~ (1|gr(cl)),
  parameters = c(0.25)
)
des <- Design$new(
  covariance = cov1,
  mean.function = mf1,
  var_par = 1
)
ds <- DesignSpace$new(des)

#find the optimal design of size 30 individuals
opt <- ds$optimal(30,C=c(rep(0,5),1))

#let the experimental condition be the cluster
# these experimental conditions are independent of one another
ds <- DesignSpace$new(des,experimental_condition = df$cl)
#now find the optimal 4 clusters to include
# approximately, finding the weights for each condition
# note it will ignore m and just return the weights
opt <- ds$optimal(4,C=c(rep(0,5),1))
# or use the exact algorithm
opt <- ds$optimal(4,C=c(rep(0,5),1),force_hill = TRUE)

#robust optimisation using two designs
  cov2 <- Covariance$new(
  data = df,
  formula = ~ (1|gr(cl)*ar1(t)),
  parameters = c(0.25,0.8)
)
des2 <- Design$new(
  covariance = cov1,
  mean.function = mf1,
  var_par = 1
)
ds <- DesignSpace$new(des,des2)
#weighted average
opt <- ds$optimal(30,C=list(c(rep(0,5),1),c(rep(0,5),1)),
   robust_function = "weighted")
#and minimax
opt <- ds$optimal(30,C=list(c(rep(0,5),1),c(rep(0,5),1)),
   verbose=FALSE,robust_function = "minimax")

## ------------------------------------------------
## Method `DesignSpace$show`
## ------------------------------------------------

#See examples for constructing the class

samuel-watson/glmmr documentation built on July 27, 2022, 10:30 p.m.