Why does Gurobi's best bound for the objective goes over the optimal objective value - gurobi

I am solving an integer programming problem in Gurobi for objective minimization. I know that there is an integer solution that gives an objective of 322.48, and I verified this by also setting that solution as constraints and solving with Gurobi. However, when solving, Gurobi's best bound starts from 322.48, but always goes beyond it, even going to 323.80, when in fact I know that a better solution exists. Does anyone know why this would be happening?
I run Gurobi with the following parameters:
opt.Params.Method = 2
opt.Params.Threads = 1
opt.Params.MIPFocus = 1
opt.Params.MIPGap = 1e-9
opt.Params.IntegralityFocus = 1
opt.Params.IntFeasTol = 1e-9
opt.Params.FeasibilityTol = 1e-9
When I set Params.Method to default, the relaxation objective itself turns out to be 323.60, which is incorrect as I previously verified that there is a solution with 322.48 objective. Something is off, does anyone have any idea what?

Related

Model is infeasible in Gurobi although it has a feasible solution

I am attempting to solve a non-convex quadratic optimization problem using Gurobi, but I have encountered an issue. Specifically, I have a specific objective function; however, I am only interested in finding a feasible solution. To do this, I tried two ways:
1- set my specific objective function as the model objective and set the parameter "SolutionLimit" to 1. This works fine, and Gurobi gives me a feasible solution.
2- give Gurobi no objective function (or set the objective to some arbitrary number like 0). In this case, Gurobi returns no feasible solution. The log it prints says:
Optimal solution found (tolerance 1.00e-04)
Warning: max constraint violation (1.5757e+01) exceeds tolerance
(model may be infeasible or unbounded - try turning presolve off)
Best objective -0.000000000000e+00, best bound -0.000000000000e+00, gap 0.0000%
I checked the solution it returned, and it is infeasible. I want the second method to work too. I have attempted to modify the solver parameters (such as "m.ModelSense = GRB.MAXIMIZE," "m.params.MIPFocus = 3," "m.params.NoRelHeurTime = 200," "m.params.DualReductions = 0," "m.params.Presolve = 2," and "m.params.Crossover = 0") in an effort to resolve this issue but have been unsuccessful. Are there any other parameters that I can adjust in order to successfully solve this problem?
This model has numerical issues; to understand more, please see Guidelines for Numerical Issues in the Gurobi Reference Manual.

Pyomo: Unbounded objective function though bounded

I am currently implementing an optimization problem with pyomo and since now some hours I get the message that my problem is unbounded. After searching for the issue, I came along one term which seems to be unbounded. I excluded this term from the objective function and it shows that it takes a very high negative value, which supports the assumption that it is unbounded to -Inf.
But I have checked the problem further and it is impossible that the term is unbounded, as following code and results show:
model.nominal_cap_storage = Var(model.STORAGE, bounds=(0,None)) #lower bound is 0
#I assumed very high CAPEX for each storage (see print)
dict_capex_storage = {'battery': capex_battery_storage,
'co2': capex_co2_storage,
'hydrogen': capex_hydrogen_storage,
'heat': capex_heat_storage,
'syncrude': capex_syncrude_storage}
print(dict_capex_storage)
>>> {'battery': 100000000000000000, 'co2': 100000000000000000,
'hydrogen': 1000000000000000000, 'heat': 1000000000000000, 'syncrude': 10000000000000000000}
From these assumptions I already assume that it is impossible that the one term can be unbounded towards -Inf as the capacity has the lower bound of 0 and the CAPEX is a positive fixed value. But now it gets crazy. The following term is has the issue of being unbounded:
model.total_investment_storage = Var()
def total_investment_storage_rule(model):
return model.total_investment_storage == sum(model.nominal_cap_storage[storage] * dict_capex_storage[storage] \
for storage in model.STORAGE)
model.total_investment_storage_con = Constraint(rule=total_investment_storage_rule)
If I exclude the term from the objective function, I get following value after the optimization. It seems, that it can take high negative values.
>>>>
Variable total_investment_storage
-1004724108.3426505
So I checked the term regarding the component model.nominal_cap_storage to see the value of the capacity:
model.total_cap_storage = Var()
def total_cap_storage_rule(model):
return model.total_cap_storage == sum(model.nominal_cap_storage[storage] for storage in model.STORAGE)
model.total_cap_storage_con = Constraint(rule=total_cap_storage_rule)
>>>>
Variable total_cap_storage
0.0
I did the same for the dictionary, but made a mistake: I forgot to delete the model.nominal_cap_storage. But the result is confusing:
model.total_capex_storage = Var()
def total_capex_storage_rule(model):
return model.total_capex_storage == sum(model.nominal_cap_storage[storage] * dict_capex_storage[storage] \
for storage in model.STORAGE)
model.total_capex_storage_con = Constraint(rule=total_capex_storage_rule)
>>>>
Variable total_capex_storage
0.0
So my question is why is the term unbounded and how is it possible that model.total_investment_storage and model.total_capex_storage have different solutions though both are calculated equally? Any help is highly appreciated.
I think you are misinterpreting "unbounded." When the solver says the problem is unbounded, that means the objective function value is unbounded based on the variables and constraints in the problem. It has nothing to do with bounds on variables, unless one of those variable bounds prevents the objective from being unbound.
If you want help on above problem, you need to edit and post the full problem, with the objective function, and (if possible) the error. What you have now is a collection of different snippets of different variations of a problem, which isn't really informative on the overall issue.
I solved the problem by setting a lower bound to the term, which takes a negative value:
model.total_investment_storage = Var(bounds=(0, None)
I am still not sure why this term can take negative values but this solved at least my problem

Why I am getting same answers in gurobi when I am finding multiple solutions?

I am using Gurobi for solving an optimization problem. In my problem, the goal is to analyze the most possible solutions. For this purpose, I am using the parameter:
PoolSearchMode=2
in Gurobi to find multiple solutions. But, when I retrieve the solutions, there are some same results!. For example, if it returns 100 solutions, half of them are the same and actually I have 50 different solutions.
For more detail, I am trying to find some sets of nodes in a graph that have a special feature. So I have set the parameter "PoolSearchMode" to 2 that causes the MIP to do a systematic search for the n best solutions. I have defined a parameter "best" to find solutions that have "objVal" equal to the best one. In the blow there is a part of my code:
m.Params.PoolSearchMode = 2
m.Params.PoolSolutions = 100
b = m.addVars(Edges, vtype=GRB.BINARY, name = "b")
.
.
.
if m.status == GRB.Status.OPTIMAL:
best = 0
for key in range(m.SolCount):
m.setParam(GRB.Param.SolutionNumber, key)
if m.objVal == m.PoolObjVal:
best+=1
optimal_sets = [[] for i in range(best)]
for key in range(best):
m.setParam(GRB.Param.SolutionNumber, key)
for e in (Edges):
if b[e].Xn>0 and b[e].varname[2:]=="{}".format(External_node):
optimal_sets[key].append(int(b[e].varname[0:2]))
return optimal_sets
I have checked and I found that, if there are not 100 solutions in a graph, it returns fewer solutions. But in these sets also there are same results like:
[1,2,3],
[1,2,3],
[1,3,5]
How can I fix this issue to get different solutions?
It seems that Gurobi returns multiple solutions to the MIP that can be mapped to the same solution of your underlying problem. I'm sure that if you checked the entire solution vector all these solutions would indeed be different. You are only looking at a subset of the variables in your set optimal_sets.

Root finding with a kinked function using NLsolve in Julia

I am currently trying to solve a complementarity problem with a function that features a downward discontinuity, using the mcpsolve() function of the NLsolve package in Julia. The function is reproduced here for specific parameters, and the numbers below refer to the three panels of the figure.
Unfortunately, the algorithm does not always return the interior solution, even though it exists:
In (1), when starting at 0, the algorithm stays at 0, thinking that the boundary constraint binds,
In (2), when starting at 0, the algorithm stops right before the downward jump, even though the solution lies to the right of this point.
These problems occur regardless of the method used - trust region or Newton's method. Ideally, the algorithm would look for potential solutions in the entire set before stopping.
I was wondering if some of you had worked with similar functions, and had found a clever solution to bypass these issues. Note that
Starting to the right of the solution would not solve these problems, as they would also occur for other parametrization - see (3) this time,
It is not known a priori where in the parameter space the particular cases occur.
As an illustrative example, consider the following piece of code. Note that the function is smoother, and yet here as well the algorithm cannot find the solution.
function f!(x,fvec)
if x[1] <= 1.8
fvec[1] = 0.1 * (sin(3*x[1]) - 3)
else
fvec[1] = 0.1 * (x[1]^2 - 7)
end
end
NLsolve.mcpsolve(f!,[0.], [Inf], [0.], reformulation = :smooth, autodiff = true)
Once more, setting the initial value to something else than 0 would only postpone the problem. Also, as pointed out by Halirutan, fzero from the Roots package would probably work, but I'd rather use mcpsolve() as the problem is initially a complementarity problem.
Thank you very much in advance for your help.

Why could a SCIPcopy model be infeasible a when original model is feasible?

I'm new to SCIP, so I'm not sure if this is a bug or if I'm just doing something wrong.
I have a MIP instance that solves perfectly using SCIP, however when I try to solve a copy of the model SCIP says that it is infeasible. It seems to be more noticeable when presolve is turned off.
I'm using windows with the pre-built SCIP v3.2.0. The model only has binary and integer variables.
The following code outlines my attempt:
SCIP* _scip, subscip;
SCIPcreate(&_scip);
SCIPincludeDefaultPlugins(_scip);
SCIPcreateProbBasic(_scip, "interval_solver")); // create an empty problem
SCIPsetPresolving(_scip, SCIP_PARAMSETTING_OFF, true); //disable presolving
// build model (snipped)
SCIPsolve(_scip); // succeeds and gives feasible solution
SCIP_Bool valid = FALSE;
SCIPcreate(&subscip);
SCIPcopy(_scip, subscip, NULL, NULL, "1", TRUE, FALSE, TRUE, &valid);
SCIPsolve(subscip); // infeasible
Something that might be related (and seems weird to me) is that after solving the original problem (and getting a feasible solution), checking the solution reports an infeasible result. i.e.
SCIP_SOL* sol = SCIPgetBestSol(_scip);
SCIPcheckSol(_scip, sol, TRUE, TRUE, TRUE, TRUE, &valid);
gives:
solution value 1 violates bounds of <t_x71_(6,1275,6805)_(9,1275,6805)>[-0,0] by 1
Any ideas why this could be happening? Thanks!
Propagation in SCIP may take into account the best solution known so far and do reductions which are only valid for the problem of finding a solution better than this.
For example, if you have a minimization problem with n variables x_1,...,x_n with objective coefficients c_1,...,c_n >= 0 and already found a solution with x_1 = 1, x_2 = ... = x_n = 0, then propagation will globally fix x_1 to 0, because the objective of any solution with x_1 = 1 will be at least as large as the objective of the solution you already found.
This means that the solutions found so far may not be feasible anymore for the remaining problem (which looks for a strictly better solution).
In order to check the solution, you should check it in the original problem space, which you can do with SCIPcheckSolOrig().
Disabling presolving an propagation might help, but does not guarantee that the global presolved problem is not changed. Presolving in the LP solver should not be the problem, but might have changed the reported optimal LP solution (if there are multiple optima) and therefore caused a change in the solving process. This might have avoided your issue in this case, but probably by pure luck and the issue may still appear again on other instances. Moreover, the more features you disable, the more this will have a negative impact on your performance.
However, there is an easy solution to your problem: You can copy the original unchanged problem by using SCIPcopyOrig().
Some of the variable bounds were still being presolved. To fix the issue I needed to add:
SCIPsetBoolParam(_scip, "lp/presolving", FALSE);
This fixed most things, but the following also helped fix some 'check solution' issues:
SCIPsetIntParam(_scip, "propagating/maxrounds", 0);
SCIPsetIntParam(_scip, "propagating/maxroundsroot", 0);