Skip to content

Commit

Permalink
[#93] Add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
simonbowly committed Nov 14, 2024
1 parent da26563 commit a37a03d
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 0 deletions.
91 changes: 91 additions & 0 deletions tests/test_constraints.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@

from .utils import GurobiModelTestCase

GUROBIPY_MAJOR_VERSION, *_ = gp.gurobi.version()


class TestAddConstrsFromDataFrame(GurobiModelTestCase):
def test_scalar_rhs(self):
Expand Down Expand Up @@ -317,6 +319,95 @@ def test_nonpython_columnnames(self):
self.assertEqual(row.getCoeff(0), 1.0)


@unittest.skipIf(
GUROBIPY_MAJOR_VERSION < 12,
"Nonlinear constraints are only supported for Gurobi 12 and later",
)
class TestNonlinearFromDataFrame(GurobiModelTestCase):
def test_varseries_nlseries(self):
# y_i == exp(x_i)
from gurobipy import nlfunc

index = pd.RangeIndex(5)
df = pd.DataFrame(
dict(
x=add_vars_from_index(self.model, index, name="x"),
y=add_vars_from_index(self.model, index, name="y"),
)
)

df["expr"] = df["x"].apply(nlfunc.exp)

constrs = add_constrs_from_dataframe(
self.model, df, "y", GRB.EQUAL, "expr", name="nonlinear"
)

# Constraints added to model
self.model.update()
self.assertEqual(self.model.NumGenConstrs, 5)

# Returned series has the right structure
self.assertIsInstance(constrs, pd.Series)
self.assertEqual(constrs.name, "nonlinear")
assert_index_equal(constrs.index, index)

# Check data in model
for ind, constr in constrs.items():
self.assertIsInstance(constr, gp.GenConstr)
self.assertEqual(constr.GenConstrName, f"nonlinear[{ind}]")
self.assertEqual(constr.GenConstrType, GRB.GENCONSTR_NL)
self.assert_nlconstr_equal(
constr,
df.loc[ind, "y"],
[
(GRB.OPCODE_EXP, -1.0, -1),
(GRB.OPCODE_VARIABLE, df.loc[ind, "x"], 0),
],
)

def test_left_nlexpr(self):
# exp(x_i) == y_i
from gurobipy import nlfunc

index = pd.RangeIndex(5)
df = pd.DataFrame(
dict(
x=add_vars_from_index(self.model, index, name="x"),
y=add_vars_from_index(self.model, index, name="y"),
)
)

df["expr"] = df["x"].apply(nlfunc.exp)

with self.assertRaisesRegex(
ValueError, "Nonlinear constraints must be in the form"
):
constrs = add_constrs_from_dataframe(
self.model, df, "expr", GRB.EQUAL, "y", name="nonlinear"
)

def test_inequality(self):
# y_i <= exp(x_i)
from gurobipy import nlfunc

index = pd.RangeIndex(5)
df = pd.DataFrame(
dict(
x=add_vars_from_index(self.model, index, name="x"),
y=add_vars_from_index(self.model, index, name="y"),
)
)

df["expr"] = df["x"].apply(nlfunc.exp)

with self.assertRaisesRegex(
ValueError, "Nonlinear constraints must be in the form"
):
constrs = add_constrs_from_dataframe(
self.model, df, "y", GRB.LESS_EQUAL, "expr", name="nonlinear"
)


class TestAddConstrsFromSeries(GurobiModelTestCase):
def test_bothseries(self):
# linear series <= linear series
Expand Down
16 changes: 16 additions & 0 deletions tests/utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import unittest

import gurobipy as gp
from gurobipy import GRB


class GurobiModelTestCase(unittest.TestCase):
Expand Down Expand Up @@ -36,3 +37,18 @@ def assert_quadexpr_equal(self, expr1, expr2):
self.assertTrue(expr1.getVar1(i).sameAs(expr2.getVar1(i)))
self.assertTrue(expr1.getVar2(i).sameAs(expr2.getVar2(i)))
self.assertEqual(expr1.getCoeff(i), expr2.getCoeff(i))

def assert_nlconstr_equal(self, genconstr, resvar_true, tree):
resvar, opcode_array, data_array, parent_array = self.model.getGenConstrNLAdv(
genconstr
)
self.assertIs(resvar, resvar_true)
for opcode, data, parent, (opcode_true, data_true, parent_true) in zip(
opcode_array, data_array, parent_array, tree
):
self.assertEqual(opcode, opcode_true)
if opcode == GRB.OPCODE_VARIABLE:
self.assertIs(data, data_true)
else:
self.assertEqual(data, data_true)
self.assertEqual(parent, parent_true)

0 comments on commit a37a03d

Please sign in to comment.