66
77hscb = 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+
914h = highspy .Highs ()
1015
1116# h.setOptionValue("log_to_console", True)
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 )
320319h .startCallback (hscb .HighsCallbackType .kCallbackLogging )
321320
322321h .run ()
@@ -356,3 +355,35 @@ def user_interrupt_callback(
356355# ~~~
357356# Clear so that incumbent model is empty
358357h .clear ()
358+
359+ # Test MIP callbacks
360+ print ("\n egout 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