Description
Most mainstream programming languages define logical operator precedence such that AND
binds more tightly than OR
(i.e., AND
has higher precedence). An expression A AND B OR C
is typically evaluated as (A AND B) OR C
. However, control rules in the input file of EPANET currently uses the opposite convention: OR
has higher precedence than AND
. In EPANET rules, an expression like IF condition1 AND condition2 OR condition3 THEN ...
is evaluated as condition1 AND (condition2 OR condition3)
.
This difference from standard programming practice can be a source of confusion and potential errors, particularly for new users who come from a programming background and expect the standard AND > OR
precedence. While the EPANET manual documents the current behaviour, it's easy to overlook or forget, leading to rules that don't function as intended.
We propose adding a new option to the [OPTIONS]
section of the EPANET input file:
[OPTIONS]
; To use standard AND > OR precedence:
RULE PRECEDENCE STANDARD
; To explicitly use the default EPANET OR > AND precedence (or if line is omitted):
; RULE PRECEDENCE LEGACY
The default behaviour should be LEGACY (until we have EPANET 3.0? ). Feedback on the option names is appreciated.
On the implementation side, refactoring the evalpremises()
function is straightforward:
int evalpremises(Project *pr, int i)
{
Network *net = &pr->network;
int result;
Spremise *p = net->Rule[i].Premises;
+ if (legacy precedence) // TODO
+ {
result = TRUE;
while (p != NULL)
{
if (p->logop == r_OR)
{
if (result == FALSE) result = checkpremise(pr, p);
}
else
{
if (result == FALSE) return (FALSE);
result = checkpremise(pr, p);
}
p = p->next;
}
+ }
+ else
+ {
+ result = FALSE;
+ while (p != NULL)
+ {
+ if (p->logop == r_AND)
+ {
+ if (result == TRUE) result = checkpremise(pr, p);
+ }
+ else
+ {
+ if (result == TRUE) return (TRUE);
+ result = checkpremise(pr, p);
+ }
+ }
+ }
return result;
}
To me, the main challenge lies in deciding which struct should hold the precedence policy.