Use this function if nonlinear expression in vector

60 Views Asked by At

I have a vector a that can contain several different types of elements of the expressions QuadExpr, NonlinearExpression, AffExpr, VariableRef. However, I want that if one of the elements (expressions) in a is a NonlinearExpression or a QuadExpression this function should be used:

function add_pen!(pen, model::JuMP.Model, a::Union{Vector{QuadExpr}, Vector{NonlinearExpression}}, b, i,len) 
    
        pen[i] = @NLexpression(model, sum(a[j] * b[j] for j in 1:len)); 
    end

If a contains neither NonlinearExpression nor QuadExpression this function should be used:

function add_pen!(pen, model::JuMP.Model, a, b, i,len) 
    
        pen[i] = @expression(model, sum(a[j] * b[j] for j in 1:len)); 
    end

I know this will not work as a::Union{Vector{QuadExpr}, Vector{NonlinearExpression}} means that a is either a Vector of only QuadExpression or NonlinearExpressions. Is it possible to use multiple-dispatch functions in this case or do I need to use the if and else statements instead? Like,

if any(x -> typeof(x) == NonlinearExpression, a)
   pen[i] = @NLexpression ...
end
1

There are 1 best solutions below

6
Przemyslaw Szufel On BEST ANSWER

You could dispatch on types of varargs.
I will make the example code without JuMP so it is easier to replicate (you can of course change to your JuMP types).

Consider the following two types:

TypesA = Union{Int,Float64,Rational{Int}}
TypesB = Union{TypesA,String,Char}

You can define the following functions:

g(a::TypesA...) = println("running A")
g(a::TypesB...) = println("running B")

Now let us test it:

julia> g([1,2,3//4]...)
running A

julia> g([1,2,3//4,"hello"]...)
running B

You can see that varags makes it possible to dispatch on the various combination of Vector elements. Note that this works correctly regardless the fact the the type of elements of Vector above is Any:

julia> eltype([1,2,3//4,"hello"])
Any

In your add_pen! you will need to move a to the end to be the last parameter.