diff --git a/src/JuMP.jl b/src/JuMP.jl index cb13acbafbb..2f320f18035 100644 --- a/src/JuMP.jl +++ b/src/JuMP.jl @@ -1103,6 +1103,7 @@ include("operators.jl") include("sd.jl") include("sets.jl") include("solution_summary.jl") +include("inequality.jl") # print.jl must come last, because it uses types defined in earlier files. include("print.jl") diff --git a/src/inequality.jl b/src/inequality.jl new file mode 100644 index 00000000000..300b87584dc --- /dev/null +++ b/src/inequality.jl @@ -0,0 +1,57 @@ +# Copyright 2017, Iain Dunning, Joey Huchette, Miles Lubin, and contributors +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at https://mozilla.org/MPL/2.0/. + +function _build_inequality_constraint( + error_fn::Function, + vectorized::Bool, + lhs::VariableRef, + rhs::VariableRef, +) + +function _build_inequality_constraint( + error_fn::Function, + vectorized::Bool, + lhs::Vector{VariableRef}, + rhs::Vector{VariableRef}, +) + if !vectorized + error_fn( + "Ineqality operator with vector operands must be explicitly vectorized, use `.!=` instead of `!=`.", + ) + end + if length(lhs) != length(rhs) + error_fn("Operand length mismatch, $(length(lhs)) vs $(length(rhs)).",) + end + lhs = _desparsify(lhs) + rhs = _desparsify(rhs) + return _build_inequality_constraint.(error_fn, false, lhs, rhs) +end + +function parse_constraint_call( + error_fn::Function, + vectorized::Bool, + ::Val{:(!=)}, + lhs, + rhs, +) + build_call = Expr( + :call, + :_build_inequality_constraint, + error_fn, + vectorized, + esc(lhs), + esc(rhs), + ) + return nothing, build_call +end + +function constraint_string( + print_mode, + constraint::VectorConstraint{F,<:MOI.AllDifferent}, +) where {F} + lhs = function_string(print_mode, constraint.func[1]) + rhs = function_string(print_mode, constraint.func[2]) + return string(lhs, " != ", rhs) +end diff --git a/src/macros/@constraint.jl b/src/macros/@constraint.jl index bc0feeb03a8..40df474e9f4 100644 --- a/src/macros/@constraint.jl +++ b/src/macros/@constraint.jl @@ -20,7 +20,7 @@ The expression `expr` may be one of following forms: which is either a [`MOI.AbstractSet`](@ref) or one of the JuMP shortcuts like [`SecondOrderCone`](@ref) or [`PSDCone`](@ref) - * `a b`, where `` is one of `==`, `≥`, `>=`, `≤`, `<=` + * `a b`, where `` is one of `==`, `!=`, `≥`, `>=`, `≤`, `<=` * `l <= f <= u` or `u >= f >= l`, constraining the expression `f` to lie between `l` and `u` @@ -233,6 +233,7 @@ The entry-point for all constraint-related parsing. JuMP currently supports the following `expr` objects: * `lhs <= rhs` * `lhs == rhs` + * `lhs != rhs` * `lhs >= rhs` * `l <= body <= u` * `u >= body >= l` @@ -259,7 +260,7 @@ end function parse_constraint(error_fn::Function, arg) return error_fn( "Incomplete constraint specification $arg. Are you missing a " * - "comparison (<=, >=, or ==)?", + "comparison (<=, >=, == or !=)?", ) end @@ -591,7 +592,7 @@ julia> @constraint(model, A * x == b) """ struct Zeros end -operator_to_set(::Function, ::Val{:(==)}) = Zeros() +operator_to_set(::Function, ::Union{Val{:(==)},Val{:(!=)}}) = Zeros() """ parse_constraint_call(