Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions .codespellrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[codespell]
skip = .git,*.svg,*.png,*.jpg,*.jpeg,*.gif,*.ico,*.pdf,*.zip,*.tar.gz,*.whl,.venv,.vs,__pycache__
ignore-words-list = Bu,gage,Gage,modpods,sindy,SINDy,pysindy,NSE,HFV,LFV,FDC,LTI,SWMM,pystorms,pyswmm,RAIM,PET,PRCP,CAMELS,USGS,configparser,argparse
5 changes: 4 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,11 @@ jobs:
- name: Lint with ruff
run: ruff check .

- name: Lint with codespell
run: codespell .

- name: Type-check with mypy
run: mypy . --ignore-missing-imports

- name: Run tests with pytest
run: pytest tests/ -v
run: pytest tests/ -v --junitxml=junit.xml --cov=modpods --cov-report=xml -n auto
10 changes: 5 additions & 5 deletions modpods/lti.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,8 @@ def lti_from_gamma(
# search across the C vector
for i in range(
C.shape[1] - 1, int(-1), int(-1)
): # accross the columns # start at the end and come back
# for i in range(int(0),C.shape[1],int(1)): # accross the columns, start at the beginning and go forward
): # across the columns # start at the end and come back
# for i in range(int(0),C.shape[1],int(1)): # across the columns, start at the beginning and go forward

og_approx = control.ss(A, B, C, 0)
og_y = np.ndarray.flatten(control.impulse_response(og_approx, t).y)
Expand Down Expand Up @@ -437,7 +437,7 @@ def lti_system_gen(
for row in original_A.index:
if delay_models[row] is None:
pass
else: # we want the model with the most transformations where the last trnasformation added at least 0.5% to the R2 score
else: # we want the model with the most transformations where the last transformation added at least 0.5% to the R2 score
for num_transforms in range(1, max_transforms + 1):
if num_transforms == 1:
optimal_number_transforms = num_transforms
Expand Down Expand Up @@ -654,15 +654,15 @@ def lti_system_gen(
C = C.apply(pd.to_numeric, errors="coerce").fillna(0.0)

# if bibo_stable is specified and A not hurwitz, make A hurwitz by defining A' = A - I*max(real(eig(A)))
# this will gaurantee stability (max eigenvalue will have real part < 0)
# this will guarantee stability (max eigenvalue will have real part < 0)
if bibo_stable:
orig_eigs, _ = np.linalg.eig(A)
if any(np.real(orig_eigs) > 0):
print("stabilizing unstable plant by subtracting I*max(real(eig)) from A")
epsilon = 10e-4
A_stab = A - np.eye(len(A)) * (1 + epsilon) * max(
np.real(orig_eigs)
) # add factor of (1+epsilon) for stability, not marginal stabilty
) # add factor of (1+epsilon) for stability, not marginal stability
stab_eigs, _ = np.linalg.eig(A_stab)
A = A_stab.copy(deep=True)

Expand Down
12 changes: 7 additions & 5 deletions modpods/train.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,10 +275,12 @@ def objective_function(params_vector):
return -1.0

# Bayesian optimization
# Use more iterations for Bayesian optimization to build a good surrogate model
# Cap at 200 to avoid memory issues with GP fitting
# Bayesian optimization: bias toward exploration (cheap random samples)
# rather than expensive GP refinement. The objective (SINDy fit) is the
# dominant cost, so spend the budget on broad initial sampling and only
# a few informed iterations.
bayesian_max_iter = min(max_iter * 4, 200)
n_initial = min(20, max(10, bayesian_max_iter // 4))
n_initial = min(30, max(20, int(bayesian_max_iter * 0.6)))
X_sample_list: list[Any] = []
Y_sample_list: list[Any] = []

Expand All @@ -299,10 +301,10 @@ def objective_function(params_vector):
best_params: np.ndarray = X_sample[np.argmax(Y_sample)]

# Gaussian Process setup
kernel = Matern(length_scale=1.0, nu=2.5)
kernel = Matern(length_scale=1.0, nu=1.5)
gpr = GaussianProcessRegressor(
kernel=kernel,
alpha=1e-6,
alpha=1e-3,
normalize_y=True,
n_restarts_optimizer=5,
random_state=42,
Expand Down
3 changes: 3 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@ networkx>=3.0

# Testing
pytest>=7.0
pytest-xdist>=3.0
pytest-cov>=4.0

# Linting
black>=23.0
ruff>=0.1
mypy>=1.0
codespell>=2.0
2 changes: 1 addition & 1 deletion test_fixed.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import modpods

# basic funcionality tests and a bit of a tutorial
# basic functionality tests and a bit of a tutorial

# some data from the CAMELS dataset
# change the filepath to wherever you have modpods at
Expand Down
Loading