Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Advance routines #121

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/Gurobi.jl
Expand Up @@ -53,6 +53,9 @@ module Gurobi
# grb_quad
add_qpterms!, add_qconstr!,

# Advance Routines
get_basisidx, get_tableaurow, get_tableaurow!,

# higher level
gurobi_model,

Expand All @@ -72,6 +75,7 @@ module Gurobi
include("grb_attrs.jl")
include("grb_constrs.jl")
include("grb_quad.jl")
include("grb_advroutines.jl")
include("grb_highlevel.jl")

include("grb_solve.jl")
Expand Down
53 changes: 53 additions & 0 deletions src/grb_advroutines.jl
@@ -0,0 +1,53 @@
mutable struct GRBsvec
len::Cint
ind::Ptr{Cint}
val::Ptr{Cdouble}
end

function get_tableaurow_grb(model::Model, cidx::Integer)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's best for this function to have a name that matches the function being wrapped. See e.g., https://github.com/JuliaOpt/Gurobi.jl/blob/93b4d3e37c3d8ed2ec37b59d207504537e85e173/src/grb_quad.jl#L4.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BinvRowi is a strange name for a function in Julia. The other problem is that this name is misleading, this is not actually the row from B^-1 is the row from A B^-1. http://www.gurobi.com/documentation/7.5/refman/c_grbbinvrowi.html
Should I call it ABinv_row?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about c_api_binvrowi

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

c_api_abinvrowi?

len = num_vars(model)+num_constrs(model)
idx = Array{Cint}(len)
val = Array{Cdouble}(len)

grb_v = GRBsvec(0, pointer(idx) , pointer(val))
ret = @grb_ccall(BinvRowi, Cint, (
Ptr{Void},
Cint,
Ref{GRBsvec}),
model, convert(Cint, cidx-1), grb_v)
if ret != 0
throw(GurobiError(model.env, ret))
end
return idx[1:grb_v.len]+1, val[1:grb_v.len]
end

function get_tableaurow!(row::Vector{Float64}, model::Model, cidx::Integer)
idx, val = get_tableaurow_grb(model, cidx)
row[idx] = val
return nothing
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer not to have these helper functions in Gurobi.jl. They don't get tested and lead to multiple ways to do the same thing.

Copy link
Author

@Thuener Thuener Jun 24, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you prefer to remove get_tableaurow! and get_tableaurow and leave get_tableaurow_grb as it is?


function get_tableaurow!(BinvA::Matrix{Float64}, model::Model, cidx::Integer)
idx, val = get_tableaurow_grb(model, cidx)
BinvA[cidx, idx] = val
return nothing
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto


function get_tableaurow(model::Model, cidx::Integer)
len = num_vars(model)+num_constrs(model)
spv = zeros(len)
get_tableaurow!(spv, model, cidx)
return spv
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto


function get_basisidx(model::Model)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

c_api_getbasishead

v = Array{Cint}(num_constrs(model))
ret = @grb_ccall(getBasisHead, Cint, (
Ptr{Void},
Ptr{Int}),
model, v)
if ret != 0
throw(GurobiError(model.env, ret))
end
return v+1
end
46 changes: 46 additions & 0 deletions test/advanced_routines.jl
@@ -0,0 +1,46 @@
# maximize 4 x + 3 y
#
# s.t. 2 x + 1 y <= 4
# 1 x + 2 y <= 1
# x >= 0, y >= 0
#
# solution: x = 1, y = 0, objv = 4

using Gurobi, Base.Test

@testset "GRB basis" begin
env = Gurobi.Env()

model = Gurobi.Model(env, "test basis", :maximize)

add_cvar!(model, 4., 0., Inf) # x
add_cvar!(model, 3., 0., Inf) # y
update_model!(model)

add_constr!(model, [2., 1., 0.], '<', 4.)
add_constr!(model, [1., 2., 0.], '<', 1.)

update_model!(model)

println(model)

optimize(model)
@test get_solution(model) ≈ [1, 0.]
@test get_objval(model) ≈ 4.

# A = get_constrmatrix(model)
# A = [A eye(2)]
# B_index = get_basisidx(model)
# B = A[:,B_index]
# invBA = full(B)\full(A)

@test Gurobi.get_basisidx(model) == [1, 3]
@test get_tableaurow(model, 1) ≈ [1., 2., 0., 1.]
@test get_tableaurow(model, 2) ≈ [0., -3., 1., -2.]

BinvA = zeros(num_constrs(model), num_vars(model)+num_constrs(model))
Gurobi.get_tableaurow!(BinvA, model, 1)
Gurobi.get_tableaurow!(BinvA, model, 2)
@test BinvA ≈ [1. 2. 0. 1.; 0. -3. 1. -2.]

end
1 change: 1 addition & 0 deletions test/runtests.jl
Expand Up @@ -12,6 +12,7 @@ tests = [
"test_grb_attrs",
"env",
"range_constraints",
"advanced_routines",
"test_get_strarray",
"large_coefficients"
]
Expand Down