Skip to contents

Restrict a model's parameter space. This reduces the number of nodal types and in consequence the number of unit causal types.

Usage

set_restrictions(
  model,
  statement = NULL,
  join_by = "|",
  labels = NULL,
  param_names = NULL,
  given = NULL,
  keep = FALSE
)

Arguments

model

A causal_model. A model object generated by make_model.

statement

A quoted expressions defining the restriction. If values for some parents are not specified, statements should be surrounded by parentheses, for instance (Y[A = 1] > Y[A=0]) will be interpreted for all combinations of other parents of Y set at possible levels they might take.

join_by

A string. The logical operator joining expanded types when statement contains wildcard (.). Can take values '&' (logical AND) or '|' (logical OR). When restriction contains wildcard (.) and join_by is not specified, it defaults to '|', otherwise it defaults to NULL. Note that join_by joins within statements, not across statements.

labels

A list of character vectors specifying nodal types to be kept or removed from the model. Use get_nodal_types to see syntax. Note that labels gets overwritten by statement if statement is not NULL.

param_names

A character vector of names of parameters to restrict on.

given

A character vector or list of character vectors specifying nodes on which the parameter set to be restricted depends. When restricting by statement, given must either be NULL or of the same length as statement. When mixing statements that are further restricted by given and ones that are not, statements without given restrictions should have given specified as one of NULL, NA, "" or " ".

keep

Logical. If `FALSE`, removes and if `TRUE` keeps only causal types specified by statement or labels.

Value

An object of class model. The causal types and nodal types in the model are reduced according to the stated restriction.

Details

Restrictions are made to nodal types, not to unit causal types. Thus for instance in a model X -> M -> Y, one cannot apply a simple restriction so that Y is nondecreasing in X, however one can restrict so that M is nondecreasing in X and Y nondecreasing in M. To have a restriction that Y be nondecreasing in X would otherwise require restrictions on causal types, not nodal types, which implies a form of undeclared confounding (i.e. that in cases in which M is decreasing in X, Y is decreasing in M).

Since restrictions are to nodal types, all parents of a node are implicitly fixed. Thus for model make_model(`X -> Y <- W`) the request set_restrictions(`(Y[X=1] == 0)`) is interpreted as set_restrictions(`(Y[X=1, W=0] == 0 | Y[X=1, W=1] == 0)`).

Statements with implicitly controlled nodes should be surrounded by parentheses, as in these examples.

Note that prior probabilities are redistributed over remaining types.

See also

Other restrictions: restrict_by_labels(), restrict_by_query()

Examples


# 1. Restrict parameter space using statements
model <- make_model('X->Y') %>%
  set_restrictions(statement = c('X[] == 0'))

model <- make_model('X->Y') %>%
  set_restrictions(non_increasing('X', 'Y'))

model <- make_model('X -> Y <- W') %>%
  set_restrictions(c(decreasing('X', 'Y'), substitutes('X', 'W', 'Y')))

model$parameters_df
#> Mapping of model parameters to nodal types: 
#> 
#> ----------------------------------------------------------------
#> 
#>  param_names: name of parameter
#>  node: name of endogeneous node associated with the parameter
#>  gen: partial causal ordering of the parameter's node
#>  param_set: parameter groupings forming a simplex
#>  given: if model has confounding gives conditioning nodal type
#>  param_value: parameter values
#>  priors: hyperparameters of the prior Dirichlet distribution 
#> 
#> ----------------------------------------------------------------
#> 
#> 
#>  first 10 rows: 
#>    param_names node gen param_set nodal_type given param_value priors
#> 1          W.0    W   1         W          0         0.5000000      1
#> 2          W.1    W   1         W          1         0.5000000      1
#> 3          X.0    X   2         X          0         0.5000000      1
#> 4          X.1    X   2         X          1         0.5000000      1
#> 5       Y.0000    Y   3         Y       0000         0.1428571      1
#> 10      Y.1010    Y   3         Y       1010         0.1428571      1
#> 13      Y.0001    Y   3         Y       0001         0.1428571      1
#> 15      Y.0101    Y   3         Y       0101         0.1428571      1
#> 17      Y.0011    Y   3         Y       0011         0.1428571      1
#> 18      Y.1011    Y   3         Y       1011         0.1428571      1

model <- make_model('X-> Y <- W') %>%
  set_restrictions(statement = decreasing('X', 'Y'))
model$parameters_df
#> Mapping of model parameters to nodal types: 
#> 
#> ----------------------------------------------------------------
#> 
#>  param_names: name of parameter
#>  node: name of endogeneous node associated with the parameter
#>  gen: partial causal ordering of the parameter's node
#>  param_set: parameter groupings forming a simplex
#>  given: if model has confounding gives conditioning nodal type
#>  param_value: parameter values
#>  priors: hyperparameters of the prior Dirichlet distribution 
#> 
#> ----------------------------------------------------------------
#> 
#> 
#>  first 10 rows: 
#>    param_names node gen param_set nodal_type given param_value priors
#> 1          W.0    W   1         W          0         0.5000000      1
#> 2          W.1    W   1         W          1         0.5000000      1
#> 3          X.0    X   2         X          0         0.5000000      1
#> 4          X.1    X   2         X          1         0.5000000      1
#> 5       Y.0000    Y   3         Y       0000         0.1111111      1
#> 9       Y.0010    Y   3         Y       0010         0.1111111      1
#> 10      Y.1010    Y   3         Y       1010         0.1111111      1
#> 13      Y.0001    Y   3         Y       0001         0.1111111      1
#> 15      Y.0101    Y   3         Y       0101         0.1111111      1
#> 17      Y.0011    Y   3         Y       0011         0.1111111      1

model <- make_model('X->Y') %>%
  set_restrictions(decreasing('X', 'Y'))
model$parameters_df
#> Mapping of model parameters to nodal types: 
#> 
#> ----------------------------------------------------------------
#> 
#>  param_names: name of parameter
#>  node: name of endogeneous node associated with the parameter
#>  gen: partial causal ordering of the parameter's node
#>  param_set: parameter groupings forming a simplex
#>  given: if model has confounding gives conditioning nodal type
#>  param_value: parameter values
#>  priors: hyperparameters of the prior Dirichlet distribution 
#> 
#> ----------------------------------------------------------------
#> 
#>   param_names node gen param_set nodal_type given param_value priors
#> 1         X.0    X   1         X          0         0.5000000      1
#> 2         X.1    X   1         X          1         0.5000000      1
#> 3        Y.00    Y   2         Y         00         0.3333333      1
#> 5        Y.01    Y   2         Y         01         0.3333333      1
#> 6        Y.11    Y   2         Y         11         0.3333333      1

model <- make_model('X->Y') %>%
  set_restrictions(c(increasing('X', 'Y'), decreasing('X', 'Y')))
model$parameters_df
#> Mapping of model parameters to nodal types: 
#> 
#> ----------------------------------------------------------------
#> 
#>  param_names: name of parameter
#>  node: name of endogeneous node associated with the parameter
#>  gen: partial causal ordering of the parameter's node
#>  param_set: parameter groupings forming a simplex
#>  given: if model has confounding gives conditioning nodal type
#>  param_value: parameter values
#>  priors: hyperparameters of the prior Dirichlet distribution 
#> 
#> ----------------------------------------------------------------
#> 
#>   param_names node gen param_set nodal_type given param_value priors
#> 1         X.0    X   1         X          0               0.5      1
#> 2         X.1    X   1         X          1               0.5      1
#> 3        Y.00    Y   2         Y         00               0.5      1
#> 6        Y.11    Y   2         Y         11               0.5      1
# \donttest{
# Restrict to define a model with monotonicity
model <- make_model('X->Y') %>%
set_restrictions(statement = c('Y[X=1] < Y[X=0]'))
grab(model, "parameter_matrix")
#> 
#> Rows are parameters, grouped in parameter sets
#> 
#> Columns are causal types
#> 
#> Cell entries indicate whether a parameter probability isused
#> in the calculation of causal type probability
#> 
#>      X0.Y00 X1.Y00 X0.Y01 X1.Y01 X0.Y11 X1.Y11
#> X.0       1      0      1      0      1      0
#> X.1       0      1      0      1      0      1
#> Y.00      1      1      0      0      0      0
#> Y.01      0      0      1      1      0      0
#> Y.11      0      0      0      0      1      1
#> 
#>  
#>  param_set  (P)
#>  

# Restrict to a single type in endogenous node
model <- make_model('X->Y') %>%
set_restrictions(statement =  '(Y[X = 1] == 1)', join_by = '&', keep = TRUE)
grab(model, "parameter_matrix")
#> 
#> Rows are parameters, grouped in parameter sets
#> 
#> Columns are causal types
#> 
#> Cell entries indicate whether a parameter probability isused
#> in the calculation of causal type probability
#> 
#>      X0.Y01 X1.Y01 X0.Y11 X1.Y11
#> X.0       1      0      1      0
#> X.1       0      1      0      1
#> Y.01      1      1      0      0
#> Y.11      0      0      1      1
#> 
#>  
#>  param_set  (P)
#>  

#  Use of | and &
# Keep node if *for some value of B* Y[A = 1] == 1
model <- make_model('A->Y<-B') %>%
set_restrictions(statement =  '(Y[A = 1] == 1)', join_by = '|', keep = TRUE)
dim(grab(model ,"parameter_matrix"))
#> [1] 16 48


# Keep node if *for all values of B* Y[A = 1] == 1
model <- make_model('A->Y<-B') %>%
set_restrictions(statement =  '(Y[A = 1] == 1)', join_by = '&', keep = TRUE)
dim(grab(model, "parameter_matrix"))
#> [1]  8 16

# Restrict multiple nodes
model <- make_model('X->Y<-M; X -> M' ) %>%
set_restrictions(statement =  c('(Y[X = 1] == 1)', '(M[X = 1] == 1)'),
                 join_by = '&', keep = TRUE)
grab(model, "parameter_matrix")
#> 
#> Rows are parameters, grouped in parameter sets
#> 
#> Columns are causal types
#> 
#> Cell entries indicate whether a parameter probability isused
#> in the calculation of causal type probability
#> 
#>        X0.M01.Y0101 X1.M01.Y0101 X0.M11.Y0101 X1.M11.Y0101 X0.M01.Y1101
#> X.0               1            0            1            0            1
#> X.1               0            1            0            1            0
#> M.01              1            1            0            0            1
#> M.11              0            0            1            1            0
#> Y.0101            1            1            1            1            0
#> Y.1101            0            0            0            0            1
#> Y.0111            0            0            0            0            0
#> Y.1111            0            0            0            0            0
#>        X1.M01.Y1101 X0.M11.Y1101 X1.M11.Y1101 X0.M01.Y0111 X1.M01.Y0111
#> X.0               0            1            0            1            0
#> X.1               1            0            1            0            1
#> M.01              1            0            0            1            1
#> M.11              0            1            1            0            0
#> Y.0101            0            0            0            0            0
#> Y.1101            1            1            1            0            0
#> Y.0111            0            0            0            1            1
#> Y.1111            0            0            0            0            0
#>        X0.M11.Y0111 X1.M11.Y0111 X0.M01.Y1111 X1.M01.Y1111 X0.M11.Y1111
#> X.0               1            0            1            0            1
#> X.1               0            1            0            1            0
#> M.01              0            0            1            1            0
#> M.11              1            1            0            0            1
#> Y.0101            0            0            0            0            0
#> Y.1101            0            0            0            0            0
#> Y.0111            1            1            0            0            0
#> Y.1111            0            0            1            1            1
#>        X1.M11.Y1111
#> X.0               0
#> X.1               1
#> M.01              0
#> M.11              1
#> Y.0101            0
#> Y.1101            0
#> Y.0111            0
#> Y.1111            1
#> 
#>  
#>  param_set  (P)
#>  

# Restrict using statements and given:
model <- make_model("X -> Y -> Z; X <-> Z") %>%
 set_restrictions(list(decreasing('X','Y'), decreasing('Y','Z')),
                  given = c(NA,'X.0'))
grab(model, "parameter_matrix")
#> 
#> Rows are parameters, grouped in parameter sets
#> 
#> Columns are causal types
#> 
#> Cell entries indicate whether a parameter probability isused
#> in the calculation of causal type probability
#> 
#>          X0.Y00.Z00 X1.Y00.Z00 X0.Y01.Z00 X1.Y01.Z00 X0.Y11.Z00 X1.Y11.Z00
#> X.0               1          0          1          0          1          0
#> X.1               0          1          0          1          0          1
#> Y.00              1          1          0          0          0          0
#> Y.01              0          0          1          1          0          0
#> Y.11              0          0          0          0          1          1
#> Z.00_X.0          1          0          1          0          1          0
#> Z.01_X.0          0          0          0          0          0          0
#> Z.11_X.0          0          0          0          0          0          0
#> Z.00_X.1          0          1          0          1          0          1
#> Z.10_X.1          0          0          0          0          0          0
#> Z.01_X.1          0          0          0          0          0          0
#> Z.11_X.1          0          0          0          0          0          0
#>          X1.Y00.Z10 X1.Y01.Z10 X1.Y11.Z10 X0.Y00.Z01 X1.Y00.Z01 X0.Y01.Z01
#> X.0               0          0          0          1          0          1
#> X.1               1          1          1          0          1          0
#> Y.00              1          0          0          1          1          0
#> Y.01              0          1          0          0          0          1
#> Y.11              0          0          1          0          0          0
#> Z.00_X.0          0          0          0          0          0          0
#> Z.01_X.0          0          0          0          1          0          1
#> Z.11_X.0          0          0          0          0          0          0
#> Z.00_X.1          0          0          0          0          0          0
#> Z.10_X.1          1          1          1          0          0          0
#> Z.01_X.1          0          0          0          0          1          0
#> Z.11_X.1          0          0          0          0          0          0
#>          X1.Y01.Z01 X0.Y11.Z01 X1.Y11.Z01 X0.Y00.Z11 X1.Y00.Z11 X0.Y01.Z11
#> X.0               0          1          0          1          0          1
#> X.1               1          0          1          0          1          0
#> Y.00              0          0          0          1          1          0
#> Y.01              1          0          0          0          0          1
#> Y.11              0          1          1          0          0          0
#> Z.00_X.0          0          0          0          0          0          0
#> Z.01_X.0          0          1          0          0          0          0
#> Z.11_X.0          0          0          0          1          0          1
#> Z.00_X.1          0          0          0          0          0          0
#> Z.10_X.1          0          0          0          0          0          0
#> Z.01_X.1          1          0          1          0          0          0
#> Z.11_X.1          0          0          0          0          1          0
#>          X1.Y01.Z11 X0.Y11.Z11 X1.Y11.Z11
#> X.0               0          1          0
#> X.1               1          0          1
#> Y.00              0          0          0
#> Y.01              1          0          0
#> Y.11              0          1          1
#> Z.00_X.0          0          0          0
#> Z.01_X.0          0          0          0
#> Z.11_X.0          0          1          0
#> Z.00_X.1          0          0          0
#> Z.10_X.1          0          0          0
#> Z.01_X.1          0          0          0
#> Z.11_X.1          1          0          1
#> 
#>  
#>  param_set  (P)
#>  

# Restrictions on levels for endogenous nodes aren't allowed
if (FALSE) {
model <- make_model('X->Y') %>%
set_restrictions(statement =  '(Y == 1)')
}

# 2. Restrict parameter space Using labels:
model <- make_model('X->Y') %>%
set_restrictions(labels = list(X = '0', Y = '00'))

# Restrictions can be  with wildcards
model <- make_model('X->Y') %>%
set_restrictions(labels = list(Y = '?0'))
grab(model, "parameter_matrix")
#> 
#> Rows are parameters, grouped in parameter sets
#> 
#> Columns are causal types
#> 
#> Cell entries indicate whether a parameter probability isused
#> in the calculation of causal type probability
#> 
#>      X0.Y01 X1.Y01 X0.Y11 X1.Y11
#> X.0       1      0      1      0
#> X.1       0      1      0      1
#> Y.01      1      1      0      0
#> Y.11      0      0      1      1
#> 
#>  
#>  param_set  (P)
#>  

# Deterministic model
model <- make_model('S -> C -> Y <- R <- X; X -> C -> R') %>%
set_restrictions(labels = list(C = '1000', R = '0001', Y = '0001'),
                 keep = TRUE)
grab(model, "parameter_matrix")
#> 
#> Rows are parameters, grouped in parameter sets
#> 
#> Columns are causal types
#> 
#> Cell entries indicate whether a parameter probability isused
#> in the calculation of causal type probability
#> 
#>        S0.X0.C1000.R0001.Y0001 S1.X0.C1000.R0001.Y0001 S0.X1.C1000.R0001.Y0001
#> S.0                          1                       0                       1
#> S.1                          0                       1                       0
#> X.0                          1                       1                       0
#> X.1                          0                       0                       1
#> C.1000                       1                       1                       1
#> R.0001                       1                       1                       1
#> Y.0001                       1                       1                       1
#>        S1.X1.C1000.R0001.Y0001
#> S.0                          0
#> S.1                          1
#> X.0                          0
#> X.1                          1
#> C.1000                       1
#> R.0001                       1
#> Y.0001                       1
#> 
#>  
#>  param_set  (P)
#>  

# Restrict using labels and given:
model <- make_model("X -> Y -> Z; X <-> Z") %>%
 set_restrictions(labels = list(X = '0', Z = '00'), given = c(NA,'X.0'))
grab(model, "parameter_matrix")
#> 
#> Rows are parameters, grouped in parameter sets
#> 
#> Columns are causal types
#> 
#> Cell entries indicate whether a parameter probability isused
#> in the calculation of causal type probability
#> 
#>          X1.Y00.Z00 X1.Y10.Z00 X1.Y01.Z00 X1.Y11.Z00 X1.Y00.Z10 X1.Y10.Z10
#> X.1               1          1          1          1          1          1
#> Y.00              1          0          0          0          1          0
#> Y.10              0          1          0          0          0          1
#> Y.01              0          0          1          0          0          0
#> Y.11              0          0          0          1          0          0
#> Z.00_X.1          1          1          1          1          0          0
#> Z.10_X.1          0          0          0          0          1          1
#> Z.01_X.1          0          0          0          0          0          0
#> Z.11_X.1          0          0          0          0          0          0
#>          X1.Y01.Z10 X1.Y11.Z10 X1.Y00.Z01 X1.Y10.Z01 X1.Y01.Z01 X1.Y11.Z01
#> X.1               1          1          1          1          1          1
#> Y.00              0          0          1          0          0          0
#> Y.10              0          0          0          1          0          0
#> Y.01              1          0          0          0          1          0
#> Y.11              0          1          0          0          0          1
#> Z.00_X.1          0          0          0          0          0          0
#> Z.10_X.1          1          1          0          0          0          0
#> Z.01_X.1          0          0          1          1          1          1
#> Z.11_X.1          0          0          0          0          0          0
#>          X1.Y00.Z11 X1.Y10.Z11 X1.Y01.Z11 X1.Y11.Z11
#> X.1               1          1          1          1
#> Y.00              1          0          0          0
#> Y.10              0          1          0          0
#> Y.01              0          0          1          0
#> Y.11              0          0          0          1
#> Z.00_X.1          0          0          0          0
#> Z.10_X.1          0          0          0          0
#> Z.01_X.1          0          0          0          0
#> Z.11_X.1          1          1          1          1
#> 
#>  
#>  param_set  (P)
#>  
# }