@@ -382,8 +382,7 @@ def get_objective_const(self: "SolverHighs") -> numbers.Real:
382
382
check (self ._lib .Highs_getObjectiveOffset (self ._model , offset ))
383
383
return offset [0 ]
384
384
385
- def relax (self : "SolverHighs" ):
386
- # change integrality of all columns
385
+ def _all_cols_continuous (self : "SolverHighs" ):
387
386
n = self .num_cols ()
388
387
integrality = ffi .new (
389
388
"int[]" , [self ._lib .kHighsVarTypeContinuous for i in range (n )]
@@ -393,6 +392,24 @@ def relax(self: "SolverHighs"):
393
392
self ._model , 0 , n - 1 , integrality
394
393
)
395
394
)
395
+
396
+ def _reset_var_types (self : "SolverHighs" ):
397
+ var_type_map = {
398
+ mip .CONTINUOUS : self ._lib .kHighsVarTypeContinuous ,
399
+ mip .BINARY : self ._lib .kHighsVarTypeInteger ,
400
+ mip .INTEGER : self ._lib .kHighsVarTypeInteger ,
401
+ }
402
+ integrality = ffi .new ("int[]" , [var_type_map [vt ] for vt in self ._var_type ])
403
+ n = self .num_cols ()
404
+ check (
405
+ self ._lib .Highs_changeColsIntegralityByRange (
406
+ self ._model , 0 , n - 1 , integrality
407
+ )
408
+ )
409
+
410
+ def relax (self : "SolverHighs" ):
411
+ # change integrality of all columns
412
+ self ._all_cols_continuous ()
396
413
self ._var_type = [mip .CONTINUOUS ] * len (self ._var_type )
397
414
398
415
def generate_cuts (
@@ -413,8 +430,10 @@ def optimize(
413
430
relax : bool = False ,
414
431
) -> "mip.OptimizationStatus" :
415
432
if relax :
416
- # TODO: handle relax (need to remember and reset integrality?!
417
- raise NotImplementedError ()
433
+ # Temporarily change variable types. Original types are still stored
434
+ # in self._var_type.
435
+ self ._all_cols_continuous ()
436
+
418
437
check (self ._lib .Highs_run (self ._model ))
419
438
420
439
# store solution values for later access
@@ -440,6 +459,10 @@ def optimize(
440
459
if self ._has_dual_solution ():
441
460
self ._pi = [row_dual [i ] for i in range (m )]
442
461
462
+ if relax :
463
+ # Undo the temporary changes.
464
+ self ._reset_var_types ()
465
+
443
466
return opt_status
444
467
445
468
def get_objective_value (self : "SolverHighs" ) -> numbers .Real :
0 commit comments