-
Notifications
You must be signed in to change notification settings - Fork 97
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added the simple mip interface (untested)
- Loading branch information
Showing
13 changed files
with
1,260 additions
and
106 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -43,6 +43,7 @@ | |
|
||
PGM_AVAILABLE = True | ||
except ImportError: | ||
pgm = None | ||
PGM_AVAILABLE = False | ||
|
||
''' | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# GridCal | ||
# Copyright (C) 2015 - 2023 Santiago Peñate Vera | ||
# | ||
# This program is free software; you can redistribute it and/or | ||
# modify it under the terms of the GNU Lesser General Public | ||
# License as published by the Free Software Foundation; either | ||
# version 3 of the License, or (at your option) any later version. | ||
# | ||
# This program is distributed in the hope that it will be useful, | ||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
# Lesser General Public License for more details. | ||
# | ||
# You should have received a copy of the GNU Lesser General Public License | ||
# along with this program; if not, write to the Free Software Foundation, | ||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
|
||
from GridCalEngine.Utils.MIP.SimpleMip.lpexp import LpExp | ||
from GridCalEngine.Utils.MIP.SimpleMip.lpvar import LpVar | ||
from GridCalEngine.Utils.MIP.SimpleMip.problem import LpModel, get_available_mip_solvers, set_var_bounds |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
# GridCal | ||
# Copyright (C) 2015 - 2023 Santiago Peñate Vera | ||
# | ||
# This program is free software; you can redistribute it and/or | ||
# modify it under the terms of the GNU Lesser General Public | ||
# License as published by the Free Software Foundation; either | ||
# version 3 of the License, or (at your option) any later version. | ||
# | ||
# This program is distributed in the hope that it will be useful, | ||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
# Lesser General Public License for more details. | ||
# | ||
# You should have received a copy of the GNU Lesser General Public License | ||
# along with this program; if not, write to the Free Software Foundation, | ||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
from __future__ import annotations | ||
from typing import TYPE_CHECKING | ||
|
||
if TYPE_CHECKING: # Only imports the below statements during type checking | ||
from GridCalEngine.Utils.MIP.SimpleMip.problem import Problem | ||
|
||
try: | ||
import highspy | ||
HIGHS_AVAILABLE = True | ||
except ImportError: | ||
highspy = None | ||
HIGHS_AVAILABLE = False | ||
|
||
|
||
def solve_with_highs(mip: Problem, verbose: int = 0): | ||
""" | ||
Solve MIP using Highs via its python interface | ||
:param mip: Problem to be solved (results are inserted in-place) | ||
:param verbose: print info? for values > 0 | ||
""" | ||
if highspy is None: | ||
raise Exception("No highspy available, try installing with: pip install highspy") | ||
|
||
# declare the solver | ||
h = highspy.highs.Highs() | ||
|
||
# declare the LP problem | ||
lp = highspy.highs.HighsLp() | ||
|
||
# set the sense | ||
lp.sense_ = highspy.highs.ObjSense.kMinimize if mip.is_minimize() else highspy.highs.ObjSense.kMaximize | ||
|
||
# set the var information | ||
lp.col_lower_, lp.col_cost_, lp.col_upper_, is_int_list = mip.get_var_data() | ||
lp.offset_ = mip.objective.offset | ||
|
||
for i in is_int_list: | ||
lp.integrality_.append(i) | ||
|
||
# set the constraints information | ||
lp.row_lower_, A, lp.row_upper_ = mip.get_coefficients_data() | ||
lp.num_col_ = A.shape[1] | ||
lp.num_row_ = A.shape[0] | ||
|
||
lp.a_matrix_.start_ = A.indptr | ||
lp.a_matrix_.index_ = A.indices | ||
lp.a_matrix_.value_ = A.data | ||
|
||
# send the model to the solver | ||
h.passModel(lp) | ||
|
||
# solve | ||
h.run() | ||
|
||
# gather results | ||
solution = h.getSolution() | ||
basis = h.getBasis() | ||
info = h.getInfo() | ||
model_status = h.getModelStatus() | ||
|
||
if verbose > 0: | ||
print("Model status = ", h.modelStatusToString(model_status)) | ||
print("Optimal objective = ", info.objective_function_value) | ||
print("Iteration count = ", info.simplex_iteration_count) | ||
print("Primal solution status = ", h.solutionStatusToString(info.primal_solution_status) ) | ||
|
||
mip.set_solution(col_values=solution.col_value, | ||
col_duals=solution.col_dual, | ||
row_values=solution.row_value, | ||
row_duals=solution.row_dual, | ||
fixed_values=info.objective_function_value, | ||
optimal_values=model_status == highspy.highs.HighsModelStatus.kOptimal) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
# GridCal | ||
# Copyright (C) 2015 - 2023 Santiago Peñate Vera | ||
# | ||
# This program is free software; you can redistribute it and/or | ||
# modify it under the terms of the GNU Lesser General Public | ||
# License as published by the Free Software Foundation; either | ||
# version 3 of the License, or (at your option) any later version. | ||
# | ||
# This program is distributed in the hope that it will be useful, | ||
# but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
# Lesser General Public License for more details. | ||
# | ||
# You should have received a copy of the GNU Lesser General Public License | ||
# along with this program; if not, write to the Free Software Foundation, | ||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
from __future__ import annotations | ||
from typing import Tuple, TYPE_CHECKING | ||
|
||
if TYPE_CHECKING: # Only imports the below statements during type checking | ||
from GridCalEngine.Utils.MIP.SimpleMip.lpexp import LpExp | ||
from GridCalEngine.Utils.MIP.SimpleMip.lpvar import LpVar | ||
|
||
|
||
class LpCst: | ||
""" | ||
Constraint | ||
""" | ||
def __init__(self, linear_expression: LpExp, sense: str, coefficient: float, | ||
name="", internal_index: int = 0): | ||
""" | ||
constraint (<=, ==, >=) rhs | ||
:param linear_expression: | ||
:param sense: <=, ==, >= | ||
:param coefficient: | ||
:param name: | ||
:param internal_index: | ||
""" | ||
assert sense in ["<=", "==", ">="] | ||
|
||
self.name = name | ||
self.linear_expression = linear_expression | ||
self.sense = sense | ||
self.coefficient = coefficient # Right-hand side value | ||
self._index: int = internal_index # internal index to the solver | ||
|
||
def copy(self) -> "LpCst": | ||
""" | ||
Make a deep copy of this constraint | ||
:return: Constraint | ||
""" | ||
return LpCst(linear_expression=self.linear_expression.copy(), | ||
sense=self.sense, | ||
coefficient=self.coefficient, | ||
name=self.name, | ||
internal_index=self._index) | ||
|
||
def get_bounds(self) -> Tuple[float, float]: | ||
""" | ||
Get the constraint bounds | ||
:return: lhs <= constraint <= rhs | ||
""" | ||
MIP_INF = 1e20 | ||
if self.sense == '==': | ||
return self.coefficient, self.coefficient | ||
elif self.sense == '<=': | ||
return -MIP_INF, self.coefficient | ||
elif self.sense == '>=': | ||
return self.coefficient, MIP_INF | ||
else: | ||
raise Exception(f"Invalid sense: {self.sense}") | ||
|
||
def set_index(self, index: int) -> None: | ||
""" | ||
Set the internal indexing | ||
:param index: constraint index in the solver | ||
""" | ||
self._index = index | ||
|
||
def get_index(self) -> int: | ||
""" | ||
Get internal index | ||
:return: int | ||
""" | ||
return self._index | ||
|
||
def add_term(self, var: LpVar, coeff: float): | ||
""" | ||
Add a term to the constraint | ||
:param var: Variable | ||
:param coeff: coefficient | ||
""" | ||
self.linear_expression += coeff * var | ||
|
||
def add_var(self, var: LpVar): | ||
""" | ||
Add a term to the constraint | ||
:param var: Variable | ||
""" | ||
self.linear_expression += var |
Oops, something went wrong.