Optimization

Constraints for Input Values

Previously, optimization was failing to use input values for some slots if the policy set didn't need the value either directly or indirectly. One noticeable example was pool elevation inputs for level power reservoirs.

Now, an input value leads to an expression, slot[t] = input value. This expression is forced into the model through the "linearization" process. The results depend on what happens to this expression during linearization. In the case of pool elevation, for example, the expression is replaced initially with an equivalent expression for storage and eventually reflected by setting the bounds on the storage variable equal to the appropriate value. A similar process is used for any slot replaced by substitution.

If instead, the slot is not replaced by this kind of substitution, then the original expression is introduced as a hard constraint. If the slot is linearized by a method other than substitution, the slot in the constraint will be replaced by a linear expression of other slots.

If the slot is not linearized, its defining constraints will be introduced, and the value will be used in those constraints.

If a slot is linked to another slot with an input value, this process is followed for both slots.

Slot minimum/maximum values are optional for decision slot variables that have a value. In the past, such variables would never be introduced, but now that they are linearizing expressions which contain variables with values, these variables exist.

Modified definitions

The Tailwater Base Value was added to the list of slots defined by certain optimization definitions.

Modified the substitution approximation code

When translating a constraint on one slot to a constraint on another slot, the original constraint value may lie outside of the table describing the slot relationship. The table may imply that the constraint cannot be satisfied. In this case, RiverWare now issues an error. Alternatively, the table may imply that the constraint is always satisfied. In this case, RiverWare now issues a warning that alerts the user that the table may be missing values.

Forward lags

When the code encounters the variable s[t] where s is the reach Inflow or Local Inflow slot, in theory, it should write an equation like:

(1) Reach.Outflow[t+Lag] = Reach.Inflow[t] + Reach.Local Inflow[t]

Prior to now, it would write the equation:

(2) Reach.Outflow[t] = Reach.Inflow[t-Lag] + Reach.Local Inflow[t-Lag]

which is incorrect, though until the changes above, this did not cause any noticeable problems.

In practice, this problem currently doesn't arise. If the Inflow or Local Inflow are going to influence the solution, a constraint on outflow will pull their values into the formulation. We may have to revisit this situation in the future if a new lagged physical constraint is added to the model. For now, this would have been a costly fix without any practical benefit.

Instead, Inflow and Local Inflow have been removed from the list of slots whose variables are defined by the reach mass balance definition. Because this leaves Inflow and Local Inflow potentially undefined, the check that all slots referenced in a problem must have at least one definition has been relaxed.

Unconstrained slots

A warning is issued if certain slots are unconstrained during optimization (i.e., they are not linked and NaN). Currently, these slots are Reservoir.Inflow, Reach.Inflow, Reach.Local Inflow, Confluence.Inflow1, and Confluence.Inflow2. Additional slots may be added to this list in the future.

Optimization

Revised: 08/02/2021