Skip to content

Commit 6e6c373

Browse files
committed
add infeasibility tests
1 parent 5a10ced commit 6e6c373

File tree

2 files changed

+145
-2
lines changed

2 files changed

+145
-2
lines changed

src/infeasibility.jl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,9 @@ function ModelAnalyzer.analyze(
261261
end
262262
iis = iis_elastic_filter(model, optimizer)
263263
# for now, only one iis is computed
264-
push!(out.iis, IrreducibleInfeasibleSubset(iis))
264+
if iis !== nothing
265+
push!(out.iis, IrreducibleInfeasibleSubset(iis))
266+
end
265267

266268
return out
267269
end
@@ -278,7 +280,7 @@ function iis_elastic_filter(original_model::JuMP.GenericModel, optimizer)
278280
println(
279281
"iis resolver cannot continue because model is found to be $(status) by the solver",
280282
)
281-
return
283+
return nothing
282284
end
283285

284286
model, reference_map = JuMP.copy_model(original_model)

test/infeasibility.jl

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,31 @@ function test_bounds()
3434
@test length(ret) == 1
3535
@test ret[] ==
3636
ModelAnalyzer.Infeasibility.InfeasibleBounds{Float64}(y, 2.0, 1.0)
37+
#
38+
buf = IOBuffer()
39+
ModelAnalyzer.summarize(
40+
buf,
41+
ModelAnalyzer.Infeasibility.InfeasibleBounds{Float64},
42+
)
43+
str = String(take!(buf))
44+
@test startswith(str, "# `InfeasibleBounds`")
45+
ModelAnalyzer.summarize(
46+
buf,
47+
ModelAnalyzer.Infeasibility.InfeasibleBounds{Float64},
48+
verbose = false,
49+
)
50+
str = String(take!(buf))
51+
@test str == "# InfeasibleBounds"
52+
#
53+
ModelAnalyzer.summarize(buf, ret[1], verbose = true)
54+
str = String(take!(buf))
55+
@test startswith(str, "Variable: ")
56+
@test contains(str, " with lower bound ")
57+
@test contains(str, " and upper bound ")
58+
ModelAnalyzer.summarize(buf, ret[1], verbose = false)
59+
str = String(take!(buf))
60+
@test contains(str, " : ")
61+
@test contains(str, " !<= ")
3762
return
3863
end
3964

@@ -54,6 +79,33 @@ function test_integrality()
5479
2.9,
5580
MOI.Integer(),
5681
)
82+
#
83+
buf = IOBuffer()
84+
ModelAnalyzer.summarize(
85+
buf,
86+
ModelAnalyzer.Infeasibility.InfeasibleIntegrality{Float64},
87+
)
88+
str = String(take!(buf))
89+
@test startswith(str, "# `InfeasibleIntegrality`")
90+
ModelAnalyzer.summarize(
91+
buf,
92+
ModelAnalyzer.Infeasibility.InfeasibleIntegrality{Float64},
93+
verbose = false,
94+
)
95+
str = String(take!(buf))
96+
@test str == "# InfeasibleIntegrality"
97+
#
98+
ModelAnalyzer.summarize(buf, ret[1], verbose = true)
99+
str = String(take!(buf))
100+
@test startswith(str, "Variable: ")
101+
@test contains(str, " with lower bound ")
102+
@test contains(str, " and upper bound ")
103+
@test contains(str, " and integrality constraint: ")
104+
ModelAnalyzer.summarize(buf, ret[1], verbose = false)
105+
str = String(take!(buf))
106+
@test contains(str, " : [")
107+
@test contains(str, "; ")
108+
@test contains(str, "], ")
57109
return
58110
end
59111

@@ -95,9 +147,95 @@ function test_range()
95147
22.0,
96148
MOI.LessThan{Float64}(1.0),
97149
)
150+
#
151+
buf = IOBuffer()
152+
ModelAnalyzer.summarize(
153+
buf,
154+
ModelAnalyzer.Infeasibility.InfeasibleConstraintRange{Float64},
155+
)
156+
str = String(take!(buf))
157+
@test startswith(str, "# `InfeasibleConstraintRange`")
158+
ModelAnalyzer.summarize(
159+
buf,
160+
ModelAnalyzer.Infeasibility.InfeasibleConstraintRange{Float64},
161+
verbose = false,
162+
)
163+
str = String(take!(buf))
164+
@test str == "# InfeasibleConstraintRange"
165+
#
166+
ModelAnalyzer.summarize(buf, ret[1], verbose = true)
167+
str = String(take!(buf))
168+
@test startswith(str, "Constraint: ")
169+
@test contains(str, " with computed lower bound ")
170+
@test contains(str, " and computed upper bound ")
171+
@test contains(str, " and set: ")
172+
ModelAnalyzer.summarize(buf, ret[1], verbose = false)
173+
str = String(take!(buf))
174+
@test contains(str, " : [")
175+
@test contains(str, "; ")
176+
@test contains(str, "], !in ")
177+
return
178+
end
179+
180+
function test_range_greaterthan()
181+
model = Model()
182+
@variable(model, 10 <= x <= 11)
183+
@variable(model, 1 <= y <= 11)
184+
@constraint(model, c, x + y >= 100)
185+
@objective(model, Max, x + y)
186+
data = ModelAnalyzer.analyze(ModelAnalyzer.Infeasibility.Analyzer(), model)
187+
list = ModelAnalyzer.list_of_issue_types(data)
188+
@test length(list) == 1
189+
ret = ModelAnalyzer.list_of_issues(data, list[1])
190+
@test length(ret) == 1
191+
@test ret[] ==
192+
ModelAnalyzer.Infeasibility.InfeasibleConstraintRange{Float64}(
193+
c,
194+
11.0,
195+
22.0,
196+
MOI.GreaterThan{Float64}(100.0),
197+
)
98198
return
99199
end
100200

201+
function test_range_equalto()
202+
model = Model()
203+
@variable(model, 10 <= x <= 11)
204+
@variable(model, 1 <= y <= 11)
205+
@constraint(model, c, x + y == 100)
206+
@objective(model, Max, x + y)
207+
data = ModelAnalyzer.analyze(ModelAnalyzer.Infeasibility.Analyzer(), model)
208+
list = ModelAnalyzer.list_of_issue_types(data)
209+
@test length(list) == 1
210+
ret = ModelAnalyzer.list_of_issues(data, list[1])
211+
@test length(ret) == 1
212+
@test ret[] ==
213+
ModelAnalyzer.Infeasibility.InfeasibleConstraintRange{Float64}(
214+
c,
215+
11.0,
216+
22.0,
217+
MOI.EqualTo{Float64}(100.0),
218+
)
219+
return
220+
end
221+
222+
function test_iis_feasible()
223+
model = Model(HiGHS.Optimizer)
224+
set_silent(model)
225+
@variable(model, 0 <= x <= 10)
226+
@variable(model, 0 <= y <= 20)
227+
@constraint(model, c1, x + y <= 1)
228+
@objective(model, Max, x + y)
229+
optimize!(model)
230+
data = ModelAnalyzer.analyze(
231+
ModelAnalyzer.Infeasibility.Analyzer(),
232+
model,
233+
optimizer = HiGHS.Optimizer,
234+
)
235+
list = ModelAnalyzer.list_of_issue_types(data)
236+
@test length(list) == 0
237+
end
238+
101239
function test_iis()
102240
model = Model(HiGHS.Optimizer)
103241
set_silent(model)
@@ -107,6 +245,9 @@ function test_iis()
107245
@constraint(model, c2, x + y >= 2)
108246
@objective(model, Max, x + y)
109247
optimize!(model)
248+
data = ModelAnalyzer.analyze(ModelAnalyzer.Infeasibility.Analyzer(), model)
249+
list = ModelAnalyzer.list_of_issue_types(data)
250+
@test length(list) == 0
110251
data = ModelAnalyzer.analyze(
111252
ModelAnalyzer.Infeasibility.Analyzer(),
112253
model,

0 commit comments

Comments
 (0)