Skip to content
Open
Changes from 6 commits
Commits
Show all changes
138 commits
Select commit Hold shift + click to select a range
10f6b37
First pass at code redesign, still need to figure out more
sscini Nov 18, 2025
b0b7e2c
Merge branch 'Pyomo:main' into Q_opt-redesign
sscini Nov 20, 2025
3e95e91
Added comments where I have question
sscini Nov 20, 2025
8d3a4d5
Merge branch 'Q_opt-redesign' of https://github.com/sscini/pyomo into…
sscini Nov 20, 2025
3982e1b
Got preliminary _Q_opt simple working with example!
sscini Nov 21, 2025
e829344
Ran black
sscini Nov 21, 2025
e464097
Changed name to _Q_opt_blocks
sscini Nov 21, 2025
dc5ee76
Update parmest.py
sscini Nov 21, 2025
6355818
Ran black
sscini Nov 21, 2025
099f541
Added in case for bootlist, works with example
sscini Nov 25, 2025
76ee05e
Ran black
sscini Nov 25, 2025
d91ce3f
Simplified structure, ran black
sscini Nov 29, 2025
1aea99f
Removed _Q_opt, and replicate functions, only using _Q_opt_blocks
sscini Dec 13, 2025
7d93cc0
Ran black on mac
sscini Dec 15, 2025
d7d2214
Revert "Removed _Q_opt, and replicate functions, only using _Q_opt_bl…
sscini Dec 15, 2025
7f21344
Added testing statement
sscini Dec 17, 2025
32d8d41
Ran black
sscini Dec 17, 2025
4e8c3ee
Merge branch 'Pyomo:main' into Q_opt-redesign
sscini Jan 6, 2026
1e802ba
Made small design changes, in progress, ran black.
sscini Jan 6, 2026
4b89bb3
Merge branch 'Q_opt-redesign' of https://github.com/sscini/pyomo into…
sscini Jan 6, 2026
4777253
Progress made on objective_at_theta_blocks, unfinished.
sscini Jan 8, 2026
c58d5f3
Merge branch 'Pyomo:main' into Q_opt-redesign
sscini Jan 11, 2026
ea734b7
Merge branch 'Q_opt-redesign' of https://github.com/sscini/pyomo into…
sscini Jan 11, 2026
490abea
Added notes for design meeting 01/12/26
sscini Jan 12, 2026
1074fb0
Merge branch 'Pyomo:main' into Q_opt-redesign
sscini Jan 14, 2026
9543456
Removed answered reviewer question, attempted adding covariance
sscini Jan 14, 2026
af4df1a
Added assertions for cov_n
sscini Jan 14, 2026
d4c4125
Finished implementing covariance
sscini Jan 14, 2026
9d396fa
Added functional return values argument
sscini Jan 14, 2026
a97b21e
Ran black
sscini Jan 14, 2026
0afb5ba
Corrected extraction for unknown parameters
sscini Jan 14, 2026
191b131
Initial attempt at objective_at_theta_blocks
sscini Jan 14, 2026
2c0760e
Working out bugs in _Q_at_theta implement. In progress.
sscini Jan 14, 2026
bbe994b
Corrected obj_at_theta_blocks
sscini Jan 15, 2026
2c2e024
Removed _Q_opt, commented out _Q_at_theta, ran black
sscini Jan 15, 2026
2333a4b
Fixed for loop issue
sscini Jan 15, 2026
b9af9f1
Removed fix_theta from create_parm_model
sscini Jan 15, 2026
6cd3b4b
Renamed objective_at_theta_blocks, ran black.
sscini Jan 15, 2026
b46e1a7
Removed mentions of _Q_opt_blocks
sscini Jan 15, 2026
3261798
Changed back to get_labeled_model in _cov_at_theta()
sscini Jan 15, 2026
fc478be
Added notes in unused files.
sscini Jan 15, 2026
acba985
Removed _Q_at_theta and objective_at_theta
sscini Jan 15, 2026
145c2d8
Added comments for reviewers, ran black.
sscini Jan 15, 2026
337095d
Corrected count_total_experiments to divide by # outputs.
sscini Jan 15, 2026
837192c
Ran black.
sscini Jan 15, 2026
4b46c30
Undo change to count_total_experiments.
sscini Jan 15, 2026
b9cf010
Update mpi_utils.py
sscini Jan 19, 2026
062a9ee
Switched unknown_params to Vars
sscini Jan 19, 2026
5baaa2f
Fixed number for cov_n, still need to adjust counting function
sscini Jan 19, 2026
c8194ac
Added question for reviewers
sscini Jan 19, 2026
26d70e3
Ran black
sscini Jan 19, 2026
4aa027d
Changed retrieval of variables for ind_red_hes.
sscini Jan 19, 2026
26ba2ea
Added note related to count_total_experiments, commented out assertion.
sscini Jan 19, 2026
dd926f8
Ran black
sscini Jan 19, 2026
7b70d1d
Removed dependence on cov_est for theta_est(), added bool for len(exp…
sscini Jan 19, 2026
43cbaa4
Merge branch 'main' into Q_opt-redesign
sscini Jan 19, 2026
07798c9
Ran black
sscini Jan 19, 2026
b325f0d
Attempted adding support for indexed vars
sscini Jan 19, 2026
8b47430
Ran black
sscini Jan 20, 2026
aac1476
Addressed some review comments.
sscini Jan 20, 2026
66a1396
Merge branch 'Pyomo:main' into Q_opt-redesign
sscini Jan 21, 2026
3957dc9
Added Shammah fix for exp count
sscini Jan 21, 2026
382ea20
Updates to address comments.
sscini Jan 21, 2026
0da606f
Addressed some comments, simplified scenarios
sscini Jan 22, 2026
935b700
Replaced getattr with suffix calls.
sscini Jan 22, 2026
1fc71ee
Updated, ran black.
sscini Jan 22, 2026
56ac15d
Noted failing tests, currently 15
sscini Jan 22, 2026
60dc796
Removed old comment during dev
sscini Jan 22, 2026
6bf439e
Fixed scenario count issue, ran black.
sscini Jan 22, 2026
a68906b
Added else statement in cov calc
sscini Jan 23, 2026
f31a35f
Update test_parmest.py
sscini Jan 23, 2026
b124def
Update parmest.py
sscini Jan 23, 2026
2908c78
Update simple_reaction_parmest_example.py
sscini Jan 23, 2026
58435d3
Added measurement error to reactor_design
sscini Jan 23, 2026
db646ba
Changed to built-in SSE
sscini Jan 23, 2026
d222c4f
Commented out model_initialized
sscini Jan 23, 2026
9d829c4
Merge branch 'Pyomo:main' into Q_opt-redesign
sscini Jan 23, 2026
7ffab76
Merge remote-tracking branch 'refs/remotes/origin/Q_opt-redesign' int…
sscini Jan 23, 2026
e267983
Remove solver import
sscini Jan 23, 2026
e3ae6e6
Ran black
sscini Jan 23, 2026
345c3f2
Update test_parmest.py
sscini Jan 23, 2026
6c3d5a0
Added back option, ran black
sscini Jan 23, 2026
49b787a
Rearranged _Q_opt for fix_theta
sscini Jan 23, 2026
8cf624e
Ran black
sscini Jan 26, 2026
c248c74
Adjusting parmest models, in progress
sscini Jan 27, 2026
b975089
Added more description, simplified comparison
sscini Jan 27, 2026
a63e4fc
Update parameter_estimation_example.py
sscini Jan 27, 2026
b92aa7d
Ran black
sscini Jan 27, 2026
471dbe7
Adjusted if statement
sscini Jan 27, 2026
98d91fc
Removed answered questions
sscini Jan 27, 2026
a6821ae
Merge branch 'Pyomo:main' into Q_opt-redesign
sscini Jan 27, 2026
f0ef6d6
Update parmest.py
sscini Feb 2, 2026
1f86b03
Fixed models in variants test
sscini Feb 5, 2026
72b4345
Merge branch 'Pyomo:main' into Q_opt-redesign
sscini Feb 5, 2026
c495e0f
Merge remote-tracking branch 'refs/remotes/origin/Q_opt-redesign' int…
sscini Feb 5, 2026
82ee4ce
Update test_parmest.py
sscini Feb 5, 2026
559a900
Update parmest.py
sscini Feb 5, 2026
65067d5
Update parmest.py
sscini Feb 5, 2026
db26533
Temporary remove failing test.
sscini Feb 5, 2026
c9b19d7
Fixed experiment counter
sscini Feb 5, 2026
7bba006
Modified testing
sscini Feb 5, 2026
2cd2614
Removed extra print statements
sscini Feb 5, 2026
5ba4fab
Updated error message.
sscini Feb 5, 2026
ee57ec9
Adjusted experimental counter
sscini Feb 5, 2026
7cffb34
Update test_examples.py
sscini Feb 6, 2026
ebbd279
Addressed comments
sscini Feb 6, 2026
0c1e605
Merge branch 'Pyomo:main' into Q_opt-redesign
sscini Feb 11, 2026
92a2dd6
Update simple_reaction_parmest_example.py
sscini Feb 15, 2026
854366b
Merge branch 'Pyomo:main' into Q_opt-redesign
sscini Feb 19, 2026
72204d9
Merge branch 'Pyomo:main' into Q_opt-redesign
sscini Feb 23, 2026
ed2cf54
Merge branch 'Pyomo:main' into Q_opt-redesign
sscini Mar 6, 2026
cc0513a
Updated interface, added block scenario tests.
sscini Mar 6, 2026
9c0d0a3
Merge branch 'Pyomo:main' into Q_opt-redesign
sscini Mar 6, 2026
4df5b48
Merge branch 'main' into Q_opt-redesign
sscini Mar 17, 2026
4fc0336
Merge branch 'main' into Q_opt-redesign
sscini Mar 24, 2026
b372edd
Moved new tests into the main parmest testing file.
sscini Mar 24, 2026
41e8e98
Ran black
sscini Mar 24, 2026
9fe600f
Update test_parmest.py
sscini Mar 25, 2026
48ba6a6
Merge branch 'main' into Q_opt-redesign
sscini Mar 25, 2026
ba4091c
Merge branch 'Pyomo:main' into Q_opt-redesign
sscini Mar 27, 2026
eba10b3
Removed covariance functionality from theta_est, in progress
sscini Mar 27, 2026
c997944
Update simple_reaction_parmest_example.py
sscini Mar 27, 2026
d2b5d74
Update simple_reaction_parmest_example.py
sscini Mar 27, 2026
ae9808f
Update parameter_estimation_example.py
sscini Mar 27, 2026
9fa6528
Adjusted tests, ran black
sscini Mar 27, 2026
cb1ecea
Update test_parmest.py
sscini Mar 27, 2026
261a78f
Delete scenarios.csv
sscini Mar 27, 2026
3dca7d7
Merge branch 'main' into Q_opt-redesign
blnicho Apr 2, 2026
959d58e
Merge branch 'Pyomo:main' into Q_opt-redesign
sscini Apr 7, 2026
b21c34d
Merge branch 'Pyomo:main' into Q_opt-redesign
sscini Apr 8, 2026
1b6c63a
Merge branch 'main' into Q_opt-redesign
sscini Apr 9, 2026
f768ea3
Merge branch 'main' into Q_opt-redesign
sscini Apr 13, 2026
867e642
Merge branch 'main' into Q_opt-redesign
sscini Apr 15, 2026
6d7eb7a
Merge branch 'main' into Q_opt-redesign
sscini Apr 21, 2026
a39d367
Merge branch 'main' into Q_opt-redesign
sscini Apr 22, 2026
deb3c5a
Merge branch 'Pyomo:main' into Q_opt-redesign
sscini Apr 24, 2026
9fcf4f1
Merge branch 'main' into Q_opt-redesign
sscini Apr 28, 2026
a188dd7
Merge branch 'main' into Q_opt-redesign
blnicho Apr 29, 2026
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
157 changes: 157 additions & 0 deletions pyomo/contrib/parmest/parmest.py
Original file line number Diff line number Diff line change
Expand Up @@ -971,6 +971,92 @@ def _instance_creation_callback(self, experiment_number=None, cb_data=None):
model = self._create_parmest_model(experiment_number)
return model

def _create_scenario_blocks(self):
# Create scenario block structure
Comment thread
sscini marked this conversation as resolved.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
# Create scenario block structure

This comment can be removed now that there is a docstring

# Code is still heavily hypothetical and needs to be thought over and debugged.
# Utility function for _Q_opt_simple
# Make a block of model scenarios, one for each experiment in exp_list

# Create a parent model to hold scenario blocks
model = pyo.ConcreteModel()
model.exp_scenarios = pyo.Block(range(len(self.exp_list)))
for i in range(len(self.exp_list)):
# Create parmest model for experiment i
parmest_model = self._create_parmest_model(i)
# Assign parmest model to block
model.exp_scenarios[i].transfer_attributes_from(parmest_model)

# Make an objective that sums over all scenario blocks
def total_obj(m):
return sum(
block.Total_Cost_Objective for block in m.exp_scenarios.values()
) / len(self.exp_list)

model.Obj = pyo.Objective(rule=total_obj, sense=pyo.minimize)

# Make sure all the parameters are linked across blocks
for name in self.estimator_theta_names:
# Get the variable from the first block
ref_var = getattr(model.exp_scenarios[0], name)
for i in range(1, len(self.exp_list)):
curr_var = getattr(model.exp_scenarios[i], name)
# Constrain current variable to equal reference variable
model.add_component(
f"Link_{name}_Block0_Block{i}",
pyo.Constraint(expr=curr_var == ref_var),
)

# Deactivate the objective in each block to avoid double counting
for i in range(len(self.exp_list)):
model.exp_scenarios[i].Total_Cost_Objective.deactivate()

model.pprint()

return model

# Redesigning simpler version of _Q_opt
# Still work in progress
def _Q_opt_simple(
Comment thread
sscini marked this conversation as resolved.
Outdated
self,
return_values=None,
bootlist=None,
ThetaVals=None,
solver="ipopt",
calc_cov=NOTSET,
cov_n=NOTSET,
):
'''
Comment thread
sscini marked this conversation as resolved.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Please use double quotes for docstrings

Suggested change
'''
"""

Making new version of _Q_opt that uses scenario blocks, similar to DoE.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Could you make this method summary a bit more verbose. It currently reads like a commit message rather than a description of what the method is doing. You don't need to refer to it as a "new version".


Steps:
1. Load model - parmest model should be labeled
2. Create scenario blocks (biggest redesign) - clone model to have one per experiment
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
2. Create scenario blocks (biggest redesign) - clone model to have one per experiment
2. Create scenario blocks - clone model to have one per experiment

3. Define objective and constraints for the block
4. Solve the block as a single problem
5. Analyze results and extract parameter estimates

'''

# Create scenario blocks using utility function
model = self._create_scenario_blocks()

solver = SolverFactory('ipopt')
if self.solver_options is not None:
for key in self.solver_options:
solver.options[key] = self.solver_options[key]

solve_result = solver.solve(model, tee=self.tee)
assert_optimal_termination(solve_result)

# Extract objective value
obj_value = pyo.value(model.Obj)
theta_estimates = {}
# Extract theta estimates from first block
for name in self.estimator_theta_names:
theta_estimates[name] = pyo.value(getattr(model.exp_scenarios[0], name))
Comment thread
sscini marked this conversation as resolved.
Outdated

return obj_value, theta_estimates

def _Q_opt(
self,
ThetaVals=None,
Expand Down Expand Up @@ -1683,6 +1769,77 @@ def theta_est(
cov_n=cov_n,
)

# Replicate of theta_est for testing simplified _Q_opt
# Still work in progress
def theta_est_simple(
self, solver="ipopt", return_values=[], calc_cov=NOTSET, cov_n=NOTSET
):
"""
Parameter estimation using all scenarios in the data

Parameters
----------
solver: str, optional
Currently only "ef_ipopt" is supported. Default is "ef_ipopt".
return_values: list, optional
List of Variable names, used to return values from the model
for data reconciliation
calc_cov: boolean, optional
DEPRECATED.

If True, calculate and return the covariance matrix
(only for "ef_ipopt" solver). Default is NOTSET
cov_n: int, optional
DEPRECATED.

If calc_cov=True, then the user needs to supply the number of datapoints
that are used in the objective function. Default is NOTSET

Returns
-------
obj_val: float
The objective function value
theta_vals: pd.Series
Estimated values for theta
var_values: pd.DataFrame
Variable values for each variable name in
return_values (only for solver='ipopt')
"""
assert isinstance(solver, str)
assert isinstance(return_values, list)
assert (calc_cov is NOTSET) or isinstance(calc_cov, bool)

if calc_cov is not NOTSET:
deprecation_warning(
"theta_est(): `calc_cov` and `cov_n` are deprecated options and "
"will be removed in the future. Please use the `cov_est()` function "
"for covariance calculation.",
version="6.9.5",
)
else:
calc_cov = False

# check if we are using deprecated parmest
if self.pest_deprecated is not None and calc_cov:
return self.pest_deprecated.theta_est(
solver=solver,
return_values=return_values,
calc_cov=calc_cov,
cov_n=cov_n,
)
elif self.pest_deprecated is not None and not calc_cov:
return self.pest_deprecated.theta_est(
solver=solver, return_values=return_values
)

return self._Q_opt_simple(
solver=solver,
return_values=return_values,
bootlist=None,
calc_cov=calc_cov,
cov_n=cov_n,
)

def cov_est(self, method="finite_difference", solver="ipopt", step=1e-3):
"""
Covariance matrix calculation using all scenarios in the data
Expand Down
Loading