diff --git a/src/omlt/base/__init__.py b/src/omlt/base/__init__.py index 7f41372e..d588186d 100644 --- a/src/omlt/base/__init__.py +++ b/src/omlt/base/__init__.py @@ -1,4 +1,4 @@ -from omlt.base.language import DEFAULT_MODELING_LANGUAGE +from omlt.base.language import DEFAULT_MODELING_LANGUAGE # noqa: I001 from omlt.base.constraint import ( OmltConstraint, diff --git a/src/omlt/base/constraint.py b/src/omlt/base/constraint.py index a66f749f..1d847bc2 100644 --- a/src/omlt/base/constraint.py +++ b/src/omlt/base/constraint.py @@ -61,7 +61,7 @@ def __init__( self.format = lang - def keys(self, sort=False): + def keys(self, *, sort=False): # noqa: ARG002 yield from self._index_set diff --git a/src/omlt/base/expression.py b/src/omlt/base/expression.py index ffbdbd6e..509a2900 100644 --- a/src/omlt/base/expression.py +++ b/src/omlt/base/expression.py @@ -39,7 +39,7 @@ def log(self): @abstractmethod def tanh(self): - """Return an expression representing the hyperbolic tangent of this expression.""" + """Return an expression representing the hyperbolic tangent of expression.""" @abstractmethod def __add__(self, other): @@ -85,8 +85,7 @@ def __ge__(self, other): class OmltExprFactory: def __init__(self): self.exprs = { - subclass.format: subclass - for subclass in OmltExpr.__subclasses__() + subclass.format: subclass for subclass in OmltExpr.__subclasses__() } def register(self, lang, varclass): diff --git a/src/omlt/base/julia.py b/src/omlt/base/julia.py index 23e5c810..8d73f4a7 100644 --- a/src/omlt/base/julia.py +++ b/src/omlt/base/julia.py @@ -19,12 +19,15 @@ Jl.seval("import JuMP") jump = Jl.JuMP +PAIR = 2 +EXPR_TWO = 2 +EXPR_THREE = 3 # Elements class JuMPVarInfo: - def __init__( + def __init__( # noqa: PLR0913 self, lower_bound=None, upper_bound=None, @@ -175,11 +178,11 @@ def tanh(self): class OmltScalarJuMP(OmltScalar): format = "jump" - def __init__(self, *, binary=False, **kwargs): + def __init__(self, *, binary=False, **kwargs: Any): super().__init__() self._bounds = kwargs.pop("bounds", None) - if isinstance(self._bounds, tuple) and len(self._bounds) == 2: + if isinstance(self._bounds, tuple) and len(self._bounds) == PAIR: _lb = self._bounds[0] _ub = self._bounds[1] elif self._bounds is None: @@ -295,9 +298,7 @@ class OmltIndexedJuMP(OmltIndexed): def __init__(self, *indexes: Any, binary: bool = False, **kwargs: Any): index_set = indexes[0] - i_dict = {} - for i, val in enumerate(index_set): - i_dict[i] = val + i_dict = dict(enumerate(index_set)) self._index_set = tuple(i_dict[i] for i in range(len(index_set))) self._bounds = kwargs.pop("bounds", None) @@ -305,7 +306,7 @@ def __init__(self, *indexes: Any, binary: bool = False, **kwargs: Any): if isinstance(self._bounds, dict) and len(self._bounds) == len(self._index_set): _lb = {k: v[0] for k, v in self._bounds.items()} _ub = {k: v[1] for k, v in self._bounds.items()} - elif isinstance(self._bounds, tuple) and len(self._bounds) == 2: + elif isinstance(self._bounds, tuple) and len(self._bounds) == PAIR: _lb = {i: self._bounds[0] for i in self._index_set} _ub = {i: self._bounds[1] for i in self._index_set} elif self._bounds is None: @@ -391,7 +392,7 @@ def __iter__(self): """Return an iterator of the component data keys.""" return self._vars.__iter__() - def construct(self, data=None): + def construct(self, *, data=None): # noqa: ARG002 for idx in self._index_set: if isinstance(idx, int): name = str(self.name) + "[" + str(idx) + "]" @@ -449,7 +450,7 @@ def __init__(self, *indexes: Any, **kwargs: Any): self.format = "jump" self._jumpcons = {idx: None for idx in self._index_set[0]} - def keys(self, sort=False): + def keys(self, *, sort=False): # noqa: ARG002 yield from self._index_set def __setitem__(self, label, item): @@ -477,7 +478,7 @@ def __init__(self, expr): "d is exp, log, or tanh. %s was provided", expr, ) - if len(expr) == 3: + if len(expr) == EXPR_THREE: if expr[1] == "+": self._jumpexpr = self.add(expr[0], expr[2]) elif expr[1] == "-": @@ -488,7 +489,7 @@ def __init__(self, expr): self._jumpexpr = self.divide(expr[0], expr[2]) else: raise ValueError(msg) - elif len(expr) == 2: + elif len(expr) == EXPR_TWO: if expr[0] == "exp": self._jumpexpr = self.exponent(expr[1]) elif expr[0] == "log": @@ -533,7 +534,7 @@ def add(self, a, b): msg = ("Unrecognized types for addition, %s, %s", type(a), type(b)) raise TypeError(msg) - def subtract(self, a, b): + def subtract(self, a, b): # noqa: PLR0911 if isinstance(a, (int, float)) and isinstance(b, (JumpVar, OmltScalarJuMP)): return jump.AffExpr(a, jump.OrderedDict([(b.varref, -1)])) if isinstance(a, JumpVar) and isinstance(b, (int, float)): @@ -760,10 +761,6 @@ def __setattr__(self, name, value): elif isinstance(value, OmltConstraintIndexedJuMP): value.model = self value.name = name - # for idx, constr in value._jumpcons: - # self._conrefs[(name, idx)] = jump.add_constraint( - # self._jumpmodel, constr._jumpcon, (name, idx) - # ) elif isinstance(value, OmltBlockCore): value.name = name value._parent = self diff --git a/src/omlt/gbt/gbt_formulation.py b/src/omlt/gbt/gbt_formulation.py index badbfaf7..e126e4b8 100644 --- a/src/omlt/gbt/gbt_formulation.py +++ b/src/omlt/gbt/gbt_formulation.py @@ -16,12 +16,12 @@ class GBTBigMFormulation(_PyomoFormulation): constraints to enforce splitting rules according to: References: - ---------- + ----------- * Misic, V. "Optimization of tree ensembles." Operations Research 68.5 (2020): 1605-1624. * Mistry, M., et al. "Mixed-integer convex nonlinear optimization with gradient-boosted trees embedded." - INFORMS Journal on Computing (2020). + INFORMS Journal on Computing (2020). Parameters: tree_ensemble_structure (GradientBoostedTreeModel): @@ -63,7 +63,7 @@ def _build_formulation(self): ) -def add_formulation_to_block(block, model_definition, input_vars, output_vars): # noqa: C901, PLR0915 +def add_formulation_to_block(block, model_definition, input_vars, output_vars): # noqa: C901, PLR0912, PLR0915 r"""Adds the gradient-boosted trees formulation to the given Pyomo block. .. math:: @@ -89,12 +89,12 @@ def add_formulation_to_block(block, model_definition, input_vars, output_vars): References: - ---------- + ----------- * Misic, V. "Optimization of tree ensembles." Operations Research 68.5 (2020): 1605-1624. * Mistry, M., et al. "Mixed-integer convex nonlinear optimization with gradient-boosted trees embedded." - INFORMS Journal on Computing (2020). + INFORMS Journal on Computing (2020). Parameters: block (Block): diff --git a/src/omlt/neuralnet/layers/full_space.py b/src/omlt/neuralnet/layers/full_space.py index 0766b584..5f749d0c 100644 --- a/src/omlt/neuralnet/layers/full_space.py +++ b/src/omlt/neuralnet/layers/full_space.py @@ -6,7 +6,7 @@ from omlt.neuralnet.layer import ConvLayer2D, PoolingLayer2D -def full_space_dense_layer(net_block, net, layer_block, layer): +def full_space_dense_layer(net_block, net, layer_block, layer): # noqa: PLR0912 r"""Add full-space formulation of the dense layer to the block. .. math:: diff --git a/src/omlt/neuralnet/layers/partition_based.py b/src/omlt/neuralnet/layers/partition_based.py index 644c70d4..0ab82072 100644 --- a/src/omlt/neuralnet/layers/partition_based.py +++ b/src/omlt/neuralnet/layers/partition_based.py @@ -17,7 +17,7 @@ def default_partition_split_func(w, n): return np.array_split(sorted_indexes, n) -def partition_based_dense_relu_layer(net_block, net, layer_block, layer, split_func): +def partition_based_dense_relu_layer(net_block, net, layer_block, layer, split_func): # noqa: C901,PLR0912,PLR0915 r"""Partition-based ReLU activation formulation. Generates the constraints for the ReLU activation function: diff --git a/src/omlt/neuralnet/nn_formulation.py b/src/omlt/neuralnet/nn_formulation.py index fe18349a..bc6d16b3 100644 --- a/src/omlt/neuralnet/nn_formulation.py +++ b/src/omlt/neuralnet/nn_formulation.py @@ -141,7 +141,7 @@ def output_indexes(self): return network_outputs[0].output_indexes -def _build_neural_network_formulation( # noqa: C901 +def _build_neural_network_formulation( # noqa: C901,PLR0912,PLR0915 block, network_structure, layer_constraints, activation_constraints ): """Adds the neural network formulation to the given Pyomo block. @@ -362,7 +362,7 @@ def __init__(self, network_structure, activation_functions=None): def _supported_default_activation_functions(self): return dict(_DEFAULT_ACTIVATION_FUNCTIONS) - def _build_formulation(self): + def _build_formulation(self): # noqa: C901,PLR0912 _setup_scaled_inputs_outputs( self.block, self.__scaling_object, self.__scaled_input_bounds ) @@ -413,11 +413,6 @@ def _build_formulation(self): input_layer_block.z[output_index] == block.scaled_inputs[idx_0] ) - # @input_layer_block.Expression(input_layer.output_indexes) - # def z(b, *output_index): - # pb = b.parent_block() - # return pb.scaled_inputs[output_index] - # loop over the layers and build the expressions for layer in layers: if isinstance(layer, InputLayer): # skip the InputLayer @@ -530,7 +525,7 @@ def __init__(self, network_structure, split_func=None): self.__split_func = split_func - def _build_formulation(self): # noqa: C901 + def _build_formulation(self): # noqa: C901,PLR0912,PLR0915 _setup_scaled_inputs_outputs( self.block, self.__scaling_object, self.__scaled_input_bounds ) diff --git a/tests/base/test_jump.py b/tests/base/test_jump.py index 6580a35b..3676eaf4 100644 --- a/tests/base/test_jump.py +++ b/tests/base/test_jump.py @@ -21,6 +21,11 @@ from omlt import OffsetScaling +TWO = 2 +FOUR = 4 +FIVE = 5 +SIX = 6 +ELEVEN = 11 @pytest.mark.skipif(not julia_available, reason="Need JuMP for this test") def test_variable_jump(): @@ -28,10 +33,10 @@ def test_variable_jump(): assert v.name is None assert v.lb == 0 - assert v.ub == 5 + assert v.ub == FIVE v.value = 4 - assert v.value == 4 + assert v.value == FOUR @pytest.mark.skipif(not julia_available, reason="Need JuMP for this test") @@ -58,7 +63,7 @@ def test_expression_linear_jump(): var_plus_three = jump_block.v1 + 3 assert isinstance(var_plus_three, OmltExprJuMP) - assert var_plus_three() == 5 + assert var_plus_three() == FIVE three_minus_var = 3 - jump_block.v1 assert isinstance(three_minus_var, OmltExprJuMP) @@ -66,23 +71,23 @@ def test_expression_linear_jump(): three_times_var = 3 * jump_block.v1 assert isinstance(three_times_var, OmltExprJuMP) - assert three_times_var() == 6 + assert three_times_var() == SIX var_times_three = jump_block.v1 * 3 assert isinstance(var_times_three, OmltExprJuMP) - assert var_times_three() == 6 + assert var_times_three() == SIX expr_sum = var_plus_three + var_times_three assert isinstance(expr_sum, OmltExprJuMP) - assert expr_sum() == 11 + assert expr_sum() == ELEVEN var_minus_expr = element2 - three_minus_var assert isinstance(var_minus_expr, OmltExprJuMP) - assert var_minus_expr() == 2 + assert var_minus_expr() == TWO expr_minus_expr = var_plus_three - three_minus_var assert isinstance(expr_minus_expr, OmltExprJuMP) - assert expr_minus_expr() == 4 + assert expr_minus_expr() == FOUR expr_div_int = var_plus_three / 5 assert isinstance(expr_div_int, OmltExprJuMP)