Skip to content

Commit 22fbb81

Browse files
committed
more tests
1 parent 10807d5 commit 22fbb81

File tree

2 files changed

+65
-12
lines changed

2 files changed

+65
-12
lines changed

src/dual_feasibility_checker.jl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,13 @@
33
# Use of this source code is governed by an MIT-style license that can be found
44
# in the LICENSE.md file or at https://opensource.org/licenses/MIT.
55

6+
# TODO
7+
# 1 - JuMP: primal_feasibility_report should have a typed error for not found stuff so we can capture
8+
# 2 - Dualization: should consider and option to dont treat @variable(m, x >= 0) differently from @variable(m, x >= 1)
9+
# 3 - Dualization: JuMP model dualization should hold the primal dual map, maybe a JuMP converted version
10+
# 4 - Dualization: Primal dual map could work with a getindex for simpler usage
11+
12+
613
function _last_dual_solution(model::GenericModel{T}) where {T}
714
if !has_duals(model)
815
error(

test/dual_feasibility_checker.jl

Lines changed: 58 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ function runtests()
2020
end
2121
return
2222
end
23-
#=
23+
2424
function test_no_solution()
2525
model = Model()
2626
@variable(model, x, Bin)
@@ -32,7 +32,6 @@ function test_no_solution()
3232
# no dual solutions available
3333
@test_throws ErrorException ModelAnalyzer.dual_feasibility_report(model)
3434
end
35-
=#
3635

3736
function test_only_bounds()
3837
# in this case the dual has no varaibles and has innocuous constraints
@@ -49,7 +48,7 @@ function test_only_bounds()
4948
@test isempty(report)
5049
end
5150

52-
function test_simple()
51+
function test_no_lb()
5352
model = Model()
5453
@variable(model, x)
5554
@constraint(model, c, x >= 0)
@@ -65,28 +64,52 @@ function test_simple()
6564
@test isempty(report)
6665
report = ModelAnalyzer.dual_feasibility_report(model, Dict(c => [1.0]))
6766
@test isempty(report)
68-
@show report =
67+
report =
6968
ModelAnalyzer.dual_feasibility_report(model, Dict(c => [3.3]))
7069
@test report[x] == 2.3
70+
@test length(report) == 1
7171
end
7272

73-
function test_simple2()
73+
function test_lb0()
7474
model = Model()
7575
@variable(model, x >= 0)
7676
@constraint(model, c, x >= 0.5)
7777
@objective(model, Min, x)
7878
# the dual is:
79-
# Max 0
79+
# Max 0.5 * y
8080
# Subject to
81-
# y == 1 (as a constraint) # from x, a free "bounded" varaible
82-
# y >= 0 (as a bound) # from c, a ">=" constraint
83-
# mayber force fail here
84-
# @test_throws ErrorException
81+
# - y >= -1 (as a constraint) # from x >= 0 (bound)
82+
# y >= 0 (as a bound) # from c, a ">=" constraint
8583
report = ModelAnalyzer.dual_feasibility_report(
8684
model,
87-
Dict(c => 1.0, LowerBoundRef(x) => 0.0),
85+
Dict(c => [1.0], LowerBoundRef(x) => [0.0]),
8886
)
8987
@test isempty(report)
88+
report = ModelAnalyzer.dual_feasibility_report(
89+
model,
90+
Dict(c => [3.3], LowerBoundRef(x) => [0.0]),
91+
)
92+
@test report[LowerBoundRef(x)] == 2.3
93+
@test length(report) == 1
94+
report = ModelAnalyzer.dual_feasibility_report(
95+
model,
96+
Dict(c => [-3.3], LowerBoundRef(x) => [0.0]),
97+
)
98+
@test report[c] == 3.3
99+
@test length(report) == 1
100+
end
101+
102+
function test_lb2()
103+
model = Model()
104+
@variable(model, x >= 2)
105+
@constraint(model, c, x >= 0.5)
106+
@objective(model, Min, x)
107+
# the dual is:
108+
# Max 0.5 * y + 2 * z
109+
# Subject to
110+
# y + z == 1 (as a constraint) # from x, a free variable (bound is considered below)
111+
# z >= 0 (as a bound) # from the "constraint" x >= 2 (bound in the above example)
112+
# y >= 0 (as a bound) # from c, a ">=" constraint
90113
report = ModelAnalyzer.dual_feasibility_report(
91114
model,
92115
Dict(c => [1.0], LowerBoundRef(x) => [0.0]),
@@ -96,7 +119,30 @@ function test_simple2()
96119
model,
97120
Dict(c => [3.3], LowerBoundRef(x) => [0.0]),
98121
)
99-
@test report[LowerBoundRef(x)] == 2.3
122+
@test report[x] == 2.3
123+
@test length(report) == 1
124+
report = ModelAnalyzer.dual_feasibility_report(
125+
model,
126+
Dict(c => [-3.3], LowerBoundRef(x) => [0.0]),
127+
)
128+
@test report[x] == 4.3
129+
@test report[c] == 3.3
130+
@test length(report) == 2
131+
report = ModelAnalyzer.dual_feasibility_report(
132+
model,
133+
Dict(c => [-3.3], LowerBoundRef(x) => [-1.0]),
134+
)
135+
@test report[x] == 5.3
136+
@test report[c] == 3.3
137+
@test report[LowerBoundRef(x)] == 1.0
138+
@test length(report) == 3
139+
report = ModelAnalyzer.dual_feasibility_report(
140+
model,
141+
Dict(c => [-3.3]),
142+
skip_missing = true,
143+
)
144+
@test report[c] == 3.3
145+
@test length(report) == 1
100146
end
101147

102148
end # module

0 commit comments

Comments
 (0)