Skip to content

Commit 1ac0910

Browse files
Add method for evaluating decision rules through interface
1 parent b8273f9 commit 1ac0910

File tree

2 files changed

+61
-0
lines changed

2 files changed

+61
-0
lines changed

pyomo/contrib/pyros/dr_interface.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,44 @@ def get_num_coeffs_per_ss_dim(self, simplified=True):
232232
else:
233233
return sum(num_uncertain_params**order for order in range(self.order + 1))
234234

235+
def evaluate(self, uncertain_param_values, ss_idxs=None):
236+
"""
237+
Evaluate decision rule at a given uncertain
238+
parameter realization.
239+
240+
Parameters
241+
----------
242+
uncertain_param_values : (N,) array-like
243+
Uncertain parameter realization.
244+
ss_idxs : None or list of int, optional
245+
Second-stage variable space dimensions for which
246+
to perform the evaluations. If `None` is passed,
247+
then evaluation is performed for all dimensions.
248+
249+
Returns
250+
-------
251+
numpy.ndarray
252+
Array, of length ``len(ss_idxs)``, containing the
253+
polynomial evaluation for each of the specified
254+
second-stage variable space dimensions.
255+
"""
256+
if ss_idxs is None:
257+
ss_idxs = list(range(self.second_stage_var_dim))
258+
param_val_arr = np.asarray(uncertain_param_values)
259+
static_vals = self.static_coeffs[ss_idxs]
260+
261+
affine_vals = 0
262+
if self.order >= 1:
263+
affine_vals = self.affine_coeffs[ss_idxs] @ param_val_arr
264+
265+
quadratic_vals = 0
266+
if self.order >= 2:
267+
quadratic_vals = (
268+
param_val_arr @ self.quadratic_coeffs[ss_idxs] @ param_val_arr
269+
)
270+
271+
return static_vals + affine_vals + quadratic_vals
272+
235273
def get_param_idx_to_coeff_map(self, ss_idx, simplified=True):
236274
"""
237275
Cast the coefficients contained in `self` to a map

pyomo/contrib/pyros/tests/test_dr_interface.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -782,5 +782,28 @@ def test_generate_dr_equations(self):
782782
)
783783

784784

785+
class TestEvaluateDR(unittest.TestCase):
786+
@parameterized.parameterized.expand([[0], [1], [2]])
787+
def test_evaluate_dr(self, dr_order):
788+
static_coeffs = [0.5, 0.8]
789+
affine_coeffs = [[2, 4, 6], [8, 9, 10]]
790+
quadratic_coeffs = [
791+
[[0.01, 0.02, 0.03], [0.04, 0.05, 0.06], [0.07, 0.08, 0.09]],
792+
[[0.10, 0.11, 0.12], [0.13, 0.14, 0.15], [0.16, 0.17, 0.18]],
793+
]
794+
dri = DecisionRuleInterface(
795+
static_coeffs=static_coeffs,
796+
affine_coeffs=affine_coeffs if dr_order >= 1 else None,
797+
quadratic_coeffs=quadratic_coeffs if dr_order >= 2 else None,
798+
)
799+
dr_eval = dri.evaluate([2, 1, 0.5])
800+
expected_evals = {
801+
0: static_coeffs,
802+
1: static_coeffs + np.array([11, 30]),
803+
2: static_coeffs + np.array([11, 30]) + np.array([0.4025, 1.505]),
804+
}
805+
np.testing.assert_allclose(dr_eval, expected_evals[dr_order])
806+
807+
785808
if __name__ == "__main__":
786809
unittest.main()

0 commit comments

Comments
 (0)