jkcshea / ivmte

An R package for implementing the method in Mogstad, Santos, and Torgovitsky (2018, Econometrica).
GNU General Public License v3.0
18 stars 2 forks source link

Logical treated differently than binary integer #223

Closed johnnybonney closed 2 years ago

johnnybonney commented 2 years ago

I've been seeing an issue where the solution could be infeasible based on whether a variable is of type logical or a binary integer. Consider this example:

library(ivmte)
library(data.table)

dt <- AE[AE$yob <= 45,]
setDT(dt)
dt[, p := mean(morekids), by = .(yob, samesex)]

# define logical variables
dt[, yob44_log := (yob == 44)]
dt[, yob45_log := (yob == 45)]

# define integer variables
dt[, yob44_int := as.integer(yob == 44)]
dt[, yob45_int := as.integer(yob == 45)]

knots44 <- unique(dt[yob == 44]$p)
knots45 <- unique(dt[yob == 45]$p)

mtr_logical <- ~factor(yob) +
  yob44_log:uSplines(degree = 0, knots = knots44) +
  yob45_log:uSplines(degree = 0, knots = knots45)

args <- list(data = dt,
             outcome = "worked",
             m1 = mtr_logical,
             m0 = mtr_logical,
             propensity = morekids ~ factor(samesex)*factor(yob),
             target = 'ate',
             solver = "gurobi",
             noisy = T)  

# estimate with yob as a logical variable
est_logical <- do.call(ivmte, args)

produces

Obtaining propensity scores...

Generating target moments...
    Integrating terms for control group...
    Integrating terms for treated group...

Performing direct MTR regression...
    MTR is not point identified.

Performing audit procedure...
    Solver: Gurobi ('gurobi')
    Generating initial constraint grid...

    Audit count: 1
    Minimum criterion: 0.2384021
    Obtaining bounds...
    Model was infeasible or unbounded.
Error:  The minimization problem was proven to be infeasible or unbounded. The maximization problem was proven to be infeasible or unbounded. The solver may find the model to be infeasible or unbounded if the quadratic constraint is too restrictive (infeasible), or the the initial grid is too small (unbounded). Try increasing the parameters 'criterion.tol' to relax the quadratic constraint; or increasing the parameters 'initgrid.nx' and 'initgrid.nu' to better bound the problem. If the model is indeed infeasible, consider exporting the model and passing it to the solver for more details. 

But, if I replace the logical covariates with their integer equivalents, things run smoothly:

# replace it with integers, and it runs
mtr_integer <- ~factor(yob) +
  yob44_int:uSplines(degree = 0, knots = knots44) +
  yob45_int:uSplines(degree = 0, knots = knots45)

args$m1 <- mtr_integer
args$m0 <- mtr_integer

est_integer <- do.call(ivmte, args)
Obtaining propensity scores...

Generating target moments...
    Integrating terms for control group...
    Integrating terms for treated group...

Performing direct MTR regression...
    MTR is not point identified.

Performing audit procedure...
    Solver: Gurobi ('gurobi')
    Generating initial constraint grid...

    Audit count: 1
    Minimum criterion: 0.2384021
    Obtaining bounds...
    Violations: 0
    Audit finished.

Bounds on the target parameter: [-0.5561029, 0.3933937]

ivmte is clearly not treating the two problems the same---I wonder if the logical variables are being converted into factor variables or something? In either case, I believe the logical variables should just be converted into integers. As per ?logical,

Logical vectors are coerced to integer vectors in contexts where a numerical value is required, with TRUE being mapped to 1L, FALSE to 0L and NA to NA_integer_.
jkcshea commented 2 years ago

Done!