Skip to content

Commit 48f19da

Browse files
committed
Added MIP callback examples to call_highs_from_python.py
1 parent b5cbeab commit 48f19da

File tree

1 file changed

+43
-12
lines changed

1 file changed

+43
-12
lines changed

examples/call_highs_from_python.py

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@
66

77
hscb = highspy.cb
88

9+
# Constants for iteration limits or objective targets, adjust as required
10+
SIMPLEX_ITERATION_LIMIT = 100
11+
IPM_ITERATION_LIMIT = 100
12+
EGOUT_OBJECTIVE_TARGET = 610.0
13+
914
h = highspy.Highs()
1015

1116
# h.setOptionValue("log_to_console", True)
@@ -230,7 +235,7 @@
230235

231236
# Define a callback
232237

233-
def user_interrupt_callback(
238+
def user_callback(
234239
callback_type,
235240
message,
236241
data_out,
@@ -240,28 +245,22 @@ def user_interrupt_callback(
240245
# dev_run = True
241246
dev_run = False
242247

243-
# Constants for iteration limits or objective targets, adjust as required
244-
SIMPLEX_ITERATION_LIMIT = 100
245-
IPM_ITERATION_LIMIT = 100
246-
EGOUT_OBJECTIVE_TARGET = 1.0
247-
248248
# Callback for MIP Improving Solution
249249
if callback_type == hscb.HighsCallbackType.kCallbackMipImprovingSolution:
250250
# Assuming it is a list or array
251251
assert user_callback_data is not None, "User callback data is None!"
252-
local_callback_data = user_callback_data[0]
253252

254253
if dev_run:
255254
print(f"userCallback(type {callback_type};")
256-
print(f"data {local_callback_data:.4g}): {message}")
255+
print(f"data {user_callback_data:.4g}): {message}")
257256
print(f"with objective {data_out.objective_function_value}")
258257
print(f"and solution[0] = {data_out.mip_solution[0]}")
259258

260259
# Check and update the objective function value
261260
assert (
262-
local_callback_data >= data_out.objective_function_value
261+
user_callback_data >= data_out.objective_function_value
263262
), "Objective function value is invalid!"
264-
user_callback_data[0] = data_out.objective_function_value
263+
user_callback_data = data_out.objective_function_value
265264

266265
else:
267266
# Various other callback types
@@ -297,7 +296,7 @@ def user_interrupt_callback(
297296
print(f"Objective = {data_out.objective_function_value:.4g}")
298297

299298
data_in.user_interrupt = (
300-
data_out.objective_function_value < EGOUT_OBJECTIVE_TARGET
299+
data_out.objective_function_value < user_callback_data
301300
)
302301

303302

@@ -316,7 +315,7 @@ def user_interrupt_callback(
316315

317316

318317
# Set callback and run
319-
h.setCallback(user_interrupt_callback, None)
318+
h.setCallback(user_callback, None)
320319
h.startCallback(hscb.HighsCallbackType.kCallbackLogging)
321320

322321
h.run()
@@ -356,3 +355,35 @@ def user_interrupt_callback(
356355
# ~~~
357356
# Clear so that incumbent model is empty
358357
h.clear()
358+
359+
# Test MIP callbacks
360+
print("\negout as HighsModel")
361+
362+
h.setOptionValue("output_flag", False);
363+
h.setOptionValue("presolve", "off");
364+
365+
h.readModel("check/instances/egout.mps")
366+
367+
for iCase in range(0, 2):
368+
if iCase == 0:
369+
user_callback_data = EGOUT_OBJECTIVE_TARGET;
370+
h.setCallback(user_callback, user_callback_data)
371+
h.startCallback(hscb.HighsCallbackType.kCallbackMipInterrupt)
372+
required_model_status = highspy.HighsModelStatus.kInterrupt
373+
else:
374+
user_callback_data = 1e30;
375+
h.setCallback(user_callback, user_callback_data)
376+
h.startCallback(hscb.HighsCallbackType.kCallbackMipImprovingSolution)
377+
required_model_status = highspy.HighsModelStatus.kOptimal
378+
379+
h.run()
380+
381+
assert (h.getModelStatus() == required_model_status)
382+
383+
print(f"user_callback_data = {user_callback_data}: Success!")
384+
h.clearSolver()
385+
386+
387+
388+
389+

0 commit comments

Comments
 (0)