I have a model where I try to add cuts to it within the callback, I am trying to access the objective bound of the model but it is not possible in the callback with the following error message
Error evaluating cec-procedure.jl
LoadError: Gurobi Error 10005: Unable to retrieve attribute 'ObjBoundC'
There is any way to get the objective value and the objective bound in each step in the callback?
here is my full implementation
using JuMP
import Gurobi
#import Random
function cec_procedure()
initial = 0
n = 32
s = 33
E = [(0,1),(3,17),(22,23),(6,7),(19,26),(16,9),(33,5),(33,21),
(2,3),(3,9),(22,15),(6,9),(19,13),(16,25),(33,6),(33,22),
(2,4),(3,13),(22,24),(6,26),(15,20),(16,26),(33,7),(33,23),
(2,5),(18,19),(22,16),(6,27),(15,24),(16,27),(33,8),(33,24),
(2,6),(18,16),(22,9),(7,9),(15,16),(28,13),(33,9),(33,25),
(2,7),(1,11),(22,25),(7,27),(15,28),(17,9),(33,10),(33,26),
(2,8),(1,19),(22,26),(29,19),(15,9),(9,26),(33,11),(33,27),
(2,9),(1,20),(22,27),(29,30),(15,26),(9,27),(33,12),(33,28),
(10,1),(14,6),(12,28),(29,13),(15,27),(25,13),(33,13),(33,29),
(10,11),(14,16),(12,26),(29,31),(20,16),(26,27),(33,14),(33,30),
(10,12),(14,9),(12,13),(23,17),(20,28),(26,13),(33,15),(33,31),
(10,13),(21,6),(5,29),(23,9),(20,9),(33,0),(33,16),(33,32),
(3,14),(21,15),(5,23),(19,20),(24,27),(33,1),(33,17),
(3,5),(21,20),(5,15),(19,16),(32,16),(33,2),(33,18),
(3,15),(21,9),(5,9),(19,25),(32,9),(33,3),(33,19),
(3,16),(22,6),(5,25),(19,30),(16,17),(33,4),(33,20)]
###################################################
cec_model = direct_model(Gurobi.Optimizer())
set_optimizer_attribute(cec_model, "Threads", 1)
set_optimizer_attribute(cec_model, "OptimalityTol", 1e-6)
@variable(cec_model,x[E],binary = true)
@variable(cec_model, y[v=initial:s],binary = true)
#constraint 2
for i = initial:n
@constraint(cec_model,(sum(x[(i,j)] for j in initial:s if (i,j) in E)
+sum(x[(j,i)] for j in initial:s if (j,i) in E)) == 2*y[i])
end
#constraint 3
@constraint(cec_model,sum(x[(s,i)] for i=initial:n)==2)
#constraint 5
for i = initial:n
for j = initial:s
if (j,i) in E
@constraint(cec_model,x[(j,i)] <= y[i])
@constraint(cec_model,x[(j,i)] <= y[j])
end
end
end
#constraint 6
for (i,j) in E
if i != s && j!= s
@constraint(cec_model,x[(i,j)] >= y[i]+y[j]-1)
end
end
@objective(cec_model, Max, sum(y[w] for w in initial:s)-1)
#####################################################
function subtour_elimination(cb_data)
## We only check subtours for integer-feasible solutions
status = callback_node_status(cb_data, cec_model)
if status == MOI.CALLBACK_NODE_STATUS_INTEGER #|| status == MOI.CALLBACK_NODE_STATUS_FRACTIONAL
y_val = callback_value.(Ref(cb_data), y)
x_val = callback_value.(Ref(cb_data), x)
objbound=MOI.get(cec_model, Gurobi.ModelAttribute("ObjBoundC"))
println(objbound)
# Write the current solution nodes into a list
T=[]
for ver in initial:s
if round(y_val[ver]) > 0
append!(T, ver)
end
end
cycle=[]
cycle = subtour(T,x_val)
# A subtour contains at least 3 nodes and at most (n-1)
for cy in range(1,length(cycle))
if !(isempty(cycle[cy])) && length(cycle[cy]) > 2
con = @build_constraint(sum(y[node] for node in cycle[cy]) <= length(cycle[cy]) - 1)
MOI.submit(cec_model, MOI.LazyConstraint(cb_data), con)
end
end
end
end
####################################################################
function subtour(vertices,x_values)
all_cycles=[]
while !(isempty(vertices))
cycle = collect(initial:s)
thiscycle = []
# Get the first item
nextv = first(vertices)
current = nextv
# Get the index of all nodes to which the current node is connected
index = findall(vertex -> (((current,vertex) in E)|| ((vertex,current) in E))
,vertices)
neighbours=[]
for ind in 1:length(index)
append!(neighbours,(vertices[index[ind]]))
end
prev = first(neighbours)
while true
push!(thiscycle, current)
posnext = findall(c -> (((current,c) in E && round(x_values[(current,c)]) > 0)
|| ((c,current) in E && round(x_values[(c,current)]) > 0)) && (c != prev),vertices)
temp = first(vertices[posnext])
prev = current
current = temp
if current == nextv
break
end
end
vertices = setdiff(vertices,thiscycle)
if length(thiscycle) > 2 && length(thiscycle) < length(cycle) && !(s in thiscycle)
cycle = thiscycle
push!(all_cycles,cycle)
else
cycle=[]
end
end
return all_cycles
end
MOI.set(cec_model, MOI.RawParameter("LazyConstraints"), 1)
MOI.set(cec_model, MOI.LazyConstraintCallback(), subtour_elimination)
optimize!(cec_model)
end
@time begin
cec_procedure()
println("Total excution time:")
end