@@ -232,103 +232,18 @@ ei_bounds_impl <- function(x, y, bounds, contr_m, has_contrast = FALSE, sum_one
232232 }
233233
234234 if (has_contrast ) {
235- bounds_lp_contrast_cpp (x , y , contr_m , bounds , sum_one )
235+ bounds_lp_contrast (x , y , contr_m , bounds , sum_one )
236236 } else {
237237 R_bounds_lp(x , y , as.double(bounds ))
238238 }
239239}
240240
241- # Solve bounds LP using lpSolve for contrast case (optimized)
241+ # Solve bounds LP using full simplex solver for contrast case
242242bounds_lp_contrast <- function (x , y , contr_m , bounds , sum_one ) {
243243 n = nrow(x )
244244 n_x = ncol(x )
245245 n_y = ncol(y )
246246 n_c = ncol(contr_m )
247- n_vars = n_y * n_x
248-
249- has_lb = is.finite(bounds [1 ])
250- has_ub = is.finite(bounds [2 ])
251- if (has_lb ) {
252- shift = bounds [1 ]
253- scale = 1
254- } else if (! has_lb && has_ub ) {
255- shift = bounds [2 ]
256- scale = - 1
257- has_ub = FALSE
258- } else {
259- cli_abort(" At least one bound must be finite." )
260- }
261-
262- y = scale * (y - shift )
263- ub = bounds [2 ] - shift
264-
265- res_min = matrix (nrow = n , ncol = n_c )
266- res_max = matrix (nrow = n , ncol = n_c )
267-
268- # Variables: B[k,j] for k=1..n_y, j=1..n_x (total n_y*n_x variables, row-major order)
269- A = matrix (0 , nrow = n_vars , ncol = n_y )
270- rhs = rep(0 , n_y )
271- dir_vec = rep(" ==" , n_y )
272- if (sum_one ) {
273- if (n_y == 1 || bounds [2 ] != 1 ) {
274- cli_abort(
275- " Using{.arg sum_one} requires multiple outcomes bounded above by 1." ,
276- call = parent.frame()
277- )
278- }
279- A = cbind(A , rep(scale , n_y ) %x% diag(n_x ))
280- rhs = c(rhs , rep(scale * (1 - shift ), n_x ))
281- dir_vec = c(dir_vec , rep(" ==" , n_x ))
282- }
283- if (has_ub ) {
284- A = cbind(A , diag(n_vars ))
285- rhs = c(rhs , rep(ub , n_vars ))
286- dir_vec = c(dir_vec , rep(" <=" , n_vars ))
287- }
288-
289- # For each observation
290- for (j in seq_len(n_c )) {
291- contr = contr_m [, j ]
292- obj_offset = sum(contr ) * shift
293-
294- for (i in seq_len(n )) {
295- A [, seq_len(n_y )] = diag(n_y ) %x% x [i , ]
296- rhs [seq_len(n_y )] = y [i , ]
297-
298- sol = lpSolve :: lp(
299- direction = " min" ,
300- objective.in = contr ,
301- const.mat = A ,
302- const.dir = dir_vec ,
303- const.rhs = rhs ,
304- transpose.constraints = FALSE
305- )
306- if (sol $ status == 0 ) {
307- res_min [i , j ] = sol $ objval + obj_offset
308- }
309- sol = lpSolve :: lp(
310- direction = " max" ,
311- objective.in = contr ,
312- const.mat = A ,
313- const.dir = dir_vec ,
314- const.rhs = rhs ,
315- transpose.constraints = FALSE
316- )
317- if (sol $ status == 0 ) {
318- res_max [i , j ] = sol $ objval + obj_offset
319- }
320- }
321- }
322-
323- list (min = res_min * scale + shift , max = res_max * scale + shift )
324- }
325-
326- # C++ version of bounds_lp_contrast using custom simplex solver
327- bounds_lp_contrast_cpp <- function (x , y , contr_m , bounds , sum_one ) {
328- n = nrow(x )
329- n_x = ncol(x )
330- n_y = ncol(y )
331- n_c = ncol(contr_m )
332247
333248 has_lb = is.finite(bounds [1 ])
334249 has_ub = is.finite(bounds [2 ])
0 commit comments