@@ -282,7 +282,7 @@ primal_feasibility_report(model, Dict(x => 1.0, y => 1e-6))
282282# `value(x)` of an integer variable or `::Bool` for `value(x)` of a binary
283283# variable.
284284
285- # In most cases , it is safe to post-process the solution using
285+ # For some models , it is safe to post-process the solution using
286286# `y_int = round(Int, value(y))`. However, in some cases "fixing" the
287287# integrality like this can cause violations in primal feasibility that exceed
288288# the primal feasibility tolerance. For example, if we rounded our
@@ -292,6 +292,33 @@ primal_feasibility_report(model, Dict(x => 1.0, y => 1e-6))
292292
293293primal_feasibility_report (model, Dict (x => 1.0 , y => 0.0 ))
294294
295+ # If strict integer feasibility matters to you, one heuristic that sometimes
296+ # works is to round and fix the integer variables, and then re-solve the problem
297+ # to find new values for the remaining continuous variables:
298+
299+ function round_and_repair_heuristic! (model)
300+ # # Query all values first...
301+ vars = filter! (xi -> is_integer (xi) || is_binary (xi), all_variables (model))
302+ solution = round .(Int, value .(vars))
303+ # # ...then modify the model
304+ fix .(vars, solution; force = true )
305+ optimize! (model)
306+ assert_is_solved_and_feasible (model)
307+ return
308+ end
309+
310+ # Here it is in action:
311+
312+ set_optimizer (model, HiGHS. Optimizer)
313+ set_silent (model)
314+ optimize! (model)
315+ assert_is_solved_and_feasible (model)
316+ round_and_repair_heuristic! (model)
317+ solution_summary (model)
318+
319+ # Note that this heuristic will fail if no feasible solution exists for the
320+ # rounded integer values.
321+
295322# ### Why you shouldn't use a small tolerance
296323
297324# Just like primal feasibility tolerances, using a smaller value for the
0 commit comments