Skip to content

Support of nonlinear constraints? #216

Open
@hakank

Description

@hakank

Are there plan to support general nonlinear constraints (in the future)?

Coming from constraint programming systems such as MiniZinc, Picat, Gecode, OR-tools, etc, I'm quite used to - and spoiled with - nonlinear constraints. But what I can see, there is no support at all in ConstraintSolver.jl for nonlinear constraints which is - I assume - because JuMP don't handle general nonlinear constraint what I know. And it seems that ConstraintSolver.jl don' support quadratic constraints either.

Here's a simple (and contrived) example which yield the following error:
MOI.ScalarQuadraticFunction{Float64}-in-'MOI.GreaterThan{Float64}' constraints are not supported and cannot be bridged into supported constrained variables and constraints. See details below: ....

# ....
    @variable(model, 1 <= x[1:n] <= n, Int)
    @variable(model, b1[1:n], Bin)

    for i in 1:n
        @constraint(model, b1[i] := {x[i] <= i})
        @constraint(model, b1[i]*x[i] >= 1)

    end

# ...

And the following constraint yield Cannot multiply a quadratic expression by a variable

   # ...
     @constraint(model, b1[i]*x[i]*x[i] >= 1)
   # ...

I know that many/most nonlinear constraint can be reformulated using a lot of binary variables instead, but I would really prefer to use "traditional" nonlinear constraints, especially when trying to translate (decompose) global constraints.

Here's a more realistic example: modelling the cumulative global constraint (adapted from MiniZinc's cumulative function)

function cumulative(model, start, duration, resource, b)

    tasks = [i for i in 1:length(start) if resource[i] > 0 && duration[i] > 0]
    num_tasks = length(tasks)

    # upper and lower limits of start times
    times_min_a = round.(Int,[JuMP.lower_bound(start[i]) for i in tasks])
    times_min = minimum(times_min_a)
    times_max_a = round.(Int,[JuMP.upper_bound(start[i]) for i in tasks])
    times_max = minimum(times_max_a)

    for t in times_min:times_max + 1
        bs = @variable(model, [1:num_tasks], Bin)
        bt = @variable(model, [1:num_tasks], Bin)
        for i in tasks
            # This don't work: Throws: `no method matching isless(::VariableRef, ::Int64)`
            # Hence the use of indicators.
            # @constraint(model,sum([(start[i] <= t) * (t <= start[i] + duration[i])*resource[i] for i in tasks])  <= b)

            # Using indicators instead:
            @constraint(model, bs[i] := {start[i] <= t})
            @constraint(model, bt[i] := {t <= start[i]})
            # This throws MOI.ScalarQuadraticFunction ... error
            @constraint(model,sum([bs[i] * (bt[i] + duration[i])*resource[i] for i in tasks]) <= b)
        end
  end
end

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions