diff --git a/pyomo/contrib/piecewise/tests/test_nonlinear_to_pwl.py b/pyomo/contrib/piecewise/tests/test_nonlinear_to_pwl.py index d0f5acc2ff1..6b1e3f9f89f 100644 --- a/pyomo/contrib/piecewise/tests/test_nonlinear_to_pwl.py +++ b/pyomo/contrib/piecewise/tests/test_nonlinear_to_pwl.py @@ -116,27 +116,28 @@ def test_log_constraint_random_grid(self): self.check_pw_linear_log_x(m, pwlf, x1, x2, x3) - def test_log_constraint_lmt_uniform_sample(self): - m = self.make_model() + # def test_log_constraint_lmt_uniform_sample(self): + # m = self.make_model() - n_to_pwl = TransformationFactory('contrib.piecewise.nonlinear_to_pwl') - n_to_pwl.apply_to( - m, - num_points=3, - domain_partitioning_method=DomainPartitioningMethod.LINEAR_MODEL_TREE_UNIFORM, - ) - - # cons is transformed - self.assertFalse(m.cons.active) - - pwlf = list(m.component_data_objects(PiecewiseLinearFunction, - descend_into=True)) - self.assertEqual(len(pwlf), 1) - pwlf = pwlf[0] - - set_trace() - - x1 = 4.370861069626263 - x2 = 7.587945476302646 - x3 = 9.556428757689245 - self.check_pw_linear_log_x(m, pwlf, x1, x2, x3) + # n_to_pwl = TransformationFactory('contrib.piecewise.nonlinear_to_pwl') + # n_to_pwl.apply_to( + # m, + # num_points=3, + # domain_partitioning_method=DomainPartitioningMethod.LINEAR_MODEL_TREE_UNIFORM, + # ) + + # # cons is transformed + # self.assertFalse(m.cons.active) + + # pwlf = list(m.component_data_objects(PiecewiseLinearFunction, + # descend_into=True)) + # self.assertEqual(len(pwlf), 1) + # pwlf = pwlf[0] + + # set_trace() + + # # TODO + # x1 = 4.370861069626263 + # x2 = 7.587945476302646 + # x3 = 9.556428757689245 + # self.check_pw_linear_log_x(m, pwlf, x1, x2, x3) diff --git a/pyomo/contrib/piecewise/transform/nonlinear_to_pwl.py b/pyomo/contrib/piecewise/transform/nonlinear_to_pwl.py index d819e893d5f..408efdb4b32 100644 --- a/pyomo/contrib/piecewise/transform/nonlinear_to_pwl.py +++ b/pyomo/contrib/piecewise/transform/nonlinear_to_pwl.py @@ -12,10 +12,7 @@ import enum import itertools -from lineartree import LinearTreeRegressor -import lineartree import logging -import numpy as np from pyomo.environ import ( TransformationFactory, @@ -41,6 +38,8 @@ from pyomo.common.autoslots import AutoSlots from pyomo.common.collections import ComponentMap, ComponentSet from pyomo.common.config import ConfigDict, ConfigValue, PositiveInt, InEnum +from pyomo.common.dependencies import attempt_import +from pyomo.common.dependencies import numpy as np from pyomo.common.modeling import unique_component_name from pyomo.core.expr.numeric_expr import SumExpression from pyomo.core.expr import identify_variables @@ -54,13 +53,12 @@ from pyomo.network import Port from pyomo.repn.quadratic import QuadraticRepnVisitor -from sklearn.linear_model import LinearRegression -import random -from sklearn.metrics import mean_squared_error -from sklearn.model_selection import train_test_split +lineartree, lineartree_available = attempt_import('lineartree') +sklearn_lm, sklearn_available = attempt_import('sklearn.linear_model') logger = logging.getLogger(__name__) + class DomainPartitioningMethod(enum.IntEnum): RANDOM_GRID = 1 UNIFORM_GRID = 2 @@ -117,22 +115,15 @@ def get_points_lmt(points, bounds, func, seed): y_list = [] for point in points: y_list.append(func(*point)) - regr = LinearTreeRegressor( - LinearRegression(), + # ESJ: Do we really need the sklearn dependency to get LinearRegression?? + regr = lineartree.LinearTreeRegressor( + sklearn_lm.LinearRegression(), criterion='mse', max_bins=120, min_samples_leaf=4, max_depth=5, ) - - # Using train_test_split is silly. TODO: remove this and just sample my own - # extra points if I want to estimate the error. - X_train, X_test, y_train, y_test = train_test_split( - x_list, y_list, test_size=0.2, random_state=seed - ) - regr.fit(X_train, y_train) - y_pred = regr.predict(X_test) - error = mean_squared_error(y_test, y_pred) + regr.fit(x_list, y_list) leaves, splits, ths = parse_linear_tree_regressor(regr, bounds) @@ -572,6 +563,7 @@ def _get_bounds_list(self, var_list, parent_component): bounds = [] for v in var_list: if None in v.bounds: + # ESJ TODO: Con is undefined--this is a bug! raise ValueError( "Cannot automatically approximate constraints with unbounded " "variables. Var '%s' appearining in component '%s' is missing "