diff --git a/.github/workflows/ruff_action.yml b/.github/workflows/ruff_action.yml new file mode 100644 index 00000000..15b907d0 --- /dev/null +++ b/.github/workflows/ruff_action.yml @@ -0,0 +1,8 @@ +name: Ruff +on: [ push, pull_request ] +jobs: + ruff: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: astral-sh/ruff-action@v2 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e2030306..cb3bb7a5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,12 +14,6 @@ repos: files: (^(src|tests)/)|(^[^/]*$) args: [--in-place, --remove-all-unused-imports, --recursive, --ignore-init-module-imports] - - repo: https://github.com/pycqa/isort - rev: 5.12.0 - hooks: - - id: isort - args: ["--profile", "black", "--filter-files"] - - repo: https://github.com/kynan/nbstripout rev: 0.6.0 hooks: @@ -31,13 +25,17 @@ repos: - id: flake8 args: ["--count", "--select=E9,F63,F7,F82", "--show-source", "--statistics"] - - repo: https://github.com/psf/black - rev: 23.10.1 - hooks: - - id: black-jupyter - language_version: python3.11 - language: python - types: [python] + - repo: https://github.com/astral-sh/ruff-pre-commit + # Ruff version. + rev: v0.8.2 + hooks: + # Run the linter. + - id: ruff + types_or: [ python, pyi, jupyter ] + args: [ --fix ] + # Run the formatter. + - id: ruff-format + types_or: [ python, pyi, jupyter ] - repo: local hooks: diff --git a/docs/examples/example2_student_admission.py b/docs/examples/example2_student_admission.py index 046227fb..ce31f37d 100644 --- a/docs/examples/example2_student_admission.py +++ b/docs/examples/example2_student_admission.py @@ -81,17 +81,13 @@ """ -import sys - import gurobipy as gp import gurobipy_pandas as gppd import numpy as np import pandas as pd -from matplotlib import pyplot as plt from sklearn.linear_model import LogisticRegression from sklearn.pipeline import make_pipeline from sklearn.preprocessing import StandardScaler -from sklearn.tree import DecisionTreeRegressor from gurobi_ml import add_predictor_constr diff --git a/docs/examples/example4_price_optimization.py b/docs/examples/example4_price_optimization.py index ee941661..cdafe8fa 100644 --- a/docs/examples/example4_price_optimization.py +++ b/docs/examples/example4_price_optimization.py @@ -75,14 +75,20 @@ # the data. # -import warnings - +import gurobipy as gp +import gurobipy_pandas as gppd import matplotlib.pyplot as plt import numpy as np import pandas as pd import seaborn as sns -import sklearn -from sklearn import tree +from sklearn.compose import make_column_transformer +from sklearn.linear_model import LinearRegression +from sklearn.metrics import r2_score +from sklearn.model_selection import train_test_split +from sklearn.pipeline import make_pipeline +from sklearn.preprocessing import OneHotEncoder, StandardScaler + +from gurobi_ml import add_predictor_constr ###################################################################### # The dataset from HAB contains sales data for the years 2019-2022. This @@ -310,8 +316,6 @@ def peak_season(row): # weights using ``Scikit-learn``. # -from sklearn.model_selection import train_test_split - X = df[["region", "price", "year", "peak"]] y = df["units_sold"] # Split the data for training and testing @@ -330,9 +334,6 @@ def peak_season(row): # ``make_column_transformer``. # -from sklearn.compose import make_column_transformer -from sklearn.preprocessing import OneHotEncoder, StandardScaler - feat_transform = make_column_transformer( (OneHotEncoder(drop="first"), ["region"]), (StandardScaler(), ["price", "year"]), @@ -349,10 +350,6 @@ def peak_season(row): # Define it and train it. # -from sklearn.linear_model import LinearRegression -from sklearn.metrics import r2_score -from sklearn.pipeline import make_pipeline - lin_reg = make_pipeline(feat_transform, LinearRegression()) lin_reg.fit(X_train, y_train) @@ -497,9 +494,6 @@ def peak_season(row): # dataframe. # -import gurobipy as gp -import gurobipy_pandas as gppd - m = gp.Model("Avocado_Price_Allocation") p = gppd.add_vars(m, data, name="price", lb=a_min, ub=a_max) @@ -655,8 +649,6 @@ def peak_season(row): # to insert the constraints linking the features and the demand. # -from gurobi_ml import add_predictor_constr - pred_constr = add_predictor_constr(m, lin_reg, feats, d) pred_constr.print_stats() diff --git a/docs/examples_userguide/example_simple.py b/docs/examples_userguide/example_simple.py index 87a92b2e..60a2ae49 100644 --- a/docs/examples_userguide/example_simple.py +++ b/docs/examples_userguide/example_simple.py @@ -23,7 +23,6 @@ import gurobipy as gp import numpy as np from sklearn.datasets import make_regression -from sklearn.metrics import mean_squared_error from sklearn.neural_network import MLPRegressor from gurobi_ml import add_predictor_constr diff --git a/notebooks/Functions_approx/2DPeakFunction skorch polynomials.ipynb b/notebooks/Functions_approx/2DPeakFunction skorch polynomials.ipynb index 3099abdb..392ed16f 100644 --- a/notebooks/Functions_approx/2DPeakFunction skorch polynomials.ipynb +++ b/notebooks/Functions_approx/2DPeakFunction skorch polynomials.ipynb @@ -112,6 +112,8 @@ "# Create a small class to apply polynomial features and convert\n", "\n", "from sklearn.base import BaseEstimator, TransformerMixin\n", + "\n", + "\n", "class MyPolynomialFeatures(BaseEstimator, TransformerMixin):\n", " def __init__(self):\n", " self.poly_feat = PolynomialFeatures()\n", @@ -136,12 +138,12 @@ "hs = 16\n", "nn_regression = NeuralNetRegressor(\n", " torch.nn.Sequential(\n", - " torch.nn.Linear(6, hs),\n", - " torch.nn.ReLU(),\n", - " torch.nn.Linear(hs, hs),\n", - " torch.nn.ReLU(),\n", - " torch.nn.Linear(hs, 1),\n", - "),\n", + " torch.nn.Linear(6, hs),\n", + " torch.nn.ReLU(),\n", + " torch.nn.Linear(hs, hs),\n", + " torch.nn.ReLU(),\n", + " torch.nn.Linear(hs, 1),\n", + " ),\n", " max_epochs=20,\n", " lr=0.1,\n", " iterator_train__shuffle=True,\n", @@ -246,7 +248,10 @@ "# the function to add a pytorch model on the pytorch model\n", "# - Register that function by associating it to the NeuralNetRegressor class\n", "def add_skorch_constr(gp_model, skorch_model, input_vars, output_vars=None, **kwargs):\n", - " return add_sequential_constr(gp_model, skorch_model.module, input_vars, output_vars, **kwargs)\n", + " return add_sequential_constr(\n", + " gp_model, skorch_model.module, input_vars, output_vars, **kwargs\n", + " )\n", + "\n", "\n", "register_predictor_constr(NeuralNetRegressor, add_skorch_constr)" ] @@ -260,7 +265,10 @@ "source": [ "# Now do the same for the polynomial features\n", "def add_my_polynomial_features_constr(gp_model, poly_feat, input_vars, **kwargs):\n", - " return add_polynomial_features_constr(gp_model, poly_feat.poly_feat, input_vars, **kwargs)\n", + " return add_polynomial_features_constr(\n", + " gp_model, poly_feat.poly_feat, input_vars, **kwargs\n", + " )\n", + "\n", "\n", "register_predictor_constr(MyPolynomialFeatures, add_my_polynomial_features_constr)" ] diff --git a/notebooks/Functions_approx/2DPeakFunction skorch.ipynb b/notebooks/Functions_approx/2DPeakFunction skorch.ipynb index 60df2652..bdf27c97 100644 --- a/notebooks/Functions_approx/2DPeakFunction skorch.ipynb +++ b/notebooks/Functions_approx/2DPeakFunction skorch.ipynb @@ -32,12 +32,9 @@ "from matplotlib import cm\n", "from matplotlib import pyplot as plt\n", "from sklearn import metrics\n", - "from sklearn.pipeline import make_pipeline\n", - "from sklearn.preprocessing import PolynomialFeatures\n", "\n", "from gurobi_ml import add_predictor_constr, register_predictor_constr\n", "\n", - "from gurobi_ml.sklearn import add_polynomial_features_constr\n", "from gurobi_ml.torch import add_sequential_constr" ] }, @@ -106,12 +103,12 @@ "hs = 30\n", "nn_regression = NeuralNetRegressor(\n", " torch.nn.Sequential(\n", - " torch.nn.Linear(2, hs),\n", - " torch.nn.ReLU(),\n", - " torch.nn.Linear(hs, hs),\n", - " torch.nn.ReLU(),\n", - " torch.nn.Linear(hs, 1),\n", - "),\n", + " torch.nn.Linear(2, hs),\n", + " torch.nn.ReLU(),\n", + " torch.nn.Linear(hs, hs),\n", + " torch.nn.ReLU(),\n", + " torch.nn.Linear(hs, 1),\n", + " ),\n", " max_epochs=20,\n", " lr=0.1,\n", " iterator_train__shuffle=True,\n", @@ -214,7 +211,10 @@ "# the function to add a pytorch model on the pytorch model\n", "# - Register that function by associating it to the NeuralNetRegressor class\n", "def add_skorch_constr(gp_model, skorch_model, input_vars, output_vars=None, **kwargs):\n", - " return add_sequential_constr(gp_model, skorch_model.module, input_vars, output_vars, **kwargs)\n", + " return add_sequential_constr(\n", + " gp_model, skorch_model.module, input_vars, output_vars, **kwargs\n", + " )\n", + "\n", "\n", "register_predictor_constr(NeuralNetRegressor, add_skorch_constr)" ] diff --git a/notebooks/Functions_approx/Parabola.ipynb b/notebooks/Functions_approx/Parabola.ipynb index 39717e0a..fdd48260 100644 --- a/notebooks/Functions_approx/Parabola.ipynb +++ b/notebooks/Functions_approx/Parabola.ipynb @@ -276,9 +276,7 @@ "metadata": {}, "outputs": [], "source": [ - "print(\n", - " f\"Maximal error in predicted values in solution {np.max(pconstr.get_error())}\"\n", - ")" + "print(f\"Maximal error in predicted values in solution {np.max(pconstr.get_error())}\")" ] }, { diff --git a/notebooks/Janos/Decision Tree.ipynb b/notebooks/Janos/Decision Tree.ipynb index a7e3d09a..aefe2b4b 100644 --- a/notebooks/Janos/Decision Tree.ipynb +++ b/notebooks/Janos/Decision Tree.ipynb @@ -135,10 +135,10 @@ "source": [ "m = gp.Model()\n", "\n", - "y = gppd.add_vars(m, studentsdata, name='enroll_probability')\n", + "y = gppd.add_vars(m, studentsdata, name=\"enroll_probability\")\n", "\n", "# Add variable for merit\n", - "studentsdata = studentsdata.gppd.add_vars(m, lb=0.0, ub=2.5, name='merit')\n", + "studentsdata = studentsdata.gppd.add_vars(m, lb=0.0, ub=2.5, name=\"merit\")\n", "\n", "# Keep only features\n", "studentsdata = studentsdata.loc[:, features]\n", diff --git a/notebooks/Janos/Gradient Boosting Regression.ipynb b/notebooks/Janos/Gradient Boosting Regression.ipynb index 12d9ea72..06e1ceab 100644 --- a/notebooks/Janos/Gradient Boosting Regression.ipynb +++ b/notebooks/Janos/Gradient Boosting Regression.ipynb @@ -131,10 +131,10 @@ "source": [ "m = gp.Model()\n", "\n", - "y = gppd.add_vars(m, studentsdata, name='enroll_probability')\n", + "y = gppd.add_vars(m, studentsdata, name=\"enroll_probability\")\n", "\n", "# Add variable for merit\n", - "studentsdata = studentsdata.gppd.add_vars(m, lb=0.0, ub=2.5, name='merit')\n", + "studentsdata = studentsdata.gppd.add_vars(m, lb=0.0, ub=2.5, name=\"merit\")\n", "\n", "# Keep only features\n", "studentsdata = studentsdata.loc[:, features]\n", diff --git a/notebooks/Janos/LightGBM.ipynb b/notebooks/Janos/LightGBM.ipynb index af941411..1cde8137 100644 --- a/notebooks/Janos/LightGBM.ipynb +++ b/notebooks/Janos/LightGBM.ipynb @@ -23,12 +23,10 @@ "source": [ "import gurobipy as gp\n", "import numpy as np\n", - "import math\n", "import pandas as pd\n", "import gurobipy_pandas as gppd\n", "from matplotlib import pyplot as plt\n", - "import lightgbm as lgb\n", - "from sklearn.metrics import r2_score" + "import lightgbm as lgb" ] }, { @@ -41,7 +39,8 @@ "%load_ext autoreload\n", "%autoreload 2\n", "import sys\n", - "sys.path.append('../../src')" + "\n", + "sys.path.append(\"../../src\")" ] }, { @@ -52,8 +51,7 @@ "outputs": [], "source": [ "from gurobi_ml import add_predictor_constr\n", - "from gurobi_ml import lightgbm\n", - "import gurobi_ml as gml" + "from gurobi_ml import lightgbm" ] }, { @@ -167,10 +165,10 @@ "source": [ "m = gp.Model()\n", "\n", - "y = gppd.add_vars(m, studentsdata, lb=-1e100, name='enroll_probability')\n", + "y = gppd.add_vars(m, studentsdata, lb=-1e100, name=\"enroll_probability\")\n", "\n", "# Add variable for merit\n", - "studentsdata = studentsdata.gppd.add_vars(m, lb=0.0, ub=2.5, name='merit')\n", + "studentsdata = studentsdata.gppd.add_vars(m, lb=0.0, ub=2.5, name=\"merit\")\n", "\n", "# Keep only features\n", "studentsdata = studentsdata.loc[:, features]\n", @@ -255,7 +253,9 @@ "pred_constr.remove()\n", "\n", "# Add new constraint setting epsilon to 1e-5\n", - "pred_constr = lightgbm.add_lgbmregressor_constr(m, regression, studentsdata, y, epsilon=1e-4)\n", + "pred_constr = lightgbm.add_lgbmregressor_constr(\n", + " m, regression, studentsdata, y, epsilon=1e-4\n", + ")\n", "\n", "pred_constr.print_stats()\n", "\n", diff --git a/notebooks/Janos/Random Forest.ipynb b/notebooks/Janos/Random Forest.ipynb index fdda5129..d389e0dd 100644 --- a/notebooks/Janos/Random Forest.ipynb +++ b/notebooks/Janos/Random Forest.ipynb @@ -130,10 +130,10 @@ "source": [ "m = gp.Model()\n", "\n", - "y = gppd.add_vars(m, studentsdata, name='enroll_probability')\n", + "y = gppd.add_vars(m, studentsdata, name=\"enroll_probability\")\n", "\n", "# Add variable for merit\n", - "studentsdata = studentsdata.gppd.add_vars(m, lb=0.0, ub=2.5, name='merit')\n", + "studentsdata = studentsdata.gppd.add_vars(m, lb=0.0, ub=2.5, name=\"merit\")\n", "\n", "# Keep only features\n", "studentsdata = studentsdata.loc[:, features]\n", diff --git a/notebooks/Janos/XGBoost.ipynb b/notebooks/Janos/XGBoost.ipynb index 80dd9363..4294b4f7 100644 --- a/notebooks/Janos/XGBoost.ipynb +++ b/notebooks/Janos/XGBoost.ipynb @@ -23,12 +23,10 @@ "source": [ "import gurobipy as gp\n", "import numpy as np\n", - "import math\n", "import pandas as pd\n", "import gurobipy_pandas as gppd\n", "from matplotlib import pyplot as plt\n", "import xgboost as xgb\n", - "from sklearn.metrics import r2_score\n", "\n", "from gurobi_ml import add_predictor_constr" ] @@ -84,7 +82,9 @@ "source": [ "# Run our regression\n", "n_estimators = 20\n", - "regression = xgb.XGBRegressor(n_estimators=n_estimators, max_depth=5, random_state=1, booster=\"gbtree\")\n", + "regression = xgb.XGBRegressor(\n", + " n_estimators=n_estimators, max_depth=5, random_state=1, booster=\"gbtree\"\n", + ")\n", "\n", "regression.fit(X=historical_data.loc[:, features], y=historical_data.loc[:, target])" ] @@ -135,10 +135,10 @@ "source": [ "m = gp.Model()\n", "\n", - "y = gppd.add_vars(m, studentsdata, name='enroll_probability')\n", + "y = gppd.add_vars(m, studentsdata, name=\"enroll_probability\")\n", "\n", "# Add variable for merit\n", - "studentsdata = studentsdata.gppd.add_vars(m, lb=0.0, ub=2.5, name='merit')\n", + "studentsdata = studentsdata.gppd.add_vars(m, lb=0.0, ub=2.5, name=\"merit\")\n", "\n", "# Keep only features\n", "studentsdata = studentsdata.loc[:, features]\n", diff --git a/notebooks/adversarial/adversarial_pytorch.ipynb b/notebooks/adversarial/adversarial_pytorch.ipynb index abef74fd..e2efe4b9 100644 --- a/notebooks/adversarial/adversarial_pytorch.ipynb +++ b/notebooks/adversarial/adversarial_pytorch.ipynb @@ -35,7 +35,6 @@ "metadata": {}, "outputs": [], "source": [ - "import numpy as np\n", "from matplotlib import pyplot as plt\n", "\n", "import torch\n", diff --git a/notebooks/price-optimization/Compare Models.ipynb b/notebooks/price-optimization/Compare Models.ipynb index 821fb31d..d458de23 100644 --- a/notebooks/price-optimization/Compare Models.ipynb +++ b/notebooks/price-optimization/Compare Models.ipynb @@ -27,7 +27,6 @@ "outputs": [], "source": [ "import pandas as pd\n", - "import numpy as np\n", "\n", "import gurobipy as gp\n", "from gurobipy import GRB\n", @@ -125,7 +124,7 @@ " (StandardScaler(), [\"price\"]),\n", " (\"passthrough\", [\"peak\"]),\n", " verbose_feature_names_out=False,\n", - " remainder='drop'\n", + " remainder=\"drop\",\n", ")\n", "\n", "\n", @@ -194,19 +193,27 @@ "from sklearn.base import clone\n", "from xgboost import XGBRegressor\n", "from time import time\n", - "args={\"random_state\":1}\n", - "regressions = {\"Linear Regression\": {\"regressor\":LinearRegression() },\n", - " \"MLP Regression\": {\"regressor\": MLPRegressor([8]*2, max_iter=1000, **args)},\n", - " \"Decision Tree\": {\"regressor\": DecisionTreeRegressor(max_leaf_nodes=50, **args)},\n", - " \"Random Forest\": {\"regressor\": RandomForestRegressor(n_estimators=10, max_leaf_nodes=100, **args)},\n", - " \"Gradient Boosting\":\n", - " {\"regressor\" : GradientBoostingRegressor(n_estimators=20, **args)},\n", - " \"XGB Regressor\": {\"regressor\": XGBRegressor(n_estimators=20, **args)}}\n", + "\n", + "args = {\"random_state\": 1}\n", + "regressions = {\n", + " \"Linear Regression\": {\"regressor\": LinearRegression()},\n", + " \"MLP Regression\": {\"regressor\": MLPRegressor([8] * 2, max_iter=1000, **args)},\n", + " \"Decision Tree\": {\"regressor\": DecisionTreeRegressor(max_leaf_nodes=50, **args)},\n", + " \"Random Forest\": {\n", + " \"regressor\": RandomForestRegressor(n_estimators=10, max_leaf_nodes=100, **args)\n", + " },\n", + " \"Gradient Boosting\": {\n", + " \"regressor\": GradientBoostingRegressor(n_estimators=20, **args)\n", + " },\n", + " \"XGB Regressor\": {\"regressor\": XGBRegressor(n_estimators=20, **args)},\n", + "}\n", "\n", "# Add polynomial features for linear regression and MLP\n", "regressions_poly = {}\n", "for regression in [\"Linear Regression\", \"MLP Regression\"]:\n", - " data = {\"regressor\": (PolynomialFeatures(),clone(regressions[regression][\"regressor\"]))}\n", + " data = {\n", + " \"regressor\": (PolynomialFeatures(), clone(regressions[regression][\"regressor\"]))\n", + " }\n", " regressions_poly[f\"{regression} polynomial feats\"] = data\n", "# Merge dictionary of polynomial features\n", "regressions |= regressions_poly" @@ -230,14 +237,12 @@ "for regression, data in regressions.items():\n", " regressor = data[\"regressor\"]\n", " if isinstance(regressor, tuple):\n", - " lin_reg = make_pipeline(feat_transform,\n", - " *regressor)\n", + " lin_reg = make_pipeline(feat_transform, *regressor)\n", " else:\n", - " lin_reg = make_pipeline(feat_transform,\n", - " regressor)\n", + " lin_reg = make_pipeline(feat_transform, regressor)\n", " train_start = time()\n", " lin_reg.fit(X_train, y_train)\n", - " data[(\"Learning\",\"time\")] = time() - train_start\n", + " data[(\"Learning\", \"time\")] = time() - train_start\n", " data[\"pipeline\"] = lin_reg\n", "\n", " # Get R^2 from test data\n", @@ -247,7 +252,9 @@ " r2_train = r2_score(y_train, y_pred)\n", " data[(\"Learning\", \"R2 test\")] = r2_test\n", " data[(\"Learning\", \"R2 train\")] = r2_train\n", - " print(f\"{regression:<18} R^2 value in the test set is {r2_test:.3f} training {r2_train:.3f}\")" + " print(\n", + " f\"{regression:<18} R^2 value in the test set is {r2_test:.3f} training {r2_train:.3f}\"\n", + " )" ] }, { @@ -282,7 +289,8 @@ " \"Southeast\": 0.2,\n", " \"West\": 0.2,\n", " \"Plains\": 0.2,\n", - " }, name='transport_cost'\n", + " },\n", + " name=\"transport_cost\",\n", ")\n", "\n", "c_transport = c_transport.loc[regions]\n", @@ -292,9 +300,14 @@ "a_min = 0 # minimum avocado price in each region\n", "a_max = 2 # maximum avocado price in each region\n", "\n", - "data = pd.concat([c_transport,\n", - " df.groupby(\"region\")[\"units_sold\"].min().rename('min_delivery'),\n", - " df.groupby(\"region\")[\"units_sold\"].max().rename('max_delivery')], axis=1)" + "data = pd.concat(\n", + " [\n", + " c_transport,\n", + " df.groupby(\"region\")[\"units_sold\"].min().rename(\"min_delivery\"),\n", + " df.groupby(\"region\")[\"units_sold\"].max().rename(\"max_delivery\"),\n", + " ],\n", + " axis=1,\n", + ")" ] }, { @@ -317,8 +330,8 @@ "m = gp.Model(\"Avocado_Price_Allocation\")\n", "\n", "p = gppd.add_vars(m, data, name=\"price\", lb=a_min, ub=a_max)\n", - "d = gppd.add_vars(m, data, name=\"demand\") # Add variables for the regression\n", - "w = m.addVar(name=\"w\") # excess wasteage\n", + "d = gppd.add_vars(m, data, name=\"demand\") # Add variables for the regression\n", + "w = m.addVar(name=\"w\") # excess wasteage\n", "m.update()\n", "\n", "m.setObjective((p * d).sum() - c_waste * w - (c_transport * d).sum())\n", @@ -336,12 +349,7 @@ "outputs": [], "source": [ "feats = pd.DataFrame(\n", - " data={\n", - " \"peak\": peak_or_not,\n", - " \"region\": regions,\n", - " \"price\": p\n", - " },\n", - " index=regions\n", + " data={\"peak\": peak_or_not, \"region\": regions, \"price\": p}, index=regions\n", ")\n", "feats = feats[[\"region\", \"price\", \"peak\"]]" ] @@ -369,10 +377,10 @@ " data[(\"Optimization\", \"value\")] = m.ObjVal\n", " data[(\"Optimization\", \"viol\")] = m.MaxVio\n", " data[(\"Optimization\", \"error\")] = pred_constr.get_error().max()\n", - " except:\n", - " data[(\"Optimization\", \"value\")] = float('nan')\n", - " data[(\"Optimization\", \"viol\")] = float('nan')\n", - " data[(\"Optimization\", \"error\")] = float('nan')\n", + " except gp.GurobiError:\n", + " data[(\"Optimization\", \"value\")] = float(\"nan\")\n", + " data[(\"Optimization\", \"viol\")] = float(\"nan\")\n", + " data[(\"Optimization\", \"error\")] = float(\"nan\")\n", " break\n", " pass\n", " pred_constr.remove()" @@ -385,7 +393,9 @@ "metadata": {}, "outputs": [], "source": [ - "res = pd.DataFrame.from_dict(regressions, orient='index').drop([\"regressor\", \"pipeline\"], axis=1)" + "res = pd.DataFrame.from_dict(regressions, orient=\"index\").drop(\n", + " [\"regressor\", \"pipeline\"], axis=1\n", + ")" ] }, { @@ -395,7 +405,7 @@ "metadata": {}, "outputs": [], "source": [ - "res.columns = pd.MultiIndex.from_tuples(res.columns)\n" + "res.columns = pd.MultiIndex.from_tuples(res.columns)" ] }, { diff --git a/src/gurobi_ml/__init__.py b/src/gurobi_ml/__init__.py index deada134..08c3ac2a 100644 --- a/src/gurobi_ml/__init__.py +++ b/src/gurobi_ml/__init__.py @@ -30,9 +30,11 @@ from gurobipy import gurobi -from ._version import __version__ -from .add_predictor import add_predictor_constr -from .register_user_predictor import register_predictor_constr +from ._version import __version__ as __version__ +from .add_predictor import add_predictor_constr as add_predictor_constr +from .register_user_predictor import ( + register_predictor_constr as register_predictor_constr, +) MIN_GRB_VERSION = 10 if gurobi.version()[0] < MIN_GRB_VERSION: diff --git a/src/gurobi_ml/_version.py b/src/gurobi_ml/_version.py index 596d4b7b..974d6bdd 100644 --- a/src/gurobi_ml/_version.py +++ b/src/gurobi_ml/_version.py @@ -14,6 +14,7 @@ # ============================================================================== """To get version and git hash of built package.""" + from importlib import metadata try: diff --git a/src/gurobi_ml/keras/__init__.py b/src/gurobi_ml/keras/__init__.py index 13dd2f06..046acf9e 100644 --- a/src/gurobi_ml/keras/__init__.py +++ b/src/gurobi_ml/keras/__init__.py @@ -13,4 +13,5 @@ # limitations under the License. # ============================================================================== -from .keras import KerasNetworkConstr, add_keras_constr +from .keras import KerasNetworkConstr as KerasNetworkConstr +from .keras import add_keras_constr as add_keras_constr diff --git a/src/gurobi_ml/lightgbm/__init__.py b/src/gurobi_ml/lightgbm/__init__.py index 3d56a89f..b46f3487 100644 --- a/src/gurobi_ml/lightgbm/__init__.py +++ b/src/gurobi_ml/lightgbm/__init__.py @@ -13,4 +13,5 @@ # limitations under the License. # ============================================================================== -from .lgbm_regressor import add_lgbm_booster_constr, add_lgbmregressor_constr +from .lgbm_regressor import add_lgbm_booster_constr as add_lgbm_booster_constr +from .lgbm_regressor import add_lgbmregressor_constr as add_lgbmregressor_constr diff --git a/src/gurobi_ml/lightgbm/lgbm_regressor.py b/src/gurobi_ml/lightgbm/lgbm_regressor.py index a06e64a1..26a321a7 100644 --- a/src/gurobi_ml/lightgbm/lgbm_regressor.py +++ b/src/gurobi_ml/lightgbm/lgbm_regressor.py @@ -18,7 +18,6 @@ into a :external+gurobi:py:class:`Model`. """ - import numpy as np from gurobipy import GRB diff --git a/src/gurobi_ml/lightgbm_sklearn_api.py b/src/gurobi_ml/lightgbm_sklearn_api.py index 56958738..aed3a317 100644 --- a/src/gurobi_ml/lightgbm_sklearn_api.py +++ b/src/gurobi_ml/lightgbm_sklearn_api.py @@ -13,7 +13,7 @@ # limitations under the License. # ============================================================================== -""" Convertor for LigthGBM's Scikit Learn compatible object +"""Convertor for LigthGBM's Scikit Learn compatible object This is to be able to use it in pipelines. """ diff --git a/src/gurobi_ml/modeling/__init__.py b/src/gurobi_ml/modeling/__init__.py index c0d66fc1..eaeda8d1 100644 --- a/src/gurobi_ml/modeling/__init__.py +++ b/src/gurobi_ml/modeling/__init__.py @@ -13,4 +13,4 @@ # limitations under the License. # ============================================================================== -from .base_predictor_constr import AbstractPredictorConstr +from .base_predictor_constr import AbstractPredictorConstr as AbstractPredictorConstr diff --git a/src/gurobi_ml/modeling/decision_tree/__init__.py b/src/gurobi_ml/modeling/decision_tree/__init__.py index 5f01f37a..f552f8e4 100644 --- a/src/gurobi_ml/modeling/decision_tree/__init__.py +++ b/src/gurobi_ml/modeling/decision_tree/__init__.py @@ -13,4 +13,4 @@ # limitations under the License. # ============================================================================== -from .decision_tree_model import AbstractTreeEstimator +from .decision_tree_model import AbstractTreeEstimator as AbstractTreeEstimator diff --git a/src/gurobi_ml/modeling/decision_tree/decision_tree_model.py b/src/gurobi_ml/modeling/decision_tree/decision_tree_model.py index c8f1e7cb..b0421583 100644 --- a/src/gurobi_ml/modeling/decision_tree/decision_tree_model.py +++ b/src/gurobi_ml/modeling/decision_tree/decision_tree_model.py @@ -13,7 +13,7 @@ # limitations under the License. # ============================================================================== -""" Utilities for modeling decision trees """ +"""Utilities for modeling decision trees""" from warnings import warn diff --git a/src/gurobi_ml/modeling/neuralnet/__init__.py b/src/gurobi_ml/modeling/neuralnet/__init__.py index d9054278..ef9e9611 100644 --- a/src/gurobi_ml/modeling/neuralnet/__init__.py +++ b/src/gurobi_ml/modeling/neuralnet/__init__.py @@ -13,4 +13,4 @@ # limitations under the License. # ============================================================================== -from .neural_net import BaseNNConstr +from .neural_net import BaseNNConstr as BaseNNConstr diff --git a/src/gurobi_ml/modeling/neuralnet/neural_net.py b/src/gurobi_ml/modeling/neuralnet/neural_net.py index 8869b497..dc70e39c 100644 --- a/src/gurobi_ml/modeling/neuralnet/neural_net.py +++ b/src/gurobi_ml/modeling/neuralnet/neural_net.py @@ -15,7 +15,6 @@ """Bases classes for modeling neural network layers.""" - from .._var_utils import _default_name from ..base_predictor_constr import AbstractPredictorConstr from .activations import Identity, ReLU diff --git a/src/gurobi_ml/register_user_predictor.py b/src/gurobi_ml/register_user_predictor.py index 77129a0c..7d81b903 100644 --- a/src/gurobi_ml/register_user_predictor.py +++ b/src/gurobi_ml/register_user_predictor.py @@ -15,6 +15,7 @@ """Module for user to register a predictor for the function add_predictor_constr.""" + USER_PREDICTORS = {} diff --git a/src/gurobi_ml/registered_predictors.py b/src/gurobi_ml/registered_predictors.py index 51adbb58..30d9f2cd 100644 --- a/src/gurobi_ml/registered_predictors.py +++ b/src/gurobi_ml/registered_predictors.py @@ -14,6 +14,7 @@ # ============================================================================== """Define generic function that can add any known trained predictor.""" + import sys from .register_user_predictor import user_predictors @@ -78,7 +79,6 @@ def lightgbm_convertors(): import lightgbm as lgb # pylint: disable=import-outside-toplevel from .lightgbm import ( # pylint: disable=import-outside-toplevel - add_lgbm_booster_constr, add_lgbmregressor_constr, ) diff --git a/src/gurobi_ml/sklearn/__init__.py b/src/gurobi_ml/sklearn/__init__.py index e873fce0..1c7bc20a 100644 --- a/src/gurobi_ml/sklearn/__init__.py +++ b/src/gurobi_ml/sklearn/__init__.py @@ -13,18 +13,30 @@ # limitations under the License. # ============================================================================== -from .column_transformer import add_column_transformer_constr -from .decision_tree_regressor import add_decision_tree_regressor_constr -from .gradient_boosting_regressor import add_gradient_boosting_regressor_constr -from .linear_regression import add_linear_regression_constr -from .logistic_regression import add_logistic_regression_constr -from .mlpregressor import add_mlp_regressor_constr -from .pipeline import add_pipeline_constr -from .pls_regression import add_pls_regression_constr -from .predictors_list import sklearn_predictors +from .column_transformer import ( + add_column_transformer_constr as add_column_transformer_constr, +) +from .decision_tree_regressor import ( + add_decision_tree_regressor_constr as add_decision_tree_regressor_constr, +) +from .gradient_boosting_regressor import ( + add_gradient_boosting_regressor_constr as add_gradient_boosting_regressor_constr, +) +from .linear_regression import ( + add_linear_regression_constr as add_linear_regression_constr, +) +from .logistic_regression import ( + add_logistic_regression_constr as add_logistic_regression_constr, +) +from .mlpregressor import add_mlp_regressor_constr as add_mlp_regressor_constr +from .pipeline import add_pipeline_constr as add_pipeline_constr +from .pls_regression import add_pls_regression_constr as add_pls_regression_constr +from .predictors_list import sklearn_predictors as sklearn_predictors from .preprocessing import ( - add_polynomial_features_constr, - add_standard_scaler_constr, - sklearn_transformers, + add_polynomial_features_constr as add_polynomial_features_constr, +) +from .preprocessing import add_standard_scaler_constr as add_standard_scaler_constr +from .preprocessing import sklearn_transformers as sklearn_transformers +from .random_forest_regressor import ( + add_random_forest_regressor_constr as add_random_forest_regressor_constr, ) -from .random_forest_regressor import add_random_forest_regressor_constr diff --git a/src/gurobi_ml/sklearn/base_regressions.py b/src/gurobi_ml/sklearn/base_regressions.py index bad7cf81..7fbec281 100644 --- a/src/gurobi_ml/sklearn/base_regressions.py +++ b/src/gurobi_ml/sklearn/base_regressions.py @@ -21,7 +21,6 @@ - :external+sklearn:py:class:`sklearn.linear_model.Lasso` """ - from ..modeling import AbstractPredictorConstr from .skgetter import SKgetter diff --git a/src/gurobi_ml/sklearn/column_transformer.py b/src/gurobi_ml/sklearn/column_transformer.py index 69f6267e..d24503d3 100644 --- a/src/gurobi_ml/sklearn/column_transformer.py +++ b/src/gurobi_ml/sklearn/column_transformer.py @@ -78,7 +78,7 @@ def _mip_model(self, **kwargs): """Do the transformation on x.""" column_transform = self.transformer _input = self._input - transformers = {k.lower(): v for k, v in sklearn_transformers().items()} + {k.lower(): v for k, v in sklearn_transformers().items()} transformed = [] for name, trans, cols in column_transform.transformers_: if len(cols) == 0: diff --git a/src/gurobi_ml/sklearn/decision_tree_regressor.py b/src/gurobi_ml/sklearn/decision_tree_regressor.py index db3dbdc9..cdcffa61 100644 --- a/src/gurobi_ml/sklearn/decision_tree_regressor.py +++ b/src/gurobi_ml/sklearn/decision_tree_regressor.py @@ -18,7 +18,6 @@ in a :external+gurobi:py:class:`Model`. """ - from ..modeling.decision_tree import AbstractTreeEstimator from .skgetter import SKgetter diff --git a/src/gurobi_ml/sklearn/mlpregressor.py b/src/gurobi_ml/sklearn/mlpregressor.py index 745a31e2..bfaf863d 100644 --- a/src/gurobi_ml/sklearn/mlpregressor.py +++ b/src/gurobi_ml/sklearn/mlpregressor.py @@ -16,6 +16,7 @@ """Module for formulating a :external+sklearn:py:class:`sklearn.neural_network.MLPRegressor` in a :external+gurobi:py:class:`Model`. """ + from ..exceptions import NoModel from ..modeling.neuralnet import BaseNNConstr from .skgetter import SKgetter diff --git a/src/gurobi_ml/sklearn/pipeline.py b/src/gurobi_ml/sklearn/pipeline.py index 33a4a391..0830c518 100644 --- a/src/gurobi_ml/sklearn/pipeline.py +++ b/src/gurobi_ml/sklearn/pipeline.py @@ -17,7 +17,6 @@ in a :external+gurobi:py:class:`Model`. """ - from ..lightgbm_sklearn_api import lightgbm_sklearn_convertors from ..modeling.base_predictor_constr import AbstractPredictorConstr from ..modeling.get_convertor import get_convertor diff --git a/src/gurobi_ml/sklearn/pls_regression.py b/src/gurobi_ml/sklearn/pls_regression.py index 6c9af64f..a7b67cd0 100644 --- a/src/gurobi_ml/sklearn/pls_regression.py +++ b/src/gurobi_ml/sklearn/pls_regression.py @@ -15,7 +15,6 @@ """Module for formulating :external+sklearn:py:class:`sklearn.cross_decomposition.PLSRegression` in a gurobipy model.""" - from ..modeling import AbstractPredictorConstr from .skgetter import SKgetter diff --git a/src/gurobi_ml/torch/__init__.py b/src/gurobi_ml/torch/__init__.py index 8656280e..4d7fc1bc 100644 --- a/src/gurobi_ml/torch/__init__.py +++ b/src/gurobi_ml/torch/__init__.py @@ -13,4 +13,4 @@ # limitations under the License. # ============================================================================== -from .sequential import add_sequential_constr +from .sequential import add_sequential_constr as add_sequential_constr diff --git a/src/gurobi_ml/xgboost/__init__.py b/src/gurobi_ml/xgboost/__init__.py index 859c6d65..5a74ea31 100644 --- a/src/gurobi_ml/xgboost/__init__.py +++ b/src/gurobi_ml/xgboost/__init__.py @@ -13,4 +13,7 @@ # limitations under the License. # ============================================================================== -from .xgboost_regressor import add_xgboost_regressor_constr, add_xgbregressor_constr +from .xgboost_regressor import ( + add_xgboost_regressor_constr as add_xgboost_regressor_constr, +) +from .xgboost_regressor import add_xgbregressor_constr as add_xgbregressor_constr diff --git a/src/gurobi_ml/xgboost/xgboost_regressor.py b/src/gurobi_ml/xgboost/xgboost_regressor.py index 04b08df4..d286d214 100644 --- a/src/gurobi_ml/xgboost/xgboost_regressor.py +++ b/src/gurobi_ml/xgboost/xgboost_regressor.py @@ -18,7 +18,6 @@ into a :external+gurobi:py:class:`Model`. """ - import json import numpy as np diff --git a/src/gurobi_ml/xgboost_sklearn_api.py b/src/gurobi_ml/xgboost_sklearn_api.py index fc7e358b..2b285e42 100644 --- a/src/gurobi_ml/xgboost_sklearn_api.py +++ b/src/gurobi_ml/xgboost_sklearn_api.py @@ -13,7 +13,7 @@ # limitations under the License. # ============================================================================== -""" Convertor for XGBoost's Scikit Learn compatible object +"""Convertor for XGBoost's Scikit Learn compatible object This is to be able to use it in pipelines. """ diff --git a/tests/test_sklearn/test_register_constr.py b/tests/test_sklearn/test_register_constr.py index f0174e0c..99941cee 100644 --- a/tests/test_sklearn/test_register_constr.py +++ b/tests/test_sklearn/test_register_constr.py @@ -1,5 +1,5 @@ # Copyright © 2023 Gurobi Optimization, LLC -""" Test register_predictor_constr function""" +"""Test register_predictor_constr function""" import unittest diff --git a/tests/test_sklearn/test_remove.py b/tests/test_sklearn/test_remove.py index 579f3abd..085128c7 100644 --- a/tests/test_sklearn/test_remove.py +++ b/tests/test_sklearn/test_remove.py @@ -1,4 +1,5 @@ -""" Test for adding and removing predictor objects""" +"""Test for adding and removing predictor objects""" + import random import unittest