Skip to content

Commit

Permalink
add checks to logical propositions to disallow propositions with only…
Browse files Browse the repository at this point in the history
… 1 logical variable
  • Loading branch information
hdavid16 committed Oct 30, 2023
1 parent b26e1ed commit 642e12b
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 43 deletions.
13 changes: 11 additions & 2 deletions src/constraints.jl
Original file line number Diff line number Diff line change
Expand Up @@ -493,14 +493,23 @@ end

# Check that logical expression is valid
function _check_logical_expression(ex)
_check_logical_expression_literal(ex)
_check_logical_expression_operator(ex)
end
function _check_logical_expression_literal(ex::_LogicalExpr)
if _isa_literal(ex)
error("Cannot define constraint on single logical variable, use `fix` instead.")
end
end
function _check_logical_expression_operator(ex)
return
end
function _check_logical_expression(ex::_LogicalExpr)
function _check_logical_expression_operator(ex::_LogicalExpr)
if !(ex.head in _LogicalOperatorHeads)
error("Unrecognized logical operator `$(ex.head)`.")
end
for a in ex.args
_check_logical_expression(a)
_check_logical_expression_operator(a)
end
return
end
Expand Down
43 changes: 2 additions & 41 deletions test/constraints/proposition.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ function test_proposition_add_fail()
m = GDPModel()
@variable(m, y[1:3], Logical)
@test_throws ErrorException @constraint(m, y[1] := true)
@test_throws ErrorException @constraint(m, ¬y[1] := true)
@test_throws ErrorException @constraint(m, logical_not(y[1]) := true)
@test_throws ErrorException @constraint(Model(), logical_or(y...) := true)
@test_throws ErrorException @constraint(m, logical_or(y...) == 2)
@test_throws ErrorException @constraint(m, logical_or(y...) <= 1)
Expand All @@ -22,33 +24,6 @@ function test_proposition_add_fail()
@test_throws AssertionError add_constraint(m, ScalarConstraint(logical_or(y...), MOI.LessThan(42)))
end

function test_negation_add_success()
model = GDPModel()
@variable(model, y, Logical)
c1 = @constraint(model, logical_not(y) := true)
@constraint(model, c2, ¬y := true)
@test is_valid(model, c1)
@test is_valid(model, c2)
@test owner_model(c1) == model
@test owner_model(c2) == model
@test name(c1) == ""
@test name(c2) == "c2"
@test index(c1) == LogicalConstraintIndex(1)
@test index(c2) == LogicalConstraintIndex(2)
@test haskey(DP._logical_constraints(model), index(c1))
@test haskey(DP._logical_constraints(model), index(c2))
@test DP._logical_constraints(model)[index(c1)] == DP._constraint_data(c1)
@test constraint_object(c1).func isa DP._LogicalExpr
@test constraint_object(c2).func isa DP._LogicalExpr
@test constraint_object(c1).func.head ==
constraint_object(c2).func.head == :!
@test constraint_object(c1).func.args ==
constraint_object(c2).func.args == Any[y]
@test constraint_object(c1).set ==
constraint_object(c2).set == MOI.EqualTo{Bool}(true)
@test c1 == copy(c1)
end

function test_implication_add_success()
model = GDPModel()
@variable(model, y[1:2], Logical)
Expand Down Expand Up @@ -168,18 +143,6 @@ function test_proposition_delete()
@test !DP._ready_to_optimize(model)
end

function test_negation_reformulation()
model = GDPModel()
@variable(model, y, Logical)
@constraint(model, ¬y := true)
reformulate_model(model, DummyReformulation())
ref_con = DP._reformulation_constraints(model)[1]
@test is_valid(model, ref_con)
ref_con_obj = constraint_object(ref_con)
@test ref_con_obj.set == MOI.GreaterThan(0.0)
@test ref_con_obj.func == -DP._indicator_to_binary(model)[y]
end

function test_implication_reformulation()
model = GDPModel()
@variable(model, y[1:2], Logical)
Expand Down Expand Up @@ -530,7 +493,6 @@ end
end
@testset "Add Proposition" begin
test_proposition_add_fail()
test_negation_add_success()
test_implication_add_success()
test_equivalence_add_success()
test_intersection_and_flatten_add_success()
Expand All @@ -540,7 +502,6 @@ end
test_proposition_add_sparse_axis()
end
@testset "Reformulate Proposition" begin
test_negation_reformulation()
test_implication_reformulation()
test_implication_reformulation_fail()
test_equivalence_reformulation()
Expand Down

0 comments on commit 642e12b

Please sign in to comment.