Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Price taker model for DISPATCHES, Rehashed #1358

Open
wants to merge 140 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
140 commits
Select commit Hold shift + click to select a range
a3d688c
Added basic price-taker framework
radhakrishnatg May 26, 2023
67ce6a2
run black
adam-a-a Jun 8, 2023
e716c36
add in get_optimal_n_clusters as separate method. hand off to Marcus
adam-a-a Jun 8, 2023
e3788fb
Add methods for computing the optimal # of clusters and making an elb…
MarcusHolly Jun 9, 2023
8ef54be
Merge branch 'main' into adam-a-a-price-taker-model
MarcusHolly Jun 9, 2023
f154700
Merge branch 'main' into price-taker-model
lbianchi-lbl Jun 10, 2023
422d0ba
add fom to typos.toml in github/workflows to pass spellcheck
adam-a-a Jun 12, 2023
2f36bbb
fix typo
adam-a-a Jun 12, 2023
0aa1034
Add tests for new functions (excel import failing)
MarcusHolly Jun 13, 2023
9042e5c
Update dependencies
MarcusHolly Jun 13, 2023
5549028
Merge branch 'price-taker-model' of https://github.com/adam-a-a/idaes…
MarcusHolly Jun 13, 2023
2fde47f
Add pytest marks
MarcusHolly Jun 13, 2023
d0a6c13
Fix typo where TimeStep data was being used instead of BaseCaseTax
MarcusHolly Jun 15, 2023
e5f6c07
Update test file
MarcusHolly Jun 15, 2023
56d9369
Add warning for when kmax is not set
MarcusHolly Jun 15, 2023
9b5edd4
Address Radha's comments and start adding testing (WIP)
MarcusHolly Jun 21, 2023
948f40c
Add more tests
MarcusHolly Jun 22, 2023
30fed63
Add cluster_lmp_data function
MarcusHolly Jun 22, 2023
fc43a3f
linearizing su_sd cosntraints and fixing the price traker model
Aug 3, 2023
4170501
Removing files that were mistakenly saved on this branch
Aug 3, 2023
1d87aea
modified startup and shutdown constraint function
Aug 11, 2023
4710a10
add set_period to startup and shutdown func
Aug 11, 2023
be68154
developed a function to add startup/shutdown constraints
Aug 18, 2023
66db0d8
Constructed a function that adds startup and shutdown constraints
Aug 22, 2023
b39f4d9
Added deepgetattr function and had the ramp-up/down and start-up/down…
Aug 30, 2023
799ed0b
linearized ramping constraints
Sep 14, 2023
7625d07
Added auxiliary variables
Sep 14, 2023
0c2c461
added a third mccor constraint for each aux var and created a capacit…
Sep 18, 2023
16710a6
changed startup_shutdown constraints to have the shutdown binary var
Sep 19, 2023
4518240
changed rule for min_start_up constraint
Sep 19, 2023
35ddead
fixed startup_shutdown function constraints, changed default values f…
Sep 20, 2023
fd15af9
added new method for adding aux variables
Sep 21, 2023
b84ea43
removed aux variable delcaration and added a new config option to opt…
Sep 21, 2023
15ea641
added comments
Sep 21, 2023
53e427e
small addition
Sep 21, 2023
14ee544
added design_blk
Sep 21, 2023
4e10801
added deepgetattr and constraint for the add capacity aux var func
Sep 21, 2023
d68d8fd
finished the new method and ramping function
Sep 22, 2023
6cd966e
Allowed _add_capacity_aux_vars to be cosntructed when the build func…
Oct 4, 2023
f7e3245
added a for loop that calls on the _add_capacity_aux_vars function t …
Oct 4, 2023
b223cf6
Pulling Tyler\'s brnach
Oct 31, 2023
56f8099
Updating PT model for SOFC case study
Nov 1, 2023
48d4d98
Updated price_taker_model.py doc
djlaky Feb 15, 2024
fde3f31
Updated init of PriceTakerModel
djlaky Feb 15, 2024
5bd0d5b
Added missing documentation
djlaky Feb 15, 2024
0df8b45
Corrected constraint expressions
djlaky Feb 15, 2024
fd595b4
Added tests for input checking
djlaky Feb 15, 2024
a54c3ac
Updated checks for get_optimal_clusters
djlaky Feb 15, 2024
70cbaba
Fixed typos in test_price_taker.py
djlaky Feb 15, 2024
85b7bd0
Added input checks on add_ramping_constraints
djlaky Feb 15, 2024
9851b88
Fixed broken test
djlaky Feb 15, 2024
6ede14e
Added automated LMP population
djlaky Feb 16, 2024
d31b272
Fixed getitem issues with Sets
djlaky Feb 16, 2024
769ba7b
Removed redundant set definition
djlaky Feb 16, 2024
0bba4d2
Added n_clusters check in append_lmp_data
djlaky Feb 16, 2024
b06d467
Reorganizing unit logging messages tests
djlaky Feb 20, 2024
0cf82bf
Moved deepgetattr to import from design_and_operation_models.py
djlaky Feb 21, 2024
6af8c9e
Added checks and tests
djlaky Feb 21, 2024
1fc5f53
Updated data processing workflow
djlaky Feb 22, 2024
e991392
Small update to append_lmp_data
djlaky Feb 22, 2024
f2725cc
Updated get_optimal_n_clusters
djlaky Feb 27, 2024
522023b
Updated cash flow construction
djlaky Feb 27, 2024
22dbe12
Added tests for cashflows
djlaky Feb 27, 2024
6dbb183
Fixed typos and ran black
djlaky Feb 29, 2024
7a86d03
Run black
djlaky Feb 29, 2024
7a24fba
Fixed some broken tests
djlaky Feb 29, 2024
b1629eb
Removed a test that is failing
djlaky Feb 29, 2024
d193e65
Reverted pytests.ini and corrected tests
djlaky Mar 4, 2024
fb543c7
Updated plotting test
djlaky Mar 4, 2024
460af99
Ran Black again
djlaky Mar 4, 2024
c90bbe1
Merge branch 'IDAES:main' into price-taker-model
djlaky Mar 4, 2024
643707f
Updating tests
djlaky Mar 5, 2024
8aa02c6
Add capacity limits function
djlaky Mar 25, 2024
323e4a9
Added final docstring
djlaky Mar 25, 2024
04d07ae
Ran black
djlaky Mar 25, 2024
4ae5779
Bugfix capacity constraints
djlaky Mar 25, 2024
893743d
Removed multiyear LMP support
djlaky Mar 27, 2024
82f8bdc
Merge branch 'IDAES:main' into price-taker-model
djlaky Mar 27, 2024
ebdc1b2
Delete idaes/apps/grid_integration/multiperiod/ERCOT_WEST_2022_shutdo…
djlaky Mar 28, 2024
aad41fb
Update docstring for n_clusters
djlaky Apr 30, 2024
e2dac86
Fixed typos.
djlaky Apr 30, 2024
5ad727e
Removed design_blk as an input for Operation_Model
djlaky Apr 30, 2024
2ae4635
Fixed typo in error message in tests
djlaky Apr 30, 2024
8762f7b
Replace deepgetattr with find_component()
djlaky Apr 30, 2024
7110dea
Changed dependence of tests on .xlsx to .csv
djlaky Apr 30, 2024
8550569
Merge branch 'IDAES:main' into price-taker-model
djlaky Apr 30, 2024
69c3c9b
Changed deepgetattr functionality to find_component
djlaky Apr 30, 2024
177618c
Merge branch 'price-taker-model' of https://github.com/dlakes94/idaes…
djlaky Apr 30, 2024
ce4b0fb
Updated test to remove .xlsx dependencies
djlaky Apr 30, 2024
343d191
Update on build_hourly_cashflows docstring
djlaky Apr 30, 2024
cec302e
Update for Sphinx again
djlaky Apr 30, 2024
652d1cc
Ran black
djlaky Apr 30, 2024
d8ade5d
Updated SkeletonUnitModelData to ProcessBlockData
djlaky May 8, 2024
cd3f3d3
Made sklearn and kneed optional, added log msgs
djlaky May 8, 2024
ce6b3db
Updated tests for price taker class
djlaky May 8, 2024
f4cfbdb
Fixed optional import tests
djlaky May 8, 2024
cbd7aaa
Ran black
djlaky May 8, 2024
f10ea59
Bugfix kmeans for LMP
djlaky May 16, 2024
46a3331
merged idaes main
May 29, 2024
7bdd94d
Revert "merged idaes main"
djlaky Jun 10, 2024
1c85981
Add initial documentation for pricetaker
MarcusHolly Jul 12, 2024
6956d73
Add autoclass to documentation
MarcusHolly Jul 12, 2024
8b4b479
Address merge conflict
MarcusHolly Jul 12, 2024
646b88b
Fix typos in documentation
MarcusHolly Jul 12, 2024
a1f1eb2
Reformat how math equations are handled
MarcusHolly Jul 12, 2024
8101448
add subtle additions to price-taker model used in workhop
adam-a-a Jul 15, 2024
d8de0dd
Merge branch 'main' into price-taker-model
adam-a-a Jul 23, 2024
fc7369e
Test for seed instance and seed ValueError
MarcusHolly Sep 5, 2024
75a56f4
Check for expected string outputs rather than using f-strings
MarcusHolly Sep 5, 2024
df687af
Separate tests that check for multiple error messages
MarcusHolly Sep 5, 2024
47b66c5
Separate a majority of the code outside of the pytest.raises
MarcusHolly Sep 6, 2024
8ac5987
Update imports
MarcusHolly Sep 9, 2024
d10b9a7
Merge branch 'main' into price-taker-model
MarcusHolly Sep 9, 2024
1e7842a
Add version check for sklearn
MarcusHolly Sep 9, 2024
8b1393a
Add separate function & test for generating elbow plots
MarcusHolly Sep 9, 2024
6481545
Refines version testing and # of optimal clusters testing
MarcusHolly Sep 11, 2024
b9f3ef4
Remove unused imports
MarcusHolly Sep 11, 2024
bd2db6f
Merge branch 'price-taker-model' of https://github.com/djlaky/idaes-p…
MarcusHolly Sep 11, 2024
9cf4a3a
Merge branch 'main' into djlaky-price-taker-model
MarcusHolly Oct 15, 2024
112761f
Correct acronym in pricetaker documentation
MarcusHolly Oct 15, 2024
fb0a05b
Remove commented code in design_and_operation_models
MarcusHolly Oct 15, 2024
5d960a4
Add dependencies for scikit-learn and kneed
MarcusHolly Oct 15, 2024
d7a0002
Update imports and seed.setter method
MarcusHolly Oct 15, 2024
727be78
Resolve test failures
MarcusHolly Oct 16, 2024
aebe5b8
Update pricetaker to not create new dependencies
MarcusHolly Oct 17, 2024
411bb60
Update pricetaker testing based on previous commit
MarcusHolly Oct 17, 2024
bd3244c
Refine docstring for compute_sse method
MarcusHolly Oct 17, 2024
b8149b5
Make compute_sse a prviate method & move outside of class
MarcusHolly Oct 17, 2024
043ac34
Update compute_sse docstring
MarcusHolly Oct 17, 2024
2cd22e4
Added tests for design and operation model classes
radhakrishnatg Oct 23, 2024
e9ff144
repair failing check by updating config option name; also update exce…
adam-a-a Oct 30, 2024
422ec6e
black
adam-a-a Oct 30, 2024
042a1d9
add more exception handling
adam-a-a Oct 30, 2024
0fd8edb
Update docs/reference_guides/apps/grid_integration/multiperiod/Price_…
MarcusHolly Oct 30, 2024
892e555
Merge branch 'main' into price-taker-model
adam-a-a Oct 30, 2024
a2c97c4
blk
adam-a-a Oct 30, 2024
20db58f
try to fix docstrings to mitigate sphinx error
adam-a-a Oct 30, 2024
a4620de
Remove unnecessary f-strings
MarcusHolly Nov 5, 2024
a1ae6b7
Remove/re-add commented code in price taker testing
MarcusHolly Nov 5, 2024
bef17fb
Add logger messages for when model_func is not defined
MarcusHolly Nov 8, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 40 additions & 34 deletions idaes/apps/grid_integration/multiperiod/price_taker_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,7 @@
import pandas as pd
import numpy as np

have_skl = True
have_kn = True
try:
from sklearn.cluster import KMeans
except ImportError:
have_skl = False
try:
from kneed import KneeLocator
except ImportError:
have_kn = False
from scipy.cluster.vq import kmeans, kmeans2, vq, whiten

import matplotlib.pyplot as plt

Expand All @@ -50,7 +41,6 @@
NonNegativeReals,
Expression,
maximize,
Param,
)

from idaes.apps.grid_integration import MultiPeriodModel
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not something for this PR, but one thing I have wanted to comment on for a while is to make sure that the DISPATCHES team is aware the IDAES steady-state flowsheets support time indexing.

m.fs = FlowsheetBlock(dynamic=False, time_set=[0, 1, 2, ...])

I do not think this tool has been using this capability, and it might help simplify things (or conversely make things more complicated). However, this would allow you to e.g. initialize all states (StateBlocks) in the multi-period model in one go using the existing initialization frameworks.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will note this for our continued development, thank you.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@andrewlee94 Thank you for the note! I was not aware of time indexing. In DISPATCHES, we create one instance of the flowsheet, initialize it and clone it. Also, in most cases, models tend be linear/quadratic, so initialization is not needed. If we want to use the time index, then I believe we have to make a lot of changes to the MultiPeriodModel class. Maybe for another PR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitely another PR.

For reference, state block initialization will handle the indexing just fine and will initialize all time points in one go for you. @Robbybp also has some dynamic initialization tools that copy results from one state to another that might work here as well.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I have some tools in pyomo-mpc for working with dynamic models. These should be useful for working with time-indexed steady state flowsheets, as this is very close to the use case they were designed for. To my basic understanding, MultiPeriodModel and the related tooling in Dispatches seems like they are solving a similar problem from a different angle.

Expand All @@ -77,10 +67,9 @@ def seed(self):

@seed.setter
def seed(self, value):
try:
self._seed = value
except TypeError:
if not isinstance(value, int):
MarcusHolly marked this conversation as resolved.
Show resolved Hide resolved
raise TypeError(f"seed must be an integer, but {value} is not an integer")
self._seed = value

@property
def horizon_length(self):
Expand All @@ -91,11 +80,30 @@ def horizon_length(self, value):
if value <= 0:
raise ValueError(f"horizon_length must be > 0, but {value} is provided.")
if not isinstance(value, int):
raise ValueError(
raise TypeError(
f"horizon_length must be an integer, but {value} is not an integer"
)
self._horizon_length = value

@staticmethod
MarcusHolly marked this conversation as resolved.
Show resolved Hide resolved
def compute_sse(data, centroids, idx):
"""
Function used to compute the inertia (sum of square errors) for k clusters.

Args:
data: Columnar data for a given LMP signal
centroids: Array of k centroids
idx: Index for data

Returns:
inertia: Sum of square errors for k clusters
"""
inertia = 0
for i, centroid in enumerate(centroids):
cluster_points = data[idx == i]
inertia += np.sum((cluster_points - centroid) ** 2)
return inertia

def generate_daily_data(self, raw_data):
"""
Function used to generate the daily data in a usable format
Expand Down Expand Up @@ -171,20 +179,23 @@ def get_optimal_n_clusters(

np.random.seed(self._seed)

if not (have_skl and have_kn):
raise ImportError(
f"Optimal cluster feature requires optional imports 'scikit-learn' and 'kneed'."
)
# Compute the inertia (SSE) for k clusters
whitened_daily_data = whiten(daily_data.transpose())

for k in k_values:
kmeans = KMeans(n_clusters=k).fit(daily_data.transpose())
inertia_values.append(kmeans.inertia_)
centroids, _ = kmeans(whitened_daily_data, k)
idx, _ = vq(whitened_daily_data, centroids)

# Identify the "elbow point"
elbow_point = KneeLocator(
k_values, inertia_values, curve="convex", direction="decreasing"
)
n_clusters = elbow_point.knee
# Compute the inertia (SSE) for k clusters
inertia = self.compute_sse(whitened_daily_data, centroids, idx)
inertia_values.append(inertia)

# Calculate the second derivative
first_deriv = np.diff(inertia_values)
second_deriv = np.diff(first_deriv)

# Determine the optimal number of clusters
# The +2 accounts for the dimension being reduced twice by derivatives
n_clusters = np.argmin(second_deriv) + 2

if n_clusters is None:
raise ValueError(
Expand Down Expand Up @@ -272,15 +283,10 @@ def cluster_lmp_data(self, raw_data, n_clusters):

# reconfiguring raw data
daily_data = self.generate_daily_data(raw_data)
whitened_daily_data = whiten(daily_data.transpose())

# KMeans clustering with the optimal number of clusters
if not have_skl:
raise ImportError(
f"Clustering feature requires optional import 'scikit-learn'."
)
kmeans = KMeans(n_clusters=n_clusters).fit(daily_data.transpose())
centroids = kmeans.cluster_centers_
labels = kmeans.labels_
centroids, labels = kmeans2(whitened_daily_data, n_clusters)

# Set any centroid values that are < 1e-4 to 0 to avoid noise
centroids = centroids * (abs(centroids) >= 1e-4)
Expand Down
106 changes: 23 additions & 83 deletions idaes/apps/grid_integration/multiperiod/tests/test_price_taker.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,6 @@

from idaes.apps.grid_integration.multiperiod.price_taker_model import PriceTakerModel

have_skl = True
have_kn = True
try:
import sklearn as skl
from sklearn.cluster import KMeans
except:
have_skl = False
try:
from kneed import KneeLocator
except:
have_kn = False


@pytest.fixture
def excel_data():
Expand All @@ -57,14 +45,6 @@ def excel_data():
return data


@pytest.fixture
def sample_data():
DATA_DIR = Path(__file__).parent
file_path = DATA_DIR / "sample_data.csv"
data = pd.read_csv(file_path)
return data


@pytest.mark.unit
def test_seed():
m = PriceTakerModel()
MarcusHolly marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -75,7 +55,7 @@ def test_seed():
def test_seed_value():
value = "fifty"
with pytest.raises(
ValueError,
TypeError,
match=("seed must be an integer, but fifty is not an integer"),
):

Expand All @@ -94,40 +74,16 @@ def test_daily_data_size(excel_data):
assert len(daily_data) == m.horizon_length


@pytest.mark.skipif(
have_skl * have_kn < 1,
reason="optional packages 'scikit-learn' and 'kneed' not installed",
)
@pytest.mark.unit
def test_skl_version(excel_data):
skl_version = skl.__version__
major, minor, *_ = map(int, skl_version.split("."))

# Checks that the version is 2.0+ or greater than 1.1
# Only versions at or above 1.1 support python 3.12
assert major > 1 or (major == 1 and minor >= 1)


@pytest.mark.skipif(
have_skl * have_kn < 1,
reason="optional packages 'scikit-learn' and 'kneed' not installed",
)
@pytest.mark.unit
def test_determine_optimal_num_clusters(sample_data):
# Uses the smaller sample_data dataset so that the solution
# reliably converges to 9 clusters, instead of a range of clusters
def test_determine_optimal_num_clusters(excel_data):
m = PriceTakerModel()

daily_data = m.generate_daily_data(sample_data["BaseCaseTax"])
n_clusters, inertia_values = m.get_optimal_n_clusters(daily_data, kmax=15)
daily_data = m.generate_daily_data(excel_data["BaseCaseTax"])
n_clusters, inertia_values = m.get_optimal_n_clusters(daily_data, kmax=30)

assert n_clusters == 9
assert n_clusters == 11


@pytest.mark.skipif(
have_skl * have_kn < 1,
reason="optional packages 'scikit-learn' and 'kneed' not installed",
)
@pytest.mark.unit
def test_generate_elbow_plot(excel_data):
m = PriceTakerModel()
Expand All @@ -145,10 +101,6 @@ def test_generate_elbow_plot(excel_data):
plt.close("all")


@pytest.mark.skipif(
not (have_skl and have_kn),
reason="optional packages 'scikit-learn' and 'kneed' not installed",
)
@pytest.mark.unit
def test_cluster_lmp_data(excel_data):
# This function gets within both if statement expression in the
Expand All @@ -169,10 +121,6 @@ def test_cluster_lmp_data(excel_data):
assert len(lmp_data) == n_clusters


@pytest.mark.skipif(
not (have_skl and have_kn),
reason="optional packages 'scikit-learn' and 'kneed' not installed",
)
@pytest.mark.unit
def test_init_logger_messages_clusters(excel_data, caplog):
with caplog.at_level(idaeslog.WARNING):
Expand Down Expand Up @@ -201,7 +149,7 @@ def test_init_logger_message2(excel_data, caplog):
value = 12.34
m = PriceTakerModel()
with pytest.raises(
ValueError,
TypeError,
match=("horizon_length must be an integer, but 12.34 is not an integer"),
):
m.horizon_length = value
Expand All @@ -213,7 +161,7 @@ def test_init_logger_message3(excel_data, caplog):
value = 12.34
m = PriceTakerModel()
with pytest.raises(
ValueError,
TypeError,
match=("seed must be an integer, but 12.34 is not an integer"),
):
m.seed = value
Expand Down Expand Up @@ -279,10 +227,6 @@ def test_min_down_time_logger_message2(excel_data):
m.add_startup_shutdown(des, oper, build_bin_var, up_time[0], down_time[1])


@pytest.mark.skipif(
not (have_skl and have_kn),
reason="optional package 'scikit-learn' not installed",
)
@pytest.mark.unit
MarcusHolly marked this conversation as resolved.
Show resolved Hide resolved
def test_init_logger_messages_clusters_min_up_down_time(excel_data, caplog):
# Test Not Implemented Error (Rep. Days used for su/sd code)
Expand All @@ -294,7 +238,7 @@ def test_init_logger_messages_clusters_min_up_down_time(excel_data, caplog):
m.append_lmp_data(
file_path=file_path,
column_name="BaseCaseTax",
n_clusters=5,
n_clusters=2,
)

m.sofc_design = DesignModel(
Expand Down Expand Up @@ -401,25 +345,21 @@ def test_optimal_clusters_kmax_logger_message2(excel_data):
m.cluster_lmp_data(excel_data, n_clusters)


@pytest.mark.skipif(
have_skl and have_kn,
reason="optional packages 'scikit-learn' and 'kneed' are installed",
)
@pytest.mark.unit
def test_failed_imports(excel_data):
m = PriceTakerModel()
kmin = 9
kmax = 10
daily_data = m.generate_daily_data(excel_data["BaseCaseTax"])
with pytest.raises(
ImportError,
match=(
"Optimal cluster feature requires optional imports 'scikit-learn' and 'kneed'."
),
):
n_clusters, inertia_values = m.get_optimal_n_clusters(
daily_data, kmin=kmin, kmax=kmax
)
# @pytest.mark.unit
MarcusHolly marked this conversation as resolved.
Show resolved Hide resolved
# def test_failed_imports(excel_data):
# m = PriceTakerModel()
# kmin = 9
# kmax = 10
# daily_data = m.generate_daily_data(excel_data["BaseCaseTax"])
# with pytest.raises(
# ImportError,
# match=(
# "Optimal cluster feature requires optional imports 'scikit-learn' and 'kneed'."
# ),
# ):
# n_clusters, inertia_values = m.get_optimal_n_clusters(
# daily_data, kmin=kmin, kmax=kmax
# )


# The following test doesn't pass on all systems, so the warning for n_clusters being
Expand Down
2 changes: 0 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,6 @@ class ExtraDependencies:
]
grid = [
"gridx-prescient>=2.2.1", # idaes.tests.prescient
"scikit-learn>=1.1",
"kneed",
]
coolprop = [
"coolprop", # idaes.generic_models.properties.general.coolprop
Expand Down
Loading