Obtaining sub-optimal results from the model when the time limit is reached

I am working on a model that includes both linear and non-linear constraints. I am using Ipopt and Juniper solvers for my model.

What I am trying to do is to limit the time of the model and obtain the sub-optimal solution of the objective function and the decision variables. I am limiting the time using the following code:

nl_solver = optimizer_with_attributes(Ipopt.Optimizer, "print_level" => 0)
model = Model(optimizer_with_attributes(Juniper.Optimizer, "time_limit" => 200, "nl_solver"=>nl_solver))

I also tried using the following code:

set_time_limit_sec(model, 200.0)

However, the outcome of both implementations is the same. The model stops running and does not provide any results of the objective function and the decision variables. Is there a way I can limit the time of the model and obtain the sub-optimal results found by the model so far?

I am trying to limit the time because the model takes a very long time (in days, I am not sure if this is normal) to run. The same model (code) works perfectly fine if I use a smaller number of input parameters (variables) and provides the results within a few hours. But with a higher number of input parameters, the model takes so long and I am not sure if the model is stuck in some infinite loop or if there are any other reasons.

PS: I am new to optimization and JuMP/Julia so I apologize for the incorrect use of terminologies if there are any.

1 Like

What will be returned depends on the solver and the problem. If it has a feasible solution to return when hitting the time limit, most solvers will return that (but not every solver). It might also have no feasible solution to return.

You can see what Juniper has to return using termination_status(model) and primal_status(model). What do you get for this problem?

Thank you for your response @odow.

So I ran the model with the time limit of 3600 seconds and I got the following output:

termination_status(model): TIME_LIMIT
primal_status(model): INFEASIBLE_POINT

Also, which solver supports this? I might try changing the solver. I am not sure if this will provide any major improvement to the model running time.

You could try KNITRO if you have a license, but Juniper is good choice.

In this case, it looks like there is a solution available that you could check. But it looks like it might be infeasible. You could check with primal_feasbility_report(model).

Thank you for your reply.

I am working on the suggestion you just mentioned. But I have a question.

What does “infeasible” means here? (a) Does it mean that the current solution does not meet all the constraints? or (b) does it mean that it meets all the constraints but it is not the optimal value of the objective function?

Infeasible means that the point does not satisfy the constraints.

1 Like

I am getting the following output:

primal_feasbility_report(model): Dict{Any, Float64}()

What does that mean?

1 Like

I had a suspicion. The point is actually feasible, so the point is exactly the suboptimal point you want.

But there is a bug in Juniper that reports it as infeasible.

So is there a way I can access this solution after the time limit is reached?

And what do you suggest to do if there is a bug in Juniper? Change of solver or something else?

So is there a way I can access this solution after the time limit is reached?

Just access it as normal with value(x) and objective_value(model) etc.

And what do you suggest to do if there is a bug in Juniper?

We’ll get it fixed: Incorrect PrimalStatus if termination is not optimal · Issue #249 · lanl-ansi/Juniper.jl · GitHub

But you can probably just use the point (with care).

Thank you for your efforts to fix this.

So I have a quick update on what I did so far.

I tried changing the solver and I tested almost all non-commercial solvers. But each had its own errors and issues with my model, which I am not going to explain here.

But currently I am working with SCIP Solver, and surprisingly I am able to get the results from the model in a very short time. This is the output using SCIP solver:

SCIP Status        : problem is solved [optimal solution found]
Solving Time (sec) : 34.32
Solving Nodes      : 7506
Primal Bound       : +2.62483019292676e+01 (18 solutions)
Dual Bound         : +2.62483019292676e+01
Gap                : 0.00 %
objective_value= 26.24830192926761

While running the exact same model with the exact same inputs using Juniper produces the following output:

#branches: 89082
Obj: 26.24830569524511
objective_value= 26.24830569524511
Solving Time (sec): 16366.3

I verified the outputs I got using SCIP and it satisfies all the constraints in my model. My question is, why is there a huge difference in the model run time between Juniper and SCIP? I just want to understand from where this difference is coming, the model or the solver.

For anyone looking at this post in the future, I will explain how I got around this issue.

As I mentioned in my previous reply, I changed the solver from Juniper to SCIP.

With SCIP, I used the time limiting option to limit the time of the model and obtain the sub-optimal solution. This is how I defined the SCIP solver and the time limit (in seconds) option:

using SCIP
model = Model(() -> SCIP.Optimizer(limits_time = 10800))

Once the limit is reached, the SCIP will provide the best solution reached so far.

Hopefully, the bug with Juniper will be fixed. But I wanted to help anyone visiting this post for a similar issue they are facing.