|  | 
| 175 | 175 |     @test pre_optimize_called == 1 | 
| 176 | 176 |     @test post_optimize_called == 3 | 
| 177 | 177 | end | 
|  | 178 | + | 
|  | 179 | +@testset "relax_integrality and enforce_integrality" begin | 
|  | 180 | +    model = SDDP.LinearPolicyGraph( | 
|  | 181 | +        stages = 2, lower_bound = 0.0, | 
|  | 182 | +        direct_mode = false | 
|  | 183 | +    ) do sp, t | 
|  | 184 | +        @variable(sp, x, SDDP.State, initial_value = 2.0) | 
|  | 185 | +        @variable(sp, b1, Bin) | 
|  | 186 | +        @variable(sp, 0.2 <= b2, Bin) | 
|  | 187 | +        @variable(sp, 0.5 <= b3 <= 1.2, Bin) | 
|  | 188 | +        @variable(sp, i1, Int) | 
|  | 189 | +        @variable(sp, 6.2 >= i2, Int) | 
|  | 190 | +        @variable(sp, -8 <= i3 <= 2, Int) | 
|  | 191 | +        @stageobjective(sp, b1 + b2 + b2 + i3 + i1) | 
|  | 192 | +    end | 
|  | 193 | + | 
|  | 194 | +    for node in [model[1], model[2]] | 
|  | 195 | +        @test JuMP.is_binary(node.subproblem[:b1]) | 
|  | 196 | +        @test !JuMP.has_lower_bound(node.subproblem[:b1]) | 
|  | 197 | +        @test !JuMP.has_upper_bound(node.subproblem[:b1]) | 
|  | 198 | + | 
|  | 199 | +        @test JuMP.is_binary(node.subproblem[:b2]) | 
|  | 200 | +        @test JuMP.lower_bound(node.subproblem[:b2]) == 0.2 | 
|  | 201 | +        @test !JuMP.has_upper_bound(node.subproblem[:b2]) | 
|  | 202 | + | 
|  | 203 | +        @test JuMP.is_binary(node.subproblem[:b3]) | 
|  | 204 | +        @test JuMP.lower_bound(node.subproblem[:b3]) == 0.5 | 
|  | 205 | +        @test JuMP.upper_bound(node.subproblem[:b3]) == 1.2 | 
|  | 206 | + | 
|  | 207 | +        @test JuMP.is_integer(node.subproblem[:i1]) | 
|  | 208 | +        @test !JuMP.has_lower_bound(node.subproblem[:i1]) | 
|  | 209 | +        @test !JuMP.has_upper_bound(node.subproblem[:i1]) | 
|  | 210 | + | 
|  | 211 | +        @test JuMP.is_integer(node.subproblem[:i2]) | 
|  | 212 | +        @test JuMP.upper_bound(node.subproblem[:i2]) == 6.2 | 
|  | 213 | +        @test !JuMP.has_lower_bound(node.subproblem[:i2]) | 
|  | 214 | + | 
|  | 215 | +        @test JuMP.is_integer(node.subproblem[:i3]) | 
|  | 216 | +        @test JuMP.lower_bound(node.subproblem[:i3]) == -8 | 
|  | 217 | +        @test JuMP.upper_bound(node.subproblem[:i3]) == 2 | 
|  | 218 | +    end | 
|  | 219 | +    binaries, integers = SDDP.relax_integrality(model) | 
|  | 220 | +    for node in [model[1], model[2]] | 
|  | 221 | +        @test !JuMP.is_binary(node.subproblem[:b1]) | 
|  | 222 | +        @test JuMP.lower_bound(node.subproblem[:b1]) == 0.0 | 
|  | 223 | +        @test JuMP.upper_bound(node.subproblem[:b1]) == 1.0 | 
|  | 224 | + | 
|  | 225 | +        @test !JuMP.is_binary(node.subproblem[:b2]) | 
|  | 226 | +        @test JuMP.lower_bound(node.subproblem[:b2]) == 0.2 | 
|  | 227 | +        @test JuMP.upper_bound(node.subproblem[:b2]) == 1.0 | 
|  | 228 | + | 
|  | 229 | +        @test !JuMP.is_binary(node.subproblem[:b3]) | 
|  | 230 | +        @test JuMP.lower_bound(node.subproblem[:b3]) == 0.5 | 
|  | 231 | +        @test JuMP.upper_bound(node.subproblem[:b3]) == 1.0 | 
|  | 232 | + | 
|  | 233 | +        @test !JuMP.is_integer(node.subproblem[:i1]) | 
|  | 234 | +        @test !JuMP.has_lower_bound(node.subproblem[:i1]) | 
|  | 235 | +        @test !JuMP.has_upper_bound(node.subproblem[:i1]) | 
|  | 236 | + | 
|  | 237 | +        @test !JuMP.is_integer(node.subproblem[:i2]) | 
|  | 238 | +        @test JuMP.upper_bound(node.subproblem[:i2]) == 6.2 | 
|  | 239 | +        @test !JuMP.has_lower_bound(node.subproblem[:i2]) | 
|  | 240 | + | 
|  | 241 | +        @test !JuMP.is_integer(node.subproblem[:i3]) | 
|  | 242 | +        @test JuMP.lower_bound(node.subproblem[:i3]) == -8 | 
|  | 243 | +        @test JuMP.upper_bound(node.subproblem[:i3]) == 2 | 
|  | 244 | +    end | 
|  | 245 | +    SDDP.enforce_integrality(binaries, integers) | 
|  | 246 | +    for node in [model[1], model[2]] | 
|  | 247 | +        @test JuMP.is_binary(node.subproblem[:b1]) | 
|  | 248 | +        @test !JuMP.has_lower_bound(node.subproblem[:b1]) | 
|  | 249 | +        @test !JuMP.has_upper_bound(node.subproblem[:b1]) | 
|  | 250 | + | 
|  | 251 | +        @test JuMP.is_binary(node.subproblem[:b2]) | 
|  | 252 | +        @test JuMP.lower_bound(node.subproblem[:b2]) == 0.2 | 
|  | 253 | +        @test !JuMP.has_upper_bound(node.subproblem[:b2]) | 
|  | 254 | + | 
|  | 255 | +        @test JuMP.is_binary(node.subproblem[:b3]) | 
|  | 256 | +        @test JuMP.lower_bound(node.subproblem[:b3]) == 0.5 | 
|  | 257 | +        @test JuMP.upper_bound(node.subproblem[:b3]) == 1.2 | 
|  | 258 | + | 
|  | 259 | +        @test JuMP.is_integer(node.subproblem[:i1]) | 
|  | 260 | +        @test !JuMP.has_lower_bound(node.subproblem[:i1]) | 
|  | 261 | +        @test !JuMP.has_upper_bound(node.subproblem[:i1]) | 
|  | 262 | + | 
|  | 263 | +        @test JuMP.is_integer(node.subproblem[:i2]) | 
|  | 264 | +        @test JuMP.upper_bound(node.subproblem[:i2]) == 6.2 | 
|  | 265 | +        @test !JuMP.has_lower_bound(node.subproblem[:i2]) | 
|  | 266 | + | 
|  | 267 | +        @test JuMP.is_integer(node.subproblem[:i3]) | 
|  | 268 | +        @test JuMP.lower_bound(node.subproblem[:i3]) == -8 | 
|  | 269 | +        @test JuMP.upper_bound(node.subproblem[:i3]) == 2 | 
|  | 270 | +    end | 
|  | 271 | +end | 
0 commit comments