@@ -1933,6 +1933,11 @@ def setup_working_model(model_data, user_var_partitioning):
19331933 orig_temp_util_block .user_var_partitioning = VariablePartitioning (
19341934 ** user_var_partitioning ._asdict ()
19351935 )
1936+ # for multi-stage
1937+ orig_temp_util_block .nested_second_stage_variables = (
1938+ config .nested_second_stage_variables
1939+ )
1940+ orig_temp_util_block .nested_uncertain_params = config .nested_uncertain_params
19361941
19371942 # now set up working model
19381943 model_data .working_model = working_model = ConcreteModel ()
@@ -1961,6 +1966,14 @@ def setup_working_model(model_data, user_var_partitioning):
19611966 ** working_temp_util_block .user_var_partitioning ._asdict ()
19621967 )
19631968
1969+ # for multi-stage
1970+ working_model .nested_second_stage_variables = (
1971+ working_temp_util_block .nested_second_stage_variables
1972+ )
1973+ working_model .nested_uncertain_params = (
1974+ working_temp_util_block .nested_uncertain_params
1975+ )
1976+
19641977 # we are done with the util blocks
19651978 delattr (original_model , temp_util_block_attr_name )
19661979 delattr (working_model .user_model , temp_util_block_attr_name )
@@ -2017,6 +2030,22 @@ def setup_working_model(model_data, user_var_partitioning):
20172030 else :
20182031 working_model .original_active_inequality_cons .append (con )
20192032
2033+ # for multi-stage: map adjustable vars to stages
2034+ # and also uncertain params (assuming all were originally Params)
2035+ working_model .adj_var_to_stage_map = ComponentMap ()
2036+ working_model .param_to_stage_map = ComponentMap ()
2037+ ss_vars_param_zip = zip (
2038+ working_model .nested_second_stage_variables ,
2039+ working_model .nested_uncertain_params ,
2040+ )
2041+ for stage_idx , (varlist , paramlist ) in enumerate (ss_vars_param_zip ):
2042+ working_model .adj_var_to_stage_map .update (
2043+ (var , stage_idx ) for var in varlist
2044+ )
2045+ working_model .param_to_stage_map .update (
2046+ (param , stage_idx ) for param in paramlist
2047+ )
2048+
20202049
20212050def standardize_inequality_constraints (model_data ):
20222051 """
@@ -3140,6 +3169,7 @@ def add_decision_rule_constraints(model_data):
31403169 indexed_dr_var_list = model_data .working_model .first_stage .decision_rule_vars
31413170 uncertain_params = model_data .working_model .effective_uncertain_params
31423171 degree = config .decision_rule_order
3172+ param_to_stage_map = model_data .working_model .param_to_stage_map
31433173
31443174 model_data .working_model .second_stage .decision_rule_eqns = decision_rule_eqns = (
31453175 Constraint (range (len (effective_second_stage_vars )))
@@ -3162,6 +3192,9 @@ def add_decision_rule_constraints(model_data):
31623192 ComponentMap ()
31633193 )
31643194
3195+ # for multi-stage
3196+ model_data .working_model .dr_var_to_stage_map = dr_var_to_stage_map = ComponentMap ()
3197+
31653198 # set up uncertain parameter combinations for
31663199 # construction of the monomials of the DR expressions
31673200 monomial_param_combos = []
@@ -3192,6 +3225,10 @@ def add_decision_rule_constraints(model_data):
31923225 # associated monomial with respect to the uncertain params
31933226 dr_var_to_exponent_map [dr_var ] = len (param_combo )
31943227 dr_var_to_param_combo_map [dr_var ] = param_combo
3228+ # for multi-stage
3229+ dr_var_to_stage_map [dr_var ] = max (
3230+ param_to_stage_map [param ] for param in param_combo
3231+ ) if param_combo else 0
31953232
31963233 # declare constraint on model
31973234 decision_rule_eqns [idx ] = dr_expression - eff_ss_var == 0
@@ -3213,14 +3250,25 @@ def enforce_dr_degree(working_blk, config, degree):
32133250 degree : int
32143251 Degree of the DR polynomials that is to be enforced.
32153252 """
3216- for indexed_dr_var in working_blk .first_stage .decision_rule_vars :
3253+ # account for multi-stage setup
3254+ dr_var_to_stage_map = working_blk .dr_var_to_stage_map
3255+ adj_var_to_stage_map = working_blk .adj_var_to_stage_map
3256+ for eff_ss_var , indexed_dr_var in working_blk .eff_ss_var_to_dr_var_map .items ():
32173257 for dr_var in indexed_dr_var .values ():
32183258 dr_var_degree = working_blk .dr_var_to_exponent_map [dr_var ]
3219- if dr_var_degree > degree :
3259+ dr_var_stage = dr_var_to_stage_map [dr_var ]
3260+ ss_var_stage = adj_var_to_stage_map [eff_ss_var ]
3261+ if (dr_var_degree > degree ) or (dr_var_stage > ss_var_stage ):
32203262 dr_var .fix (0 )
32213263 else :
32223264 dr_var .unfix ()
32233265
3266+ # config.progress_logger.debug(
3267+ # f"{dr_var.name}, SS var {eff_ss_var.name}, "
3268+ # f"{dr_var_degree=}, {ss_var_stage=}, {dr_var_stage=}, "
3269+ # f"{dr_var.fixed=}, DR > SS stage {dr_var_stage > ss_var_stage}"
3270+ # )
3271+
32243272
32253273def load_final_solution (model_data , master_soln , original_user_var_partitioning ):
32263274 """
0 commit comments