Skip to content

Commit 449f695

Browse files
authored
Merge pull request ERGO-Code#2264 from quantresearch1/feature/multiobjective_highspy
expose multiobjective in highspy
2 parents fa215aa + fe49f71 commit 449f695

File tree

4 files changed

+44
-1
lines changed

4 files changed

+44
-1
lines changed

src/highspy/__init__.pyi

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ from highspy._core import (
77
HighsHessian,
88
HighsInfo,
99
HighsInfoType,
10+
HighsLinearObjective,
1011
HighsLogType,
1112
HighsLp,
1213
HighsModel,
@@ -59,6 +60,7 @@ __all__: list[str] = [
5960
"HighsRanging",
6061
"kHighsInf",
6162
"kHighsIInf",
63+
"HighsLinearObjective",
6264
"HIGHS_VERSION_MAJOR",
6365
"HIGHS_VERSION_MINOR",
6466
"HIGHS_VERSION_PATCH",

src/highspy/_core/__init__.pyi

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,17 @@ class HighsModel:
290290

291291
def __init__(self) -> None: ...
292292

293+
class HighsLinearObjective:
294+
weight: float
295+
offset: float
296+
coefficients: list[float]
297+
abs_tolerance: float
298+
rel_tolerance: float
299+
priority: int
300+
301+
def __init__(self) -> None: ...
302+
303+
293304
class HighsModelStatus:
294305
"""
295306
Members:
@@ -777,6 +788,7 @@ class _Highs:
777788
indices: numpy.ndarray[typing.Any, numpy.dtype[numpy.int32]],
778789
values: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]],
779790
) -> HighsStatus: ...
791+
def addLinearObjective(self, linear_objective: HighsLinearObjective) -> HighsStatus: ...
780792
def addVar(self, lower_bound: float, upper_bound: float) -> HighsStatus: ...
781793
def addVars(
782794
self,
@@ -814,6 +826,7 @@ class _Highs:
814826
def changeRowBounds(self, row: int, lower_bound: float, upper_bound: float) -> HighsStatus: ...
815827
def clear(self) -> HighsStatus: ...
816828
def clearModel(self) -> HighsStatus: ...
829+
def clearLinearObjectives(self) -> HighsStatus: ...
817830
def clearSolver(self) -> HighsStatus: ...
818831
def crossover(self, solution: HighsSolution) -> HighsStatus: ...
819832
def deleteCols(self, num_cols: int, cols: numpy.ndarray[typing.Any, numpy.dtype[numpy.int32]]) -> HighsStatus: ...

src/highspy/highs.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
ObjSense,
1111
HighsVarType,
1212
HighsStatus,
13+
HighsLinearObjective,
1314
cb, # type: ignore
1415
_Highs, # type: ignore
1516
readonly_ptr_wrapper_double,
@@ -249,7 +250,6 @@ def maximize(self, obj: Optional[Union[highs_var, highs_linear_expression]] = No
249250

250251
super().changeObjectiveSense(ObjSense.kMaximize)
251252
return self.solve()
252-
253253
@staticmethod
254254
def internal_get_value(
255255
array_values: Union[Sequence[float], np.ndarray[Any, np.dtype[np.float64]], readonly_ptr_wrapper_double],

tests/test_highspy.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2059,3 +2059,31 @@ def test_repr_str(self):
20592059
expr = y + x <= 5
20602060
self.assertEqual(repr(expr), "-inf <= 1.0_v1 1.0_v0 <= 5.0")
20612061
self.assertEqual(str(expr), "-inf <= 1.0_v0 1.0_v1 <= 5.0")
2062+
2063+
def test_lexicographic_optimization(self):
2064+
# max f1 = X1
2065+
# max f2 = 3 X1 + 4 X2
2066+
# st X1 <= 2
2067+
# X2 <= 4
2068+
# 5 X1 + 4 X2 <= 20
2069+
model = highspy.Highs()
2070+
model.setOptionValue("blend_multi_objectives", False)
2071+
num_vars = 2
2072+
model.addVars(num_vars, np.array([0.0, 0.0]), np.array([2.0, 4.0]))
2073+
obj1 = highspy.HighsLinearObjective()
2074+
obj1.offset = 0
2075+
obj1.coefficients = [1, 0]
2076+
obj1.priority = 2
2077+
obj1.rel_tolerance = 0.1
2078+
obj1.abs_tolerance = 0.2
2079+
obj2 = highspy.HighsLinearObjective()
2080+
obj2.offset=0
2081+
obj2.coefficients=[3, 4]
2082+
obj2.priority=1
2083+
model.addLinearObjective(obj1)
2084+
model.addLinearObjective(obj2)
2085+
model.addRow(0.0, 20.0, num_vars, np.arange(num_vars), np.array([5.0, 4.0]))
2086+
model.run()
2087+
2088+
status = model.getModelStatus()
2089+
self.assertEqual(status, highspy.HighsModelStatus.kOptimal)

0 commit comments

Comments
 (0)