Skip to content

Commit

Permalink
Add comprehensive tests for Farkas certificates (#1190)
Browse files Browse the repository at this point in the history
  • Loading branch information
odow committed Nov 27, 2020
1 parent 594eb36 commit c424201
Show file tree
Hide file tree
Showing 2 changed files with 326 additions and 0 deletions.
206 changes: 206 additions & 0 deletions src/Test/UnitTests/solve.jl
Expand Up @@ -173,6 +173,212 @@ function solve_result_index(model::MOI.ModelLike, config::TestConfig)
end
unittests["solve_result_index"] = solve_result_index

function solve_farkas_equalto_upper(model::MOI.ModelLike, config::TestConfig)
MOI.empty!(model)
x = MOI.add_variables(model, 2)
clb = MOI.add_constraint.(
model, MOI.SingleVariable.(x), MOI.GreaterThan(0.0)
)
c = MOI.add_constraint(
model,
MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.([2.0, 1.0], x), 0.0),
MOI.EqualTo(-1.0),
)
if config.solve && config.infeas_certificates
MOI.optimize!(model)
@test MOI.get(model, MOI.TerminationStatus()) == MOI.INFEASIBLE
@test MOI.get(model, MOI.DualStatus()) == MOI.INFEASIBILITY_CERTIFICATE
clb_dual = MOI.get.(model, MOI.ConstraintDual(), clb)
c_dual = MOI.get(model, MOI.ConstraintDual(), c)
@test clb_dual[1] > config.atol
@test clb_dual[2] > config.atol
@test c_dual[1] < -config.atol
@test clb_dual [2, 1] .* -c_dual atol=config.atol rtol=config.rtol
end
end
unittests["solve_farkas_equalto_upper"] = solve_farkas_equalto_upper

function solve_farkas_equalto_lower(model::MOI.ModelLike, config::TestConfig)
MOI.empty!(model)
x = MOI.add_variables(model, 2)
clb = MOI.add_constraint.(
model, MOI.SingleVariable.(x), MOI.GreaterThan(0.0)
)
c = MOI.add_constraint(
model,
MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.([-2.0, -1.0], x), 0.0),
MOI.EqualTo(1.0),
)
if config.solve && config.infeas_certificates
MOI.optimize!(model)
@test MOI.get(model, MOI.TerminationStatus()) == MOI.INFEASIBLE
@test MOI.get(model, MOI.DualStatus()) == MOI.INFEASIBILITY_CERTIFICATE
clb_dual = MOI.get.(model, MOI.ConstraintDual(), clb)
c_dual = MOI.get(model, MOI.ConstraintDual(), c)
@test clb_dual[1] > config.atol
@test clb_dual[2] > config.atol
@test c_dual[1] > config.atol
@test clb_dual [2, 1] .* c_dual atol=config.atol rtol=config.rtol
end
end
unittests["solve_farkas_equalto_lower"] = solve_farkas_equalto_lower

function solve_farkas_lessthan(model::MOI.ModelLike, config::TestConfig)
MOI.empty!(model)
x = MOI.add_variables(model, 2)
clb = MOI.add_constraint.(
model, MOI.SingleVariable.(x), MOI.GreaterThan(0.0)
)
c = MOI.add_constraint(
model,
MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.([2.0, 1.0], x), 0.0),
MOI.LessThan(-1.0),
)
if config.solve && config.infeas_certificates
MOI.optimize!(model)
@test MOI.get(model, MOI.TerminationStatus()) == MOI.INFEASIBLE
@test MOI.get(model, MOI.DualStatus()) == MOI.INFEASIBILITY_CERTIFICATE
clb_dual = MOI.get.(model, MOI.ConstraintDual(), clb)
c_dual = MOI.get(model, MOI.ConstraintDual(), c)
@test clb_dual[1] > config.atol
@test clb_dual[2] > config.atol
@test c_dual[1] < -config.atol
@test clb_dual [2, 1] .* -c_dual atol=config.atol rtol=config.rtol
end
end
unittests["solve_farkas_lessthan"] = solve_farkas_lessthan

function solve_farkas_greaterthan(model::MOI.ModelLike, config::TestConfig)
MOI.empty!(model)
x = MOI.add_variables(model, 2)
clb = MOI.add_constraint.(
model, MOI.SingleVariable.(x), MOI.GreaterThan(0.0)
)
c = MOI.add_constraint(
model,
MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.([-2.0, -1.0], x), 0.0),
MOI.GreaterThan(1.0),
)
if config.solve && config.infeas_certificates
MOI.optimize!(model)
@test MOI.get(model, MOI.TerminationStatus()) == MOI.INFEASIBLE
@test MOI.get(model, MOI.DualStatus()) == MOI.INFEASIBILITY_CERTIFICATE
clb_dual = MOI.get.(model, MOI.ConstraintDual(), clb)
c_dual = MOI.get(model, MOI.ConstraintDual(), c)
@test clb_dual[1] > config.atol
@test clb_dual[2] > config.atol
@test c_dual[1] > config.atol
@test clb_dual [2, 1] .* c_dual atol=config.atol rtol=config.rtol
end
end
unittests["solve_farkas_greaterthan"] = solve_farkas_greaterthan

function solve_farkas_interval_upper(model::MOI.ModelLike, config::TestConfig)
MOI.empty!(model)
x = MOI.add_variables(model, 2)
clb = MOI.add_constraint.(
model, MOI.SingleVariable.(x), MOI.GreaterThan(0.0)
)
c = MOI.add_constraint(
model,
MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.([2.0, 1.0], x), 0.0),
MOI.Interval(-2.0, -1.0),
)
if config.solve && config.infeas_certificates
MOI.optimize!(model)
@test MOI.get(model, MOI.TerminationStatus()) == MOI.INFEASIBLE
@test MOI.get(model, MOI.DualStatus()) == MOI.INFEASIBILITY_CERTIFICATE
clb_dual = MOI.get.(model, MOI.ConstraintDual(), clb)
c_dual = MOI.get(model, MOI.ConstraintDual(), c)
@test clb_dual[1] > config.atol
@test clb_dual[2] > config.atol
@test c_dual[1] < -config.atol
@test clb_dual [2, 1] .* -c_dual atol=config.atol rtol=config.rtol
end
end
unittests["solve_farkas_interval_upper"] = solve_farkas_interval_upper

function solve_farkas_interval_lower(model::MOI.ModelLike, config::TestConfig)
MOI.empty!(model)
x = MOI.add_variables(model, 2)
clb = MOI.add_constraint.(
model, MOI.SingleVariable.(x), MOI.GreaterThan(0.0)
)
c = MOI.add_constraint(
model,
MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.([-2.0, -1.0], x), 0.0),
MOI.Interval(1.0, 2.0),
)
if config.solve && config.infeas_certificates
MOI.optimize!(model)
@test MOI.get(model, MOI.TerminationStatus()) == MOI.INFEASIBLE
@test MOI.get(model, MOI.DualStatus()) == MOI.INFEASIBILITY_CERTIFICATE
clb_dual = MOI.get.(model, MOI.ConstraintDual(), clb)
c_dual = MOI.get(model, MOI.ConstraintDual(), c)
@test clb_dual[1] > config.atol
@test clb_dual[2] > config.atol
@test c_dual[1] > config.atol
@test clb_dual [2, 1] .* c_dual atol=config.atol rtol=config.rtol
end
end
unittests["solve_farkas_interval_lower"] = solve_farkas_interval_lower

function solve_farkas_variable_lessthan(model::MOI.ModelLike, config::TestConfig)
MOI.empty!(model)
x = MOI.add_variables(model, 2)
clb = MOI.add_constraint.(
model, MOI.SingleVariable.(x), MOI.LessThan(0.0)
)
c = MOI.add_constraint(
model,
MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.([2.0, 1.0], x), 0.0),
MOI.GreaterThan(1.0),
)
if config.solve && config.infeas_certificates
MOI.optimize!(model)
@test MOI.get(model, MOI.TerminationStatus()) == MOI.INFEASIBLE
@test MOI.get(model, MOI.DualStatus()) == MOI.INFEASIBILITY_CERTIFICATE
clb_dual = MOI.get.(model, MOI.ConstraintDual(), clb)
c_dual = MOI.get(model, MOI.ConstraintDual(), c)
@test clb_dual[1] < -config.atol
@test clb_dual[2] < -config.atol
@test c_dual[1] > config.atol
@test clb_dual [2, 1] .* -c_dual atol=config.atol rtol=config.rtol
end
end
unittests["solve_farkas_variable_lessthan"] = solve_farkas_variable_lessthan

function solve_farkas_variable_lessthan_max(model::MOI.ModelLike, config::TestConfig)
MOI.empty!(model)
x = MOI.add_variables(model, 2)
clb = MOI.add_constraint.(
model, MOI.SingleVariable.(x), MOI.LessThan(0.0)
)
c = MOI.add_constraint(
model,
MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.([2.0, 1.0], x), 0.0),
MOI.GreaterThan(1.0),
)
MOI.set(model, MOI.ObjectiveSense(), MOI.MAX_SENSE)
MOI.set(
model,
MOI.ObjectiveFunction{MOI.SingleVariable}(),
MOI.SingleVariable(x[1]),
)
if config.solve && config.infeas_certificates
MOI.optimize!(model)
@test MOI.get(model, MOI.TerminationStatus()) == MOI.INFEASIBLE
@test MOI.get(model, MOI.DualStatus()) == MOI.INFEASIBILITY_CERTIFICATE
clb_dual = MOI.get.(model, MOI.ConstraintDual(), clb)
c_dual = MOI.get(model, MOI.ConstraintDual(), c)
@test clb_dual[1] < -config.atol
@test clb_dual[2] < -config.atol
@test c_dual[1] > config.atol
@test clb_dual [2, 1] .* -c_dual atol=config.atol rtol=config.rtol
end
end
unittests["solve_farkas_variable_lessthan_max"] = solve_farkas_variable_lessthan_max

function solve_twice(model::MOI.ModelLike, config::TestConfig)
MOI.empty!(model)
x = MOI.add_variable(model)
Expand Down
120 changes: 120 additions & 0 deletions test/Test/unit.jl
Expand Up @@ -49,6 +49,14 @@ end
"solve_single_variable_dual_min",
"solve_single_variable_dual_max",
"solve_result_index",
"solve_farkas_equalto_lower",
"solve_farkas_equalto_upper",
"solve_farkas_lessthan",
"solve_farkas_greaterthan",
"solve_farkas_interval_lower",
"solve_farkas_interval_upper",
"solve_farkas_variable_lessthan",
"solve_farkas_variable_lessthan_max",
"solve_twice",
])
MOI.empty!(model)
Expand Down Expand Up @@ -394,6 +402,118 @@ end
MOIT.solve_result_index(mock, config)
end

@testset "solve_farkas_equalto_upper" begin
MOIU.set_mock_optimize!(mock,
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(
mock,
MOI.INFEASIBLE,
(MOI.NO_SOLUTION, [NaN, NaN]),
MOI.INFEASIBILITY_CERTIFICATE,
(MOI.SingleVariable, MOI.GreaterThan{Float64}) => [2.0, 1.0],
(MOI.ScalarAffineFunction{Float64}, MOI.EqualTo{Float64}) => [-1.0],
)
)
MOIT.solve_farkas_equalto_upper(mock, config)
end

@testset "solve_farkas_equalto_lower" begin
MOIU.set_mock_optimize!(mock,
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(
mock,
MOI.INFEASIBLE,
(MOI.NO_SOLUTION, [NaN, NaN]),
MOI.INFEASIBILITY_CERTIFICATE,
(MOI.SingleVariable, MOI.GreaterThan{Float64}) => [2.0, 1.0],
(MOI.ScalarAffineFunction{Float64}, MOI.EqualTo{Float64}) => [1.0],
)
)
MOIT.solve_farkas_equalto_lower(mock, config)
end

@testset "solve_farkas_lessthan" begin
MOIU.set_mock_optimize!(mock,
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(
mock,
MOI.INFEASIBLE,
(MOI.NO_SOLUTION, [NaN, NaN]),
MOI.INFEASIBILITY_CERTIFICATE,
(MOI.SingleVariable, MOI.GreaterThan{Float64}) => [2.0, 1.0],
(MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}) => [-1.0],
)
)
MOIT.solve_farkas_lessthan(mock, config)
end

@testset "solve_farkas_greaterthan" begin
MOIU.set_mock_optimize!(mock,
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(
mock,
MOI.INFEASIBLE,
(MOI.NO_SOLUTION, [NaN, NaN]),
MOI.INFEASIBILITY_CERTIFICATE,
(MOI.SingleVariable, MOI.GreaterThan{Float64}) => [2.0, 1.0],
(MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}) => [1.0],
)
)
MOIT.solve_farkas_greaterthan(mock, config)
end

@testset "solve_farkas_interval_upper" begin
MOIU.set_mock_optimize!(mock,
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(
mock,
MOI.INFEASIBLE,
(MOI.NO_SOLUTION, [NaN, NaN]),
MOI.INFEASIBILITY_CERTIFICATE,
(MOI.SingleVariable, MOI.GreaterThan{Float64}) => [2.0, 1.0],
(MOI.ScalarAffineFunction{Float64}, MOI.Interval{Float64}) => [-1.0],
)
)
MOIT.solve_farkas_interval_upper(mock, config)
end

@testset "solve_farkas_interval_lower" begin
MOIU.set_mock_optimize!(mock,
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(
mock,
MOI.INFEASIBLE,
(MOI.NO_SOLUTION, [NaN, NaN]),
MOI.INFEASIBILITY_CERTIFICATE,
(MOI.SingleVariable, MOI.GreaterThan{Float64}) => [2.0, 1.0],
(MOI.ScalarAffineFunction{Float64}, MOI.Interval{Float64}) => [1.0],
)
)
MOIT.solve_farkas_interval_lower(mock, config)
end

@testset "solve_farkas_variable_lessthan" begin
MOIU.set_mock_optimize!(mock,
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(
mock,
MOI.INFEASIBLE,
(MOI.NO_SOLUTION, [NaN, NaN]),
MOI.INFEASIBILITY_CERTIFICATE,
(MOI.SingleVariable, MOI.LessThan{Float64}) => [-2.0, -1.0],
(MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}) => [1.0],
)
)
MOIT.solve_farkas_variable_lessthan(mock, config)
end

@testset "solve_farkas_variable_lessthan_max" begin
MOIU.set_mock_optimize!(mock,
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(
mock,
MOI.INFEASIBLE,
(MOI.NO_SOLUTION, [NaN, NaN]),
MOI.INFEASIBILITY_CERTIFICATE,
(MOI.SingleVariable, MOI.LessThan{Float64}) => [-2.0, -1.0],
(MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}) => [1.0],
)
)
MOIT.solve_farkas_variable_lessthan_max(mock, config)
end

@testset "solve_twice" begin
MOIU.set_mock_optimize!(mock,
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(
Expand Down

0 comments on commit c424201

Please sign in to comment.