1313 HighsLinearObjective ,
1414 cb , # type: ignore
1515 _Highs , # type: ignore
16- readonly_ptr_wrapper_double ,
1716 kHighsInf ,
1817)
1918
@@ -179,19 +178,17 @@ def optimize(self):
179178 """
180179 return self .solve ()
181180
182- # reset the objective and sense, then solve
183- def minimize (self , obj : Optional [Union [highs_var , highs_linear_expression ]] = None ):
181+ # reset the objective
182+ def setObjective (self , obj : Optional [Union [highs_var , highs_linear_expression ]] = None , sense : Optional [ ObjSense ] = None ):
184183 """
185- Solves a minimization of the objective and optionally updates the costs.
184+ Updates the costs.
186185
187186 Args:
188187 obj: An optional highs_linear_expression representing the new objective function.
188+ sense: An optional ObjSense value representing the new objective sense.
189189
190190 Raises:
191191 Exception: If obj is an inequality or not a highs_linear_expression.
192-
193- Returns:
194- A HighsStatus object containing the solve status after minimization.
195192 """
196193 if obj is not None :
197194 # if we have a single variable, wrap it in a linear expression
@@ -212,13 +209,13 @@ def minimize(self, obj: Optional[Union[highs_var, highs_linear_expression]] = No
212209 super ().changeColsCost (len (idxs ), idxs , vals )
213210 super ().changeObjectiveOffset (expr .constant or 0.0 )
214211
215- super (). changeObjectiveSense ( ObjSense . kMinimize )
216- return self . solve ( )
212+ if sense is not None :
213+ super (). changeObjectiveSense ( sense )
217214
218215 # reset the objective and sense, then solve
219- def maximize (self , obj : Optional [Union [highs_var , highs_linear_expression ]] = None ):
216+ def minimize (self , obj : Optional [Union [highs_var , highs_linear_expression ]] = None ):
220217 """
221- Solves a maximization of the objective and optionally updates the costs.
218+ Solves a minimization of the objective and optionally updates the costs.
222219
223220 Args:
224221 obj: An optional highs_linear_expression representing the new objective function.
@@ -227,32 +224,31 @@ def maximize(self, obj: Optional[Union[highs_var, highs_linear_expression]] = No
227224 Exception: If obj is an inequality or not a highs_linear_expression.
228225
229226 Returns:
230- A HighsStatus object containing the solve status after maximization .
227+ A HighsStatus object containing the solve status after minimization .
231228 """
232- if obj is not None :
233- # if we have a single variable, wrap it in a linear expression
234- expr = highs_linear_expression (obj ) if isinstance (obj , highs_var ) else obj
229+ self .setObjective (obj , ObjSense .kMinimize )
230+ return self .solve ()
235231
236- if expr .bounds is not None :
237- raise Exception ("Objective cannot be an inequality" )
232+ # reset the objective and sense, then solve
233+ def maximize (self , obj : Optional [Union [highs_var , highs_linear_expression ]] = None ):
234+ """
235+ Solves a maximization of the objective and optionally updates the costs.
238236
239- # reset objective
240- super ().changeColsCost (
241- self .numVariables ,
242- np .arange (self .numVariables , dtype = np .int32 ),
243- np .full (self .numVariables , 0 , dtype = np .float64 ),
244- )
237+ Args:
238+ obj: An optional highs_linear_expression representing the new objective function.
245239
246- # if we have duplicate variables, add the vals
247- idxs , vals = expr .unique_elements ()
248- super ().changeColsCost (len (idxs ), idxs , vals )
249- super ().changeObjectiveOffset (expr .constant or 0.0 )
240+ Raises:
241+ Exception: If obj is an inequality or not a highs_linear_expression.
250242
251- super ().changeObjectiveSense (ObjSense .kMaximize )
243+ Returns:
244+ A HighsStatus object containing the solve status after maximization.
245+ """
246+ self .setObjective (obj , ObjSense .kMaximize )
252247 return self .solve ()
248+
253249 @staticmethod
254250 def internal_get_value (
255- array_values : Union [Sequence [float ], np .ndarray [Any , np .dtype [np .float64 ]], readonly_ptr_wrapper_double ],
251+ array_values : Union [Sequence [float ], np .ndarray [Any , np .dtype [np .float64 ]]],
256252 index_collection : Union [
257253 Integral , highs_var , highs_cons , highs_linear_expression , Mapping [Any , Any ], Sequence [Any ], np .ndarray [Any , np .dtype [Any ]]
258254 ],
@@ -1203,7 +1199,7 @@ def __internal_callback(
12031199 data_in : Optional [cb .HighsCallbackDataIn ],
12041200 user_callback_data : Any ,
12051201 ):
1206- user_callback_data .callbacks [int (callback_type )].fire (message , data_out , data_in )
1202+ user_callback_data .callbacks [int (callback_type )].fire (callback_type , message , data_out , data_in )
12071203
12081204 def enableCallbacks (self ):
12091205 """
@@ -1216,9 +1212,16 @@ def enableCallbacks(self):
12161212 if len (c .callbacks ) > 0 :
12171213 self .startCallback (c .callback_type )
12181214
1215+ def clearCallbacks (self ):
1216+ """
1217+ Clears all callbacks.
1218+ """
1219+ for c in self .callbacks :
1220+ c .clear ()
1221+
12191222 def disableCallbacks (self ):
12201223 """
1221- Disables all callbacks.
1224+ Disables all callbacks, but does not clear them .
12221225 """
12231226 status = super ().setCallback (None , None ) # this will also stop all callbacks
12241227
@@ -1264,8 +1267,8 @@ def HandleUserInterrupt(self, value: bool):
12641267 self .cbMipInterrupt -= self .__user_interrupt_event
12651268
12661269 def __user_interrupt_event (self , e : HighsCallbackEvent ):
1267- if self .__solver_should_stop and e . data_in is not None :
1268- e .data_in . user_interrupt = True
1270+ if self .__solver_should_stop :
1271+ e .interrupt ()
12691272
12701273 @property
12711274 def cbLogging (self ):
@@ -1359,20 +1362,29 @@ def cbMipDefineLazyConstraints(self, value: HighsCallback):
13591362## Callback support
13601363##
13611364class HighsCallbackEvent (object ):
1362- __slots__ = ["message" , "data_out" , "data_in" , "user_data" ]
1365+ __slots__ = ["callback_type" , " message" , "data_out" , "data_in" , "user_data" ]
13631366
13641367 def __init__ (
13651368 self ,
1369+ callback_type : cb .HighsCallbackType ,
13661370 message : str ,
13671371 data_out : cb .HighsCallbackDataOut ,
13681372 data_in : Optional [cb .HighsCallbackDataIn ],
1369- user_data : Optional [Any ],
1373+ user_data : Optional [Any ]
13701374 ):
1375+ self .callback_type = callback_type
13711376 self .message = message
13721377 self .data_out = data_out
13731378 self .data_in = data_in
13741379 self .user_data = user_data
13751380
1381+ def interrupt (self , interrupt_value : bool = True ):
1382+ """
1383+ Sets the user interrupt flag in the callback data.
1384+ """
1385+ if self .data_in is not None :
1386+ self .data_in .user_interrupt = interrupt_value
1387+
13761388 def val (
13771389 self ,
13781390 var_expr : Union [Integral , highs_var , highs_cons , highs_linear_expression , Mapping [Any , Any ], np .ndarray [Any , np .dtype [Any ]]],
@@ -1468,14 +1480,15 @@ def clear(self):
14681480
14691481 def fire (
14701482 self ,
1483+ callback_type : cb .HighsCallbackType ,
14711484 message : str ,
14721485 data_out : cb .HighsCallbackDataOut ,
14731486 data_in : cb .HighsCallbackDataIn ,
14741487 ):
14751488 """
14761489 Fires the event, executing all subscribed callbacks.
14771490 """
1478- e = HighsCallbackEvent (message , data_out , data_in , None )
1491+ e = HighsCallbackEvent (callback_type , message , data_out , data_in , None )
14791492
14801493 for fn , user_data in zip (self .callbacks , self .user_callback_data ):
14811494 e .user_data = user_data
@@ -1792,7 +1805,7 @@ def copy(self):
17921805
17931806 def evaluate (
17941807 self ,
1795- values : Union [Sequence [float ], np .ndarray [Any , np .dtype [np .float64 ]], readonly_ptr_wrapper_double ],
1808+ values : Union [Sequence [float ], np .ndarray [Any , np .dtype [np .float64 ]]],
17961809 ) -> Union [float , bool ]:
17971810 """
17981811 Evaluates the linear expression given a solution array (values).
0 commit comments