diff --git a/extras/glpk.jl b/extras/glpk.jl index 8487a8ac18f7a..d9e542d2d378c 100644 --- a/extras/glpk.jl +++ b/extras/glpk.jl @@ -2,8 +2,6 @@ ### GLPK API Wrapper ### -# Note: be sure to load "sparse.jl" before this file - ## Shared library interface setup #{{{ load("glpk_h.jl") @@ -128,10 +126,21 @@ end # In this framework, optional arguments can be passed either # as an empty vector [] or as the 'nothing' constant -typealias VecOrNothing{T} Union(AbstractVector{T}, AbstractVector{None}, Nothing) -typealias MatOrNothing{T} Union(AbstractMatrix{T}, AbstractVector{None}, Nothing) -_jl_glpk__is_empty{T}(x::Union(VecOrNothing{T}, MatOrNothing{T})) = - isa(x, Union(AbstractVector{None}, Nothing)) +typealias VecOrNothing Union(Vector, Nothing) +function _jl_glpk__convert_vecornothing{T}(::Type{T}, a::VecOrNothing) + if (a == nothing) || (isa(a, Array{Any}) && isempty(a)) + return T[] + elseif T <: Integer + if !(eltype(a) <: Integer) + throw(GLPError("integer-valued array required, or [] or nothing")) + end + elseif T <: Real + if !(eltype(a) <: Real) + throw(GLPError("real-valued array required, or [] or nothing")) + end + end + convert(Array{T}, a) +end # General exception: all GLP functions # throw this in case of errors @@ -431,7 +440,7 @@ function _jl_glpk__check_vectors_size(numel::Integer, vecs...) end if numel > 0 for v = vecs - if _jl_glpk__is_empty(v) + if isempty(v) throw(GLPError("Number of elements is $numel but vector is empty or nothing")) elseif length(v) < numel throw(GLPError("Wrong vector size: $(length(v)) (numel declared as $numel)")) @@ -745,7 +754,7 @@ function glp_set_obj_coef(glp_prob::GLPProb, col::Integer, coef::Real) @glpk_ccall set_obj_coef Void (Ptr{Void}, Int32, Float64) glp_prob.p col coef end -function glp_set_mat_row{Ti<:Integer, Tv<:Real}(glp_prob::GLPProb, row::Integer, len::Integer, ind::VecOrNothing{Ti}, val::Vector{Tv}) +function glp_set_mat_row{Ti<:Integer, Tv<:Real}(glp_prob::GLPProb, row::Integer, len::Integer, ind::Vector{Ti}, val::Vector{Tv}) _jl_glpk__check_glp_prob(glp_prob) _jl_glpk__check_vectors_size(len, ind, val) _jl_glpk__check_row_is_valid(glp_prob, row) @@ -759,8 +768,10 @@ function glp_set_mat_row{Ti<:Integer, Tv<:Real}(glp_prob::GLPProb, row::Integer, @glpk_ccall set_mat_row Void (Ptr{Void}, Int32, Int32, Ptr{Int32}, Ptr{Float64}) glp_prob row len ind32p val64p end +glp_set_mat_row{Tv<:Real}(glp_prob::GLPProb, row::Integer, len::Integer, ::Nothing, val::Vector{Tv}) = + glp_set_mat_row(glp_prob, row, len, Int32[], val) -function glp_set_mat_col{Ti<:Integer, Tv<:Real}(glp_prob::GLPProb, col::Integer, len::Integer, ind::VecOrNothing{Ti}, val::Vector{Tv}) +function glp_set_mat_col{Ti<:Integer, Tv<:Real}(glp_prob::GLPProb, col::Integer, len::Integer, ind::Vector{Ti}, val::Vector{Tv}) _jl_glpk__check_glp_prob(glp_prob) _jl_glpk__check_vectors_size(len, ind, val) _jl_glpk__check_col_is_valid(glp_prob, col) @@ -774,8 +785,10 @@ function glp_set_mat_col{Ti<:Integer, Tv<:Real}(glp_prob::GLPProb, col::Integer, @glpk_ccall set_mat_col Void (Ptr{Void}, Int32, Int32, Ptr{Int32}, Ptr{Float64}) glp_prob col len ind32p val64p end +glp_set_mat_col{Tv<:Real}(glp_prob::GLPProb, col::Integer, len::Integer, ::Nothing, val::Vector{Tv}) = + glp_set_mat_col(glp_prob::GLPProb, col, len, Int32[], val) -function glp_load_matrix{Ti<:Integer, Tv<:Real}(glp_prob::GLPProb, numel::Integer, ia::VecOrNothing{Ti}, ja::VecOrNothing{Ti}, ar::VecOrNothing{Tv}) +function glp_load_matrix{Ti<:Integer, Tv<:Real}(glp_prob::GLPProb, numel::Integer, ia::Vector{Ti}, ja::Vector{Ti}, ar::Vector{Tv}) _jl_glpk__check_glp_prob(glp_prob) _jl_glpk__check_vectors_size(numel, ia, ja, ar) if numel == 0 @@ -794,6 +807,12 @@ function glp_load_matrix{Ti<:Integer, Tv<:Real}(glp_prob::GLPProb, numel::Intege @glpk_ccall load_matrix Void (Ptr{Void}, Int32, Ptr{Int32}, Ptr{Int32}, Ptr{Float64}) glp_prob.p numel ia32p ja32p ar64p end +function glp_load_matrix{Tv<:Real}(glp_prob::GLPProb, numel::Integer, ia::VecOrNothing, ja::VecOrNothing, ar::VecOrNothing) + cia = _jl_glpk__convert_vecornothing(Int32, ia) + cja = _jl_glpk__convert_vecornothing(Int32, ja) + car = _jl_glpk__convert_vecornothing(Float64, ar) + return glp_load_matrix(glp_prob, numel, cia, cja, car) +end glp_load_matrix{Ti<:Integer, Tv<:Real}(glp_prob::GLPProb, ia::AbstractVector{Ti}, ja::AbstractVector{Ti}, ar::AbstractVector{Tv}) = glp_load_matrix(glp_prob, length(ar), ia, ja, ar) @@ -803,7 +822,7 @@ function glp_load_matrix{Ti<:Integer, Tv<:Real}(glp_prob::GLPProb, a::SparseMatr glp_load_matrix(glp_prob, ia, ja, ar) end -function glp_check_dup{Ti<:Integer}(rows::Integer, cols::Integer, numel::Integer, ia::VecOrNothing{Ti}, ja::VecOrNothing{Ti}) +function glp_check_dup{Ti<:Integer}(rows::Integer, cols::Integer, numel::Integer, ia::Vector{Ti}, ja::Vector{Ti}) _jl_glpk__check_rows_and_cols(rows, cols) _jl_glpk__check_vectors_size(numel, ia, ja) ia32 = int32(ia) @@ -816,6 +835,11 @@ function glp_check_dup{Ti<:Integer}(rows::Integer, cols::Integer, numel::Integer k = @glpk_ccall check_dup Int32 (Int32, Int32, Int32, Ptr{Int32}, Ptr{Int32}) rows cols numel ia32p ja32p return k end +function glp_check_dup(rows::Integer, cols::Integer, numel::Integer, ia::VecOrNothing, ja::VecOrNothing) + cia = _jl_glpk__convert_vecornothing(Int32, ia) + cja = _jl_glpk__convert_vecornothing(Int32, ja) + return glp_check_dup(rows, cols, numel, cia, cja) +end glp_check_dup{Ti<:Integer}(rows::Integer, cols::Integer, ia::AbstractVector{Ti}, ja::AbstractVector{Ti}) = glp_check_dup(rows, cols, length(ia), ia, ja) @@ -971,33 +995,51 @@ function glp_get_num_nz(glp_prob::GLPProb) return num_nz end -function glp_get_mat_row(glp_prob::GLPProb, row::Integer, ind::VecOrNothing{Int32}, val::VecOrNothing{Float64}) +function glp_get_mat_row(glp_prob::GLPProb, row::Integer, ind::Union(Vector{Int32},Nothing), val::Union(Vector{Float64},Nothing)) _jl_glpk__check_glp_prob(glp_prob) _jl_glpk__check_row_is_valid(glp_prob, row) numel = @glpk_ccall get_mat_row Int32 (Ptr{Void}, Int32, Ptr{Int32}, Ptr{Float64}) glp_prob row C_NULL C_NULL if numel == 0 return 0 end - _jl_glpk__check_vectors_size(numel, ind, val) - off32 = sizeof(Int32) - off64 = sizeof(Float64) - ind32p = pointer(ind) - off32 - val64p = pointer(val) - off64 + if !isequal(ind, nothing) + _jl_glpk__check_vectors_size(numel, ind) + off32 = sizeof(Int32) + ind32p = pointer(ind) - off32 + else + ind32p = C_NULL + end + if !isequal(val, nothing) + _jl_glpk__check_vectors_size(numel, val) + off64 = sizeof(Float64) + val64p = pointer(val) - off64 + else + val64p = C_NULL + end numel = @glpk_ccall get_mat_row Int32 (Ptr{Void}, Int32, Ptr{Int32}, Ptr{Float64}) glp_prob row ind32p int64p end -function glp_get_mat_col(glp_prob::GLPProb, col::Integer, ind::VecOrNothing{Int32}, val::VecOrNothing{Float64}) +function glp_get_mat_col(glp_prob::GLPProb, col::Integer, ind::Union(Vector{Int32},Nothing), val::Union(Vector{Float64},Nothing)) _jl_glpk__check_glp_prob(glp_prob) _jl_glpk__check_col_is_valid(glp_prob, col) numel = @glpk_ccall get_mat_col Int32 (Ptr{Void}, Int32, Ptr{Int32}, Ptr{Float64}) glp_prob col C_NULL C_NULL if numel == 0 return 0 end - _jl_glpk__check_vectors_size(numel, ind, val) - off32 = sizeof(Int32) - off64 = sizeof(Float64) - ind32p = pointer(ind) - off32 - val64p = pointer(val) - off64 + if !isequal(ind, nothing) + _jl_glpk__check_vectors_size(numel, ind) + off32 = sizeof(Int32) + ind32p = pointer(ind) - off32 + else + ind32p = C_NULL + end + if !isequal(val, nothing) + _jl_glpk__check_vectors_size(numel, val) + off64 = sizeof(Float64) + val64p = pointer(val) - off64 + else + val64p = C_NULL + end numel = @glpk_ccall get_mat_col Int32 (Ptr{Void}, Int32, Ptr{Int32}, Ptr{Float64}) glp_prob col ind32p int64p end @@ -1469,7 +1511,7 @@ function glp_write_mip(glp_prob::GLPProb, filename::String) return ret end -function glp_print_ranges(glp_prob::GLPProb, len::Integer, list::VecOrNothing{Int32}, flags::Integer, filename::String) +function glp_print_ranges{Ti<:Integer}(glp_prob::GLPProb, len::Integer, list::Vector{Ti}, flags::Integer, filename::String) _jl_glpk__check_glp_prob(glp_prob) _jl_glpk__check_vectors_size(len, list) _jl_glpk__check_list_ids(glp_prob, len, list) @@ -1482,6 +1524,14 @@ function glp_print_ranges(glp_prob::GLPProb, len::Integer, list::VecOrNothing{In ret = @glpk_ccall print_ranges Int32 (Ptr{Void}, Int32, Ptr{Int32}, Int32, Ptr{Uint8}) glp_prob.p len ind32p cstring(filename) end +function glp_print_ranges(glp_prob::GLPProb, len::Integer, ::Nothing, flags::Integer, filename::String) + _jl_glpk__check_glp_prob(glp_prob) + if len != 0; throw(GLPError("list passed as nothing bit len != 0 ($len)")); end + _jl_glpk_bf_exists(glp_prob.p) + _jl_glpk__check_file_is_writable(filename) + + ret = @glpk_ccall print_ranges Int32 (Ptr{Void}, Int32, Ptr{Int32}, Int32, Ptr{Uint8}) glp_prob.p len C_NULL cstring(filename) +end function glp_bf_exists(glp_prob::GLPProb) _jl_glpk__check_glp_prob(glp_prob) diff --git a/extras/linprog.jl b/extras/linprog.jl index fff6f24517f90..471f1969fbbe7 100644 --- a/extras/linprog.jl +++ b/extras/linprog.jl @@ -3,6 +3,8 @@ ## for optimization and constraint satisfaction problems ## +# note: be sure to load "sparse.jl" and "glpk.jl" before this file + # General notes: the interface is provided as a collection of # high-level functions which use the glpk library. # Most functions have almost same interface @@ -40,15 +42,14 @@ # Some methods have slightly different function calls, see # individual notes for additional information -include("glpk.jl") +typealias SparseOrFullMat{T} Union(Matrix{T}, SparseMatrixCSC{T}) +typealias MatOrNothing Union(Matrix, SparseMatrixCSC, Vector{None}, Nothing) # Linear Programming, Interior point method (default) #{{{ -function linprog_interior{T<:Real, P<:Union(GLPInteriorParam, Nothing)}(f::AbstractVector{T}, A::MatOrNothing{T}, b::VecOrNothing{T}, - Aeq::MatOrNothing{T}, beq::VecOrNothing{T}, - lb::VecOrNothing{T}, ub::VecOrNothing{T}, - params::P) +function linprog_interior{T<:Real,P<:Union(GLPInteriorParam,Nothing)}(f::Vector{T}, A::SparseOrFullMat{T}, b::Vector{T}, + Aeq::SparseOrFullMat{T}, beq::Vector{T}, lb::Vector{T}, ub::Vector{T}, params::P) lp, n = _jl_linprog__setup_prob(f, A, b, Aeq, beq, lb, ub, params) @@ -67,17 +68,29 @@ function linprog_interior{T<:Real, P<:Union(GLPInteriorParam, Nothing)}(f::Abstr return (nothing, nothing, ret) end end +function linprog_interior{T<:Real,P<:Union(GLPInteriorParam,Nothing)}(f::Vector{T}, A::MatOrNothing, b::VecOrNothing, + Aeq::MatOrNothing, beq::VecOrNothing, lb::VecOrNothing, ub::VecOrNothing, params::P) + + cA = _jl_linprog__convert_matornothing(T, A) + cb = _jl_linprog__convert_vecornothing(T, b) + cAeq = _jl_linprog__convert_matornothing(T, Aeq) + cbeq = _jl_linprog__convert_vecornothing(T, beq) + clb = _jl_linprog__convert_vecornothing(T, lb) + cub = _jl_linprog__convert_vecornothing(T, ub) + return linprog_interior(f, cA, cb, cAeq, cbeq, clb, cub, params) + +end -linprog_interior{T<:Real}(f::AbstractVector{T}, A::MatOrNothing{T}, b::VecOrNothing{T}) = +linprog_interior{T<:Real}(f::Vector{T}, A::MatOrNothing, b::VecOrNothing) = linprog_interior(f, A, b, nothing, nothing, nothing, nothing, nothing) -linprog_interior{T<:Real}(f::AbstractVector{T}, A::MatOrNothing{T}, b::VecOrNothing{T}, - Aeq::MatOrNothing{T}, beq::VecOrNothing{T}) = +linprog_interior{T<:Real}(f::Vector{T}, A::MatOrNothing, b::VecOrNothing, + Aeq::MatOrNothing, beq::VecOrNothing) = linprog_interior(f, A, b, Aeq, beq, nothing, nothing, nothing) -linprog_interior{T<:Real}(f::AbstractVector{T}, A::MatOrNothing{T}, b::VecOrNothing{T}, - Aeq::MatOrNothing{T}, beq::VecOrNothing{T}, lb::VecOrNothing{T}, - ub::VecOrNothing{T}) = +linprog_interior{T<:Real}(f::Vector{T}, A::MatOrNothing, b::VecOrNothing, + Aeq::MatOrNothing, beq::VecOrNothing, lb::VecOrNothing, + ub::VecOrNothing) = linprog_interior(f, A, b, Aeq, beq, lb, ub, nothing) linprog = linprog_interior @@ -85,10 +98,8 @@ linprog = linprog_interior # Linear Programming, Simplex Method #{{{ -function linprog_simplex{T<:Real, P<:Union(GLPSimplexParam, Nothing)}(f::AbstractVector{T}, A::MatOrNothing{T}, b::VecOrNothing{T}, - Aeq::MatOrNothing{T}, beq::VecOrNothing{T}, - lb::VecOrNothing{T}, ub::VecOrNothing{T}, - params::P) +function linprog_simplex{T<:Real,P<:Union(GLPSimplexParam,Nothing)}(f::Vector{T}, A::SparseOrFullMat{T}, b::Vector{T}, + Aeq::SparseOrFullMat{T}, beq::Vector{T}, lb::Vector{T}, ub::Vector{T}, params::P) lp, n = _jl_linprog__setup_prob(f, A, b, Aeq, beq, lb, ub, params) @@ -107,17 +118,29 @@ function linprog_simplex{T<:Real, P<:Union(GLPSimplexParam, Nothing)}(f::Abstrac return (nothing, nothing, ret) end end +function linprog_simplex{T<:Real,P<:Union(GLPSimplexParam,Nothing)}(f::Vector{T}, A::MatOrNothing, b::VecOrNothing, + Aeq::MatOrNothing, beq::VecOrNothing, lb::VecOrNothing, ub::VecOrNothing, params::P) + + cA = _jl_linprog__convert_matornothing(T, A) + cb = _jl_linprog__convert_vecornothing(T, b) + cAeq = _jl_linprog__convert_matornothing(T, Aeq) + cbeq = _jl_linprog__convert_vecornothing(T, beq) + clb = _jl_linprog__convert_vecornothing(T, lb) + cub = _jl_linprog__convert_vecornothing(T, ub) + return linprog_simplex(f, cA, cb, cAeq, cbeq, clb, cub, params) + +end -linprog_simplex{T<:Real}(f::AbstractVector{T}, A::MatOrNothing{T}, b::VecOrNothing{T}) = +linprog_simplex{T<:Real}(f::Vector{T}, A::MatOrNothing, b::VecOrNothing) = linprog_simplex(f, A, b, nothing, nothing, nothing, nothing, nothing) -linprog_simplex{T<:Real}(f::AbstractVector{T}, A::MatOrNothing{T}, b::VecOrNothing{T}, - Aeq::MatOrNothing{T}, beq::VecOrNothing{T}) = +linprog_simplex{T<:Real}(f::Vector{T}, A::MatOrNothing, b::VecOrNothing, + Aeq::MatOrNothing, beq::VecOrNothing) = linprog_simplex(f, A, b, Aeq, beq, nothing, nothing, nothing) -linprog_simplex{T<:Real}(f::AbstractVector{T}, A::MatOrNothing{T}, b::VecOrNothing{T}, - Aeq::MatOrNothing{T}, beq::VecOrNothing{T}, lb::VecOrNothing{T}, - ub::VecOrNothing{T}) = +linprog_simplex{T<:Real}(f::Vector{T}, A::MatOrNothing, b::VecOrNothing, + Aeq::MatOrNothing, beq::VecOrNothing, lb::VecOrNothing, + ub::VecOrNothing) = linprog_simplex(f, A, b, Aeq, beq, lb, ub, nothing) #}}} @@ -129,10 +152,8 @@ linprog_simplex{T<:Real}(f::AbstractVector{T}, A::MatOrNothing{T}, b::VecOrNothi # * the exact step only accepts the "it_lim" and "tm_lim" options, # which means no message suppression is possible -function linprog_exact{T<:Real, P<:Union(GLPSimplexParam, Nothing)}(f::AbstractVector{T}, A::MatOrNothing{T}, b::VecOrNothing{T}, - Aeq::MatOrNothing{T}, beq::VecOrNothing{T}, - lb::VecOrNothing{T}, ub::VecOrNothing{T}, - params::P) +function linprog_exact{T<:Real,P<:Union(GLPSimplexParam,Nothing)}(f::Vector{T}, A::SparseOrFullMat{T}, b::Vector{T}, + Aeq::SparseOrFullMat{T}, beq::Vector{T}, lb::Vector{T}, ub::Vector{T}, params::P) lp, n = _jl_linprog__setup_prob(f, A, b, Aeq, beq, lb, ub, params) @@ -155,17 +176,29 @@ function linprog_exact{T<:Real, P<:Union(GLPSimplexParam, Nothing)}(f::AbstractV return (nothing, nothing, ret) end end +function linprog_exact{T<:Real,P<:Union(GLPSimplexParam,Nothing)}(f::Vector{T}, A::MatOrNothing, b::VecOrNothing, + Aeq::MatOrNothing, beq::VecOrNothing, lb::VecOrNothing, ub::VecOrNothing, params::P) + + cA = _jl_linprog__convert_matornothing(T, A) + cb = _jl_linprog__convert_vecornothing(T, b) + cAeq = _jl_linprog__convert_matornothing(T, Aeq) + cbeq = _jl_linprog__convert_vecornothing(T, beq) + clb = _jl_linprog__convert_vecornothing(T, lb) + cub = _jl_linprog__convert_vecornothing(T, ub) + return linprog_exact(f, cA, cb, cAeq, cbeq, clb, cub, params) + +end -linprog_exact{T<:Real}(f::AbstractVector{T}, A::MatOrNothing{T}, b::VecOrNothing{T}) = +linprog_exact{T<:Real}(f::Vector{T}, A::MatOrNothing, b::VecOrNothing) = linprog_exact(f, A, b, nothing, nothing, nothing, nothing, nothing) -linprog_exact{T<:Real}(f::AbstractVector{T}, A::MatOrNothing{T}, b::VecOrNothing{T}, - Aeq::MatOrNothing{T}, beq::VecOrNothing{T}) = +linprog_exact{T<:Real}(f::Vector{T}, A::MatOrNothing, b::VecOrNothing, + Aeq::MatOrNothing, beq::VecOrNothing) = linprog_exact(f, A, b, Aeq, beq, nothing, nothing, nothing) -linprog_exact{T<:Real}(f::AbstractVector{T}, A::MatOrNothing{T}, b::VecOrNothing{T}, - Aeq::MatOrNothing{T}, beq::VecOrNothing{T}, lb::VecOrNothing{T}, - ub::VecOrNothing{T}) = +linprog_exact{T<:Real}(f::Vector{T}, A::MatOrNothing, b::VecOrNothing, + Aeq::MatOrNothing, beq::VecOrNothing, lb::VecOrNothing, + ub::VecOrNothing) = linprog_exact(f, A, b, Aeq, beq, lb, ub, nothing) #}}} @@ -188,13 +221,9 @@ linprog_exact{T<:Real}(f::AbstractVector{T}, A::MatOrNothing{T}, b::VecOrNothing # method to use (GLPSimplexParam -> simplex, GLPInteriorParam -> interior # point) -function mixintprog{T<:Real, Ti<:Integer, P<:Union(GLPIntoptParam, Nothing), Px<:Union(GLPParam, Nothing)}( - f::AbstractVector{T}, - A::MatOrNothing{T}, b::VecOrNothing{T}, - Aeq::MatOrNothing{T}, beq::VecOrNothing{T}, - lb::VecOrNothing{T}, ub::VecOrNothing{T}, - col_kind::VecOrNothing{Ti}, - params::P, params_presolve::Px) +function mixintprog{T<:Real,Ti<:Integer,P<:Union(GLPIntoptParam,Nothing),Px<:Union(GLPParam,Nothing)}( + f::Vector{T}, A::SparseOrFullMat{T}, b::Vector{T}, Aeq::SparseOrFullMat{T}, beq::Vector{T}, + lb::Vector{T}, ub::Vector{T}, col_kind::Vector{Ti}, params::P, params_presolve::Px) lp, n = _jl_linprog__setup_prob(f, A, b, Aeq, beq, lb, ub, params) _jl_mixintprog_set_col_kind(lp, n, col_kind) @@ -232,37 +261,81 @@ function mixintprog{T<:Real, Ti<:Integer, P<:Union(GLPIntoptParam, Nothing), Px< return (nothing, nothing, ret, ret_ps) end end +function mixintprog{T<:Real,P<:Union(GLPIntoptParam,Nothing),Px<:Union(GLPParam,Nothing)}( + f::Vector{T}, A::MatOrNothing, b::VecOrNothing, Aeq::MatOrNothing, beq::VecOrNothing, + lb::VecOrNothing, ub::VecOrNothing, col_kind::VecOrNothing, params::P, params_presolve::Px) + + cA = _jl_linprog__convert_matornothing(T, A) + cb = _jl_linprog__convert_vecornothing(T, b) + cAeq = _jl_linprog__convert_matornothing(T, Aeq) + cbeq = _jl_linprog__convert_vecornothing(T, beq) + clb = _jl_linprog__convert_vecornothing(T, lb) + cub = _jl_linprog__convert_vecornothing(T, ub) + ccol_kind = _jl_linprog__convert_vecornothing(Int32, col_kind) + return mixintprog(f, cA, cb, cAeq, cbeq, clb, cub, ccol_kind, params, params_presolve) + +end -mixintprog{T<:Real}(f::AbstractVector{T}, A::MatOrNothing{T}, b::VecOrNothing{T}) = +mixintprog{T<:Real}(f::Vector{T}, A::MatOrNothing, b::VecOrNothing) = mixintprog(f, A, b, nothing, nothing, nothing, nothing, nothing, nothing, nothing) -mixintprog{T<:Real}(f::AbstractVector{T}, A::MatOrNothing{T}, b::VecOrNothing{T}, - Aeq::MatOrNothing{T}, beq::VecOrNothing{T}) = +mixintprog{T<:Real}(f::Vector{T}, A::MatOrNothing, b::VecOrNothing, + Aeq::MatOrNothing, beq::VecOrNothing) = mixintprog(f, A, b, Aeq, beq, nothing, nothing, nothing, nothing, nothing) -mixintprog{T<:Real}(f::AbstractVector{T}, A::MatOrNothing{T}, b::VecOrNothing{T}, - Aeq::MatOrNothing{T}, beq::VecOrNothing{T}, lb::VecOrNothing{T}, - ub::VecOrNothing{T}) = +mixintprog{T<:Real}(f::Vector{T}, A::MatOrNothing, b::VecOrNothing, + Aeq::MatOrNothing, beq::VecOrNothing, lb::VecOrNothing, + ub::VecOrNothing) = mixintprog(f, A, b, Aeq, beq, lb, ub, nothing, nothing, nothing) -mixintprog{T<:Real, Ti<:Integer}(f::AbstractVector{T}, A::MatOrNothing{T}, b::VecOrNothing{T}, - Aeq::MatOrNothing{T}, beq::VecOrNothing{T}, lb::VecOrNothing{T}, - ub::VecOrNothing{T}, col_kind::VecOrNothing{Ti}) = +mixintprog{T<:Real}(f::Vector{T}, A::MatOrNothing, b::VecOrNothing, + Aeq::MatOrNothing, beq::VecOrNothing, lb::VecOrNothing, + ub::VecOrNothing, col_kind::VecOrNothing) = mixintprog(f, A, b, Aeq, beq, lb, ub, col_kind, nothing, nothing) -mixintprog{T<:Real, Ti<:Integer, P<:Union(GLPIntoptParam, Nothing), }(f::AbstractVector{T}, A::MatOrNothing{T}, b::VecOrNothing{T}, - Aeq::MatOrNothing{T}, beq::VecOrNothing{T}, lb::VecOrNothing{T}, - ub::VecOrNothing{T}, col_kind::VecOrNothing{Ti}, - params::P) = +mixintprog{T<:Real,P<:Union(GLPIntoptParam,Nothing)}(f::Vector{T}, A::MatOrNothing, b::VecOrNothing, + Aeq::MatOrNothing, beq::VecOrNothing, lb::VecOrNothing, + ub::VecOrNothing, col_kind::VecOrNothing, params::P) = mixintprog(f, A, b, Aeq, beq, lb, ub, col_kind, params, nothing) #}}} ## Common auxiliary functions #{{{ -function _jl_linprog__setup_prob{T<:Real, P<:Union(GLPParam, Nothing)}(f::AbstractVector{T}, A::MatOrNothing{T}, b::VecOrNothing{T}, - Aeq::MatOrNothing{T}, beq::VecOrNothing{T}, - lb::VecOrNothing{T}, ub::VecOrNothing{T}, - params::P) +function _jl_linprog__convert_vecornothing{T}(::Type{T}, a::VecOrNothing) + if isequal(a, nothing) || isa(a, Array{None}) + return T[] + elseif T <: Integer + if !(eltype(a) <: Integer) + error("integer-valued array required, or [] or nothing") + end + elseif T <: Real + if !(eltype(a) <: Real) + error("real-valued array required, or [] or nothing") + end + end + return convert(Array{T}, a) +end +function _jl_linprog__convert_matornothing{T}(::Type{T}, a::MatOrNothing) + if isequal(a, nothing) || isa(a, Array{None}) + return Array(T, 0, 0) + elseif T <: Integer + if !(eltype(a) <: Integer) + error("integer-valued array required, or [] or nothing") + end + elseif T <: Real + if !(eltype(a) <: Real) + error("real-valued array required, or [] or nothing") + end + end + if issparse(a) + return convert(SparseMatrixCSC{T}, a) + else + return convert(Array{T}, a) + end +end + +function _jl_linprog__setup_prob{T<:Real, P<:Union(GLPParam, Nothing)}(f::Vector{T}, A::SparseOrFullMat{T}, b::Vector{T}, + Aeq::SparseOrFullMat{T}, beq::Vector{T}, lb::Vector{T}, ub::Vector{T}, params::P) lp = GLPProb() glp_set_obj_dir(lp, GLP_MIN) @@ -334,38 +407,37 @@ function _jl_linprog__setup_prob{T<:Real, P<:Union(GLPParam, Nothing)}(f::Abstra return (lp, n) end -function _jl_linprog__check_A_b{T}(A::MatOrNothing{T}, b::VecOrNothing{T}, n::Int) +function _jl_linprog__check_A_b{T}(A::SparseOrFullMat{T}, b::Vector{T}, n::Int) m = 0 - if !_jl_glpk__is_empty(A) + if !isempty(A) if size(A, 2) != n error("invlid A size: $(size(A))") end m = size(A, 1) - if _jl_glpk__is_empty(b) + if isempty(b) error("b is empty but a is not") end if size(b, 1) != m - #printf(f"m=%i\n", m) error("invalid b size: $(size(b))") end else - if !_jl_glpk__is_empty(b) + if !isempty(b) error("A is empty but b is not") end end return m end -function _jl_linprog__check_lb_ub{T}(lb::VecOrNothing{T}, ub::VecOrNothing{T}, n::Int) +function _jl_linprog__check_lb_ub{T}(lb::Vector{T}, ub::Vector{T}, n::Int) has_lb = false has_ub = false - if ! _jl_glpk__is_empty(lb) + if !isempty(lb) if size(lb, 1) != n error("invlid lb size: $(size(lb))") end has_lb = true end - if ! _jl_glpk__is_empty(ub) + if !isempty(ub) if size(ub, 1) != n error("invalid ub size: $(size(ub))") end @@ -402,8 +474,8 @@ function _jl_linprog__dense_matrices_to_glp_format(m, meq, n, A, Aeq) return (ia, ja, ar) end -function _jl_mixintprog_set_col_kind{Ti<:Integer}(lp::GLPProb, n::Int, col_kind::VecOrNothing{Ti}) - if _jl_glpk__is_empty(col_kind) +function _jl_mixintprog_set_col_kind{Ti<:Integer}(lp::GLPProb, n::Int, col_kind::Vector{Ti}) + if isempty(col_kind) for i = 1 : n glp_set_col_kind(lp, i, GLP_IV) end diff --git a/test/linprog.jl b/test/linprog.jl index 1286ba5bd284e..0e435a5cf8858 100644 --- a/test/linprog.jl +++ b/test/linprog.jl @@ -1,8 +1,8 @@ ### Linear programming -setcwd("../extras") -load("sparse.jl") -load("linprog.jl") +load("../extras/sparse.jl") +load("../extras/glpk.jl") +load("../extras/linprog.jl") ## Simplex method @@ -19,13 +19,13 @@ f = [ 3.; 2. ]; A = [ 2. 1. ; 1. 1. ]; b = [ 100.; 80 ]; -lb = [ 0.; 0;]; +lb = [ 0.; 0.]; (z, x, flag) = linprog_simplex(-f, A, b, [], [], lb, [], lps_opts); @assert flag == 0 @assert z == -180.0 -@assert x == [20.; 60.] +@assert isequal(x, [20.; 60.]) # A constraint satisfaction (matching) problem @@ -51,9 +51,9 @@ ub = ones(Float64, 9); @assert flag == 0 @assert z == 5. -@assert x == [ 0.; 0.; 1. ; - 0.; 1.; 0. ; - 1.; 0.; 0. ] +@assert isequal(x, [ 0.; 0.; 1. ; + 0.; 1.; 0. ; + 1.; 0.; 0. ]) ## Interior point method @@ -89,6 +89,6 @@ colkind = int32([ GLP_BV for i = 1 : 9 ]) @assert flag == 0 @assert z == 5. -@assert x == [ 0.; 0.; 1. ; - 0.; 1.; 0. ; - 1.; 0.; 0. ] +@assert isequal(x, [ 0.; 0.; 1. ; + 0.; 1.; 0. ; + 1.; 0.; 0. ])