Condition constraint symbol on problem data

Here is a linear program I am trying to solve:

using JuMP
import GLPK

function LP_example(A::Array{Int64, 2}, B::Array{Int64, 2},
                       c::Array{Int64, 1})
    n, m = size(B)
	model = Model(GLPK.Optimizer)

	# Constraint matrix is totally unimodular so no Bin constraint
    @variable(model, 0 <= x[1:m, 1:n] <= 1)
    @objective(model, Min, sum(x .* A))

	if m <= n
    	@constraints(model, begin
	        smile[i in 1:n], sum(x[:, i]) <= 1			# Toggle these inequalities
	        frown[j in 1:m], sum(x[j, :]) == c[j]		# depending on whether m <= n
		end)
	else
		@constraints(model, begin
	        smile[i in 1:n], sum(x[:, i]) == 1		 	#
	        frown[j in 1:m], sum(x[j, :]) >= c[j]		#
		end)
    end

    optimize!(model)
	out = value.(x)

	# Also, is this the best way to double-check that soln is binary?
	@assert isempty(filter(x -> !(round(x, digits=5) in [0, 1]), out)) "Solution not integral"

    return out
end

In the if m <= n block, the constraints are nearly identical, and the only difference is that the inequality and equality constraints switch signs.

Is there a way to avoid repeating the constraint expressions by conditioning around the comparison symbol only? Something like

smile[i in 1:n], sum(x[:, i]) (m <= n) ? (<=) : (==) 1

The if statement is fine. Alternatively, you could do something like:

m, n = 3, 2
model = Model()
@variable(model, x[1:m, 1:n])
c = rand(m)  # Make sure `c` is `Vector{Float64}`!
set_smile = m <= n ? MOI.LessThan(1.0) : MOI.EqualTo(1.0)
set_frown(j) = m <= n ? MOI.EqualTo(c[j]) : MOI.GreaterThan(c[j])
@constraints(model, begin
    smile[i=1:n], sum(x[:, i]) in set_smile
    frown[j=1:m], sum(x[j, :]) in set_frown(j)
end)

For checking whether something is binary, you could use

function is_binary(x; atol=1e-8)
    return isapprox(x, 0; atol=atol) || isapprox(x, 1; atol=atol)
end

@assert all(is_binary, out)
1 Like