typesjuliamultiple-dispatch

Use this function if nonlinear expression in vector


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

Solution

  • 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.