@@ -513,6 +513,76 @@ function test_mbm_finite_and_integer_var()
513513 [MOI. OPTIMAL, MOI. LOCALLY_SOLVED]
514514end
515515
516+ function test_mbm_infinite_simple ()
517+ model = InfiniteGDPModel (HiGHS. Optimizer)
518+ set_silent (model)
519+ model = InfiniteGDPModel (HiGHS. Optimizer)
520+ set_silent (model)
521+ K = 4
522+ @infinite_parameter (model, t ∈ [0 , 1 ], num_supports = K)
523+ @variable (model, 0 <= x <= 10 , Infinite (t))
524+ @variable (model, Y[1 : 2 ], InfiniteLogical (t))
525+ @constraint (model, x >= 5 , Disjunct (Y[1 ]))
526+ @constraint (model, x <= 3 , Disjunct (Y[2 ]))
527+ @disjunction (model, Y)
528+ JuMP. fix (Y[2 ], true ) # force disj 2 active
529+ @objective (model, Min, ∫ (x, t))
530+ DP. reformulate_model (model, BigM (10.0 ))
531+ set_optimizer (model, HiGHS. Optimizer)
532+ set_silent (model)
533+ optimize! (model, ignore_optimize_hook = true )
534+ sol = DP. extract_solution (model)
535+ @test haskey (sol, x)
536+ @test length (sol[x]) == K
537+ @test all (v -> isapprox (v, 0.0 ; atol= 1e-6 ), sol[x])
538+ end
539+
540+ # add_cut adds one pointwise-sum cut to the transformation backend and
541+ # marks the backend ready so the next optimize! does NOT re-transcribe.
542+ function test_add_cut_infinite ()
543+ model = InfiniteGDPModel (HiGHS. Optimizer)
544+ set_silent (model)
545+ K = 3
546+ @infinite_parameter (model, t ∈ [0 , 1 ], num_supports = K)
547+ @variable (model, 0 <= x <= 10 , Infinite (t))
548+ @variable (model, Y[1 : 2 ], InfiniteLogical (t))
549+ @constraint (model, x >= 5 , Disjunct (Y[1 ]))
550+ @constraint (model, x <= 3 , Disjunct (Y[2 ]))
551+ @disjunction (model, Y)
552+ DP. reformulate_model (model, BigM (10.0 ))
553+ InfiniteOpt. build_transformation_backend! (model)
554+ transcribed = InfiniteOpt. transformation_model (model)
555+ n_before = JuMP. num_constraints (transcribed;
556+ count_variable_in_set_constraints = false )
557+ rBM_sol = Dict (x => [1.0 , 2.0 , 3.0 ])
558+ sep_sol = Dict (x => [0.5 , 1.5 , 2.5 ])
559+ DP. add_cut (model, [x], rBM_sol, sep_sol)
560+ n_after = JuMP. num_constraints (transcribed;
561+ count_variable_in_set_constraints = false )
562+ @test n_after == n_before + 1
563+ # set_transformation_backend_ready(true) — next optimize! should
564+ # reuse without re-transcribing (otherwise our cut would be lost)
565+ @test InfiniteOpt. transformation_backend_ready (model)
566+ end
567+
568+ # MBM with finite + integer variables in an InfiniteModel.
569+ function test_mbm_finite_and_integer_var ()
570+ model = InfiniteGDPModel (HiGHS. Optimizer)
571+ set_silent (model)
572+ @infinite_parameter (model, t ∈ [0 , 1 ], num_supports = 10 )
573+ @variable (model, 0 <= x <= 10 , Infinite (t))
574+ @variable (model, 0 <= w <= 5 , Int)
575+ @variable (model, Y[1 : 2 ], InfiniteLogical (t))
576+ @constraint (model, x + w >= 5 , Disjunct (Y[1 ]))
577+ @constraint (model, x + w <= 3 , Disjunct (Y[2 ]))
578+ @disjunction (model, Y)
579+ @objective (model, Min, ∫ (x, t) + w)
580+ @test optimize! (model,
581+ gdp_method = MBM (HiGHS. Optimizer)) isa Nothing
582+ @test termination_status (model) in
583+ [MOI. OPTIMAL, MOI. LOCALLY_SOLVED]
584+ end
585+
516586function test_mbm_infinite_simple ()
517587 model = InfiniteGDPModel (HiGHS. Optimizer)
518588 set_silent (model)
0 commit comments