ModifyingRuleBaseControls

These modifications allow rule based controls to be modified with the
additional functions added in the dll toolkit
This commit is contained in:
AngelaMarchi
2016-09-23 13:07:06 +09:30
parent 8b4a03d349
commit 6f8be1be55
6 changed files with 664 additions and 46 deletions

View File

@@ -815,6 +815,7 @@ int DLLEXPORT ENgetcount(int code, int *count)
case EN_PATCOUNT: *count = Npats; break;
case EN_CURVECOUNT: *count = Ncurves; break;
case EN_CONTROLCOUNT: *count = Ncontrols; break;
case EN_RULECOUNT: *count = Nrules; break;
default: return(251);
}
return(0);
@@ -3163,5 +3164,295 @@ int DLLEXPORT ENgetaveragepatternvalue(int index, EN_API_FLOAT_TYPE *value)
}
int DLLEXPORT ENgetrule(int index, int *nPremises, int *nTrueActions, int *nFalseActions, double *priority)
{
/*----------------------------------------------------------------
** Input: index = index of the rule
** nPremises = number of conditions (IF AND OR)
** nTrueActions = number of actions with true conditions (THEN)
** nFalseActions = number of actions with false conditions (ELSE)
** priority = rule priority
** Output: none
** Returns: error code
**----------------------------------------------------------------
*/
int count;
struct Premise *p;
struct Action *c;
if (index > Nrules) return(257);
*priority = Rule[index].priority;
count = 1;
p = Rule[index].Pchain;
while (p->next != NULL)
{
count++;
p=p->next;
}
*nPremises = count;
count = 1;
c=Rule[index].Tchain;
while (c->next != NULL)
{
count++;
c = c->next;
}
*nTrueActions = count;
c = Rule[index].Fchain;
count = 0;
if (c != NULL)
{
count = 1;
while (c->next != NULL)
{
count ++;
c = c->next;
}
}
*nFalseActions = count;
return(0);
}
int DLLEXPORT ENgetpremise(int indexRule, int idxPremise, int *logop, int *object, int *indexObj, int *variable, int *relop, int *status, double *value)
{
int count = 1, error = 0, nPremises, a, b;
double priority;
struct Premise *p;
if (indexRule > Nrules) return(257);
error = ENgetrule(indexRule, &nPremises, &a, &b, &priority);
if (idxPremise > nPremises) return(258);
p = Rule[indexRule].Pchain;
while (count < idxPremise)
{
count++;
p = p->next;
}
*logop = p->logop;
*object = p->object;
*indexObj = p->index;
*variable = p->variable;
*relop = p->relop;
*status = p->status;
*value = p[0].value;
return(0);
}
int DLLEXPORT ENsetrulepriority(int index, double priority)
{
/*----------------------------------------------------------------
** Input: index = index of the rule
** priority = rule priority
** Output: none
** Returns: error code
**----------------------------------------------------------------
*/
if (index > Nrules) return(257);
Rule[index].priority = priority;
return(0);
}
int DLLEXPORT ENsetpremise(int indexRule, int indexPremise, int logop, int object, int indexObj, int variable, int relop, int status, double value)
{
int count = 1,error = 0, nPremises, a, b;
double priority;
struct Premise *p;
if (indexRule > Nrules) return(257);
error = ENgetrule(indexRule, &nPremises, &a, &b, &priority);
if (indexPremise > nPremises) return(258);
p = Rule[indexRule].Pchain;
while (count < indexPremise)
{
count++;
p = p->next;
}
p->logop = logop;
p->object = object;
p->index = indexObj;
p->variable = variable;
p->relop = relop;
p->status = status;
p->value = value;
return(0);
}
int DLLEXPORT ENsetpremiseindex(int indexRule, int indexPremise, int indexObj)
{
int count = 1,error = 0, nPremises, a, b;
double priority;
struct Premise *p;
if (indexRule > Nrules) return(257);
error = ENgetrule(indexRule, &nPremises, &a, &b, &priority);
if (indexPremise > nPremises) return(258);
p = Rule[indexRule].Pchain;
while (count < indexPremise)
{
count++;
p = p->next;
}
p->index = indexObj;
return(0);
}
int DLLEXPORT ENsetpremisestatus(int indexRule, int indexPremise, int status)
{
int count = 1, error = 0, nPremises, a, b;
double priority;
struct Premise *p;
if (indexRule > Nrules) return(257);
error = ENgetrule(indexRule, &nPremises, &a, &b, &priority);
if (indexPremise > nPremises) return(258);
p = Rule[indexRule].Pchain;
while (count < indexPremise)
{
count++;
p = p->next;
}
p->status = status;
return(0);
}
int DLLEXPORT ENsetpremisevalue(int indexRule, int indexPremise, double value)
{
int count = 1,error = 0, nPremises, a, b;
double priority;
struct Premise *p;
if (indexRule > Nrules) return(257);
error = ENgetrule(indexRule, &nPremises, &a, &b, &priority);
if (indexPremise > nPremises) return(258);
p = Rule[indexRule].Pchain;
while (count < indexPremise)
{
count++;
p = p->next;
}
p->value = value;
return(0);
}
int DLLEXPORT ENgettrueaction(int indexRule, int indexAction, int *indexLink, int *status, double *setting)
{
int count = 1, error = 0, nTrueAction, c, b;
double priority;
struct Action *a;
if (indexRule > Nrules) return(252);
error = ENgetrule(indexRule, &c, &nTrueAction, &b, &priority);
if (indexAction > nTrueAction) return(253);
a = Rule[indexRule].Tchain;
while (count<indexAction)
{
count++;
a = a->next;
}
*indexLink = a->link;
*status = a->status;
*setting = a->setting;
return(0);
}
int DLLEXPORT ENsettrueaction(int indexRule, int indexAction, int indexLink, int status,double setting)
{
int count = 1, error = 0, nTrueAction, c, b;
double priority;
struct Action *a;
if (indexRule > Nrules) return(257);
error = ENgetrule(indexRule, &c, &nTrueAction, &b, &priority);
if (indexAction > nTrueAction) return(258);
a = Rule[indexRule].Tchain;
while (count<indexAction)
{
count++;
a = a->next;
}
a->link = indexLink;
a->status = status;
a->setting = setting;
return(0);
}
int DLLEXPORT ENgetfalseaction(int indexRule, int indexAction, int *indexLink, int *status, double *setting)
{
int count = 1, error = 0, nFalseAction, c, b;
double priority;
struct Action *a;
if (indexRule > Nrules) return(257);
error = ENgetrule(indexRule, &c, &b, &nFalseAction, &priority);
if (indexAction > nFalseAction) return(258);
a = Rule[indexRule].Fchain;
while (count < indexAction)
{
count++;
a = a->next;
}
*indexLink = a->link;
*status = a->status;
*setting = a->setting;
return(0);
}
int DLLEXPORT ENsetfalseaction(int indexRule, int indexAction, int indexLink, int status,double setting)
{
int count = 1, error = 0, nFalseAction, c, b;
double priority;
struct Action *a;
if (indexRule > Nrules) return(257);
error = ENgetrule(indexRule, &c, &b, &nFalseAction, &priority);
if (indexAction > nFalseAction) return(258);
a = Rule[indexRule].Fchain;
while (count < indexAction)
{
count++;
a = a->next;
}
a->link = indexLink;
a->status = status;
a->setting = setting;
return(0);
}
int DLLEXPORT ENgetruleID(int indexRule, char* id)
{
strcpy(id,"");
if (!Openflag) return(102);
if (indexRule < 1 || indexRule > Nrules) return(257);
strcpy(id,Rule[indexRule].label);
return(0);
}
/*************************** END OF EPANET.C ***************************/

View File

@@ -76,7 +76,7 @@ void saveauxdata(FILE *f) /
if (sect == _END) break;
switch(sect)
{
case _RULES:
//case _RULES:
case _COORDS: if (Coordflag == FALSE)
{
fprintf(f, "%s", line);
@@ -95,7 +95,7 @@ void saveauxdata(FILE *f) /
/* Write lines appearing in the section to file */
switch(sect)
{
case _RULES:
//case _RULES:
case _COORDS: if (Coordflag == FALSE)
{
fprintf(f, "%s", line);
@@ -120,6 +120,7 @@ int saveinpfile(char *fname)
*/
{
int i,j,n;
int errcode;
double d,kc,ke,km,ucf;
char s[MAXLINE+1], s1[MAXLINE+1], s2[MAXLINE+1];
Pdemand demand;
@@ -623,6 +624,15 @@ int saveinpfile(char *fname)
}
fprintf(f, "\n\n");
fprintf(f, "\n\n[RULES]");
for (i=1; i<=Nrules; i++)
{
fprintf(f, "\nRULE %s",Rule[i].label);
errcode = writeRuleinInp(f, i);
fprintf(f, "\n");
}
fprintf(f, "\n\n");
/* Write [COORDINATES] section */
if (Coordflag == TRUE)

View File

@@ -36,48 +36,6 @@ AUTHOR: L. Rossman
#define EXTERN extern
#include "vars.h"
struct Premise /* Rule Premise Clause */
{
int logop; /* Logical operator */
int object; /* Node or link */
int index; /* Object's index */
int variable; /* Pressure, flow, etc. */
int relop; /* Relational operator */
int status; /* Variable's status */
double value; /* Variable's value */
struct Premise *next;
};
struct Action /* Rule Action Clause */
{
int link; /* Link index */
int status; /* Link's status */
double setting; /* Link's setting */
struct Action *next;
};
struct aRule /* Control Rule Structure */
{
char label[MAXID+1]; /* Rule character label */
double priority; /* Priority level */
struct Premise *Pchain; /* Linked list of premises */
struct Action *Tchain; /* Linked list of actions if true */
struct Action *Fchain; /* Linked list of actions if false */
struct aRule *next;
};
struct ActItem /* Action list item */
{
int ruleindex; /* Index of rule action belongs to */
struct Action *action; /* An action structure */
struct ActItem *next;
};
struct aRule *Rule; /* Array of rules */
struct ActItem *ActList; /* Linked list of action items */
int RuleState; /* State of rule interpreter */
long Time1; /* Start of rule evaluation time interval (sec) */
struct Premise *Plast; /* Previous premise clause */
enum Rulewords {r_RULE,r_IF,r_AND,r_OR,r_THEN,r_ELSE,r_PRIORITY,r_ERROR};
char *Ruleword[] = {w_RULE,w_IF,w_AND,w_OR,w_THEN,w_ELSE,w_PRIORITY,NULL};
@@ -105,6 +63,8 @@ char *Value[] = {"XXXX", w_OPEN, w_CLOSED, w_ACTIVE,NULL};
extern char *Tok[MAXTOKS];
extern int Ntokens;
extern char *StatTxt[];
/*
** Local function prototypes are defined here and not in FUNCS.H
** because some of them utilize the Premise and Action structures
@@ -125,7 +85,7 @@ int takeactions(void);
void clearactlist(void);
void clearrules(void);
void ruleerrmsg(int);
int writeRuleinInp(FILE *f, int RuleIdx);
void initrules()
/*
@@ -967,5 +927,210 @@ void ruleerrmsg(int err)
writeline(fmt);
}
int writeRuleinInp(FILE *f, int RuleIdx){
//int i,j;
struct Premise *p;
struct Action *a;
int hours = 0, minutes = 0, seconds = 0;
p = Rule[RuleIdx].Pchain;
if (p->value==MISSING)
{
fprintf(f, "\nIF ");
if ((strncmp(Object[p->object], "NODE", 4)==0) || (strncmp(Object[p->object], "Junc", 4)==0) || (strncmp(Object[p->object], "Reser", 5)==0) || (strncmp(Object[p->object], "Tank", 4)==0) )
{
if (p->index <= Njuncs) fprintf(f,"JUNC %s %s %s %s", Node[p->index].ID, Varword[p->variable], Operator[p->relop], Value[p->status]);
else if (Tank[p->index-Njuncs].A == 0.0) fprintf(f,"RESERV %s %s %s %s", Node[p->index].ID, Varword[p->variable], Operator[p->relop], Value[p->status]);
else fprintf(f,"TANK %s %s %s %s", Node[p->index].ID, Varword[p->variable], Operator[p->relop], Value[p->status]);
}
else
{ //it is a link
if (Link[p->index].Type == PIPE || Link[p->index].Type == CV) fprintf(f,"PIPE %s %s %s %s", Link[p->index].ID, Varword[p->variable], Operator[p->relop], Value[p->status]);
else if (Link[p->index].Type == PUMP) fprintf(f,"PUMP %s %s %s %s", Link[p->index].ID, Varword[p->variable], Operator[p->relop], Value[p->status]);
else fprintf(f,"VALVE %s %s %s %s", Link[p->index].ID, Varword[p->variable], Operator[p->relop], Value[p->status]);
}
}
else
{
if (p->variable == r_TIME)
{
hours = (int) p->value / 3600;
minutes = (int) ((p->value - 3600*hours)/60);
seconds = (int) (p->value - 3600*hours - minutes*60);
fprintf(f, "\nIF %s %s %s %d:%02d:%02d", Object[p->object], Varword[p->variable], Operator[p->relop], hours, minutes, seconds);
}
else
{
if (p->variable == r_CLOCKTIME)
{
hours = (int) p->value / 3600;
minutes = (int) ((p->value - 3600*hours)/60);
seconds = (int) (p->value - 3600*hours - minutes*60);
if (hours < 12) fprintf(f, "\nIF %s %s %s %d:%02d:%02d AM", Object[p->object], Varword[p->variable], Operator[p->relop], hours, minutes, seconds);
else fprintf(f, "\nIF %s %s %s %d:%02d:%02d PM", Object[p->object], Varword[p->variable], Operator[p->relop], hours-12, minutes, seconds);
}
else
{
if (p->variable == r_FILLTIME || p->variable == r_DRAINTIME) fprintf(f, "\nIF %s %s %s %s %.4lf", Object[p->object], Node[p->index].ID, Varword[p->variable], Operator[p->relop], p->value/3600.0);
else
{
fprintf(f, "\nIF ");
if ((strncmp(Object[p->object], "NODE", 4)==0) || (strncmp(Object[p->object], "Junc", 4)==0) || (strncmp(Object[p->object], "Reser", 5)==0) || (strncmp(Object[p->object], "Tank", 4)==0))
{
if (p->index <= Njuncs) fprintf(f,"JUNC %s %s %s %.4lf", Node[p->index].ID, Varword[p->variable], Operator[p->relop], p->value);
else if (Tank[p->index-Njuncs].A == 0.0) fprintf(f,"RESERV %s %s %s %.4lf", Node[p->index].ID, Varword[p->variable], Operator[p->relop], p->value);
else fprintf(f,"TANK %s %s %s %.4lf", Node[p->index].ID, Varword[p->variable], Operator[p->relop], p->value);
}
else
{ //it is a link
if (Link[p->index].Type == PIPE || Link[p->index].Type == CV) fprintf(f,"PIPE %s %s %s %.4lf", Link[p->index].ID, Varword[p->variable], Operator[p->relop], p->value);
else if (Link[p->index].Type == PUMP) fprintf(f,"PUMP %s %s %s %.4lf", Link[p->index].ID, Varword[p->variable], Operator[p->relop], p->value);
else fprintf(f,"VALVE %s %s %s %.4lf", Link[p->index].ID, Varword[p->variable], Operator[p->relop], p->value);
}
}
}
}
}
p = p->next;
while (p != NULL)
{
if (p->value==MISSING)
{
fprintf(f, "\n%s ", Ruleword[p->logop]);
if ((strncmp(Object[p->object], "NODE", 4)==0) || (strncmp(Object[p->object], "Junc", 4)==0) || (strncmp(Object[p->object], "Reser", 5)==0) || (strncmp(Object[p->object], "Tank", 4)==0))
{
if (p->index <= Njuncs) fprintf(f,"JUNC %s %s %s %s", Node[p->index].ID, Varword[p->variable], Operator[p->relop], Value[p->status]);
else if (Tank[p->index-Njuncs].A == 0.0) fprintf(f,"RESERV %s %s %s %s", Node[p->index].ID, Varword[p->variable], Operator[p->relop], Value[p->status]);
else fprintf(f,"TANK %s %s %s %s", Node[p->index].ID, Varword[p->variable], Operator[p->relop], Value[p->status]);
}
else
{ //it is a link
if (Link[p->index].Type == PIPE || Link[p->index].Type == CV) fprintf(f,"PIPE %s %s %s %s", Link[p->index].ID, Varword[p->variable], Operator[p->relop], Value[p->status]);
else if (Link[p->index].Type == PUMP) fprintf(f,"PUMP %s %s %s %s", Link[p->index].ID, Varword[p->variable], Operator[p->relop], Value[p->status]);
else fprintf(f,"VALVE %s %s %s %s", Link[p->index].ID, Varword[p->variable], Operator[p->relop], Value[p->status]);
}
}
else
{
if (p->variable == r_TIME)
{
hours = (int) p->value / 3600;
minutes = (int) ((p->value - 3600*hours)/60);
seconds = (int) (p->value - 3600*hours - minutes*60);
fprintf(f, "\n%s %s %s %s %d:%02d:%02d", Ruleword[p->logop], Object[p->object], Varword[p->variable], Operator[p->relop], hours, minutes, seconds);
}
else
{
if (p->variable == r_CLOCKTIME)
{
hours = (int) p->value / 3600;
minutes = (int) ((p->value - 3600*hours)/60);
seconds = (int) (p->value - 3600*hours - minutes*60);
if (hours < 12) fprintf(f, "\n%s %s %s %s %d:%02d:%02d AM", Ruleword[p->logop], Object[p->object], Varword[p->variable], Operator[p->relop], hours, minutes, seconds);
else fprintf(f, "\n%s %s %s %s %d:%02d:%02d PM", Ruleword[p->logop], Object[p->object], Varword[p->variable], Operator[p->relop], hours-12, minutes, seconds);
}
else
{
if (p->variable == r_FILLTIME || p->variable == r_DRAINTIME) fprintf(f, "\nIF %s %s %s %s %.4lf", Object[p->object], Node[p->index].ID, Varword[p->variable], Operator[p->relop], p->value/3600.0);
else
{
fprintf(f, "\n%s ", Ruleword[p->logop]);
if ((strncmp(Object[p->object], "NODE", 4)==0) || (strncmp(Object[p->object], "Junc", 4)==0) || (strncmp(Object[p->object], "Reser", 5)==0) || (strncmp(Object[p->object], "Tank", 4)==0)) {
if (p->index <= Njuncs) fprintf(f,"JUNC %s %s %s %.4lf", Node[p->index].ID, Varword[p->variable], Operator[p->relop], p->value);
else if (Tank[p->index-Njuncs].A == 0.0) fprintf(f,"RESERV %s %s %s %.4lf", Node[p->index].ID, Varword[p->variable], Operator[p->relop], p->value);
else fprintf(f,"TANK %s %s %s %.4lf", Node[p->index].ID, Varword[p->variable], Operator[p->relop], p->value);
}
else
{ //it is a link
if (Link[p->index].Type == PIPE || Link[p->index].Type == CV) fprintf(f,"PIPE %s %s %s %.4lf", Link[p->index].ID, Varword[p->variable], Operator[p->relop], p->value);
else if (Link[p->index].Type == PUMP) fprintf(f,"PUMP %s %s %s %.4lf", Link[p->index].ID, Varword[p->variable], Operator[p->relop], p->value);
else fprintf(f,"VALVE %s %s %s %.4lf", Link[p->index].ID, Varword[p->variable], Operator[p->relop], p->value);
}
}
}
}
}
p = p->next;
}
a = Rule[RuleIdx].Tchain;
if (a->setting==MISSING)
{
if (Link[a->link].Type == PIPE || Link[a->link].Type == CV) fprintf(f, "\nTHEN PIPE %s STATUS IS %s", Link[a->link].ID, Value[a->status]);
else if (Link[a->link].Type == PUMP) fprintf(f, "\nTHEN PUMP %s STATUS IS %s", Link[a->link].ID, Value[a->status]);
else fprintf(f, "\nTHEN VALVE %s STATUS IS %s", Link[a->link].ID, Value[a->status]);
}
else
{
if (Link[a->link].Type == PIPE || Link[a->link].Type == CV) fprintf(f, "\nTHEN PIPE %s SETTING IS %.4f", Link[a->link].ID, a->setting);
else if (Link[a->link].Type == PUMP) fprintf(f, "\nTHEN PUMP %s SETTING IS %.4f", Link[a->link].ID, a->setting);
else fprintf(f, "\nTHEN VALVE %s SETTING IS %.4f", Link[a->link].ID, a->setting);
}
a = a->next;
while (a != NULL)
{
if (a->setting==MISSING)
{
if (Link[a->link].Type == PIPE || Link[a->link].Type == CV) fprintf(f, "\nAND PIPE %s STATUS IS %s", Link[a->link].ID, Value[a->status]);
else if (Link[a->link].Type == PUMP) fprintf(f, "\nAND PUMP %s STATUS IS %s", Link[a->link].ID, Value[a->status]);
else fprintf(f, "\nAND VALVE %s STATUS IS %s", Link[a->link].ID, Value[a->status]);
}
else
{
if (Link[a->link].Type == PIPE || Link[a->link].Type == CV) fprintf(f, "\nAND PIPE %s SETTING IS %.4f", Link[a->link].ID, a->setting);
else if (Link[a->link].Type == PUMP) fprintf(f, "\nAND PUMP %s SETTING IS %.4f", Link[a->link].ID, a->setting);
else fprintf(f, "\nAND VALVE %s SETTING IS %.4f", Link[a->link].ID, a->setting);
}
a = a->next;
}
a = Rule[RuleIdx].Fchain;
if (a != NULL)
{
if (a->setting==MISSING)
{
if (Link[a->link].Type == PIPE || Link[a->link].Type == CV) fprintf(f, "\nELSE PIPE %s STATUS IS %s", Link[a->link].ID, Value[a->status]);
else if (Link[a->link].Type == PUMP) fprintf(f, "\nELSE PUMP %s STATUS IS %s", Link[a->link].ID, Value[a->status]);
else fprintf(f, "\nELSE VALVE %s STATUS IS %s", Link[a->link].ID, Value[a->status]);
}
else
{
if (Link[a->link].Type == PIPE || Link[a->link].Type == CV) fprintf(f, "\nELSE PIPE %s SETTING IS %.4f", Link[a->link].ID, a->setting);
else if (Link[a->link].Type == PUMP) fprintf(f, "\nELSE PUMP %s SETTING IS %.4f", Link[a->link].ID, a->setting);
else fprintf(f, "\nELSE VALVE %s SETTING IS %.4f", Link[a->link].ID, a->setting);
}
a = a->next;
while (a != NULL)
{
if (a->setting==MISSING)
{
if (Link[a->link].Type == PIPE || Link[a->link].Type == CV) fprintf(f, "\nAND PIPE %s STATUS IS %s", Link[a->link].ID, Value[a->status]);
else if (Link[a->link].Type == PUMP) fprintf(f, "\nAND PUMP %s STATUS IS %s", Link[a->link].ID, Value[a->status]);
else fprintf(f, "\nAND VALVE %s STATUS IS %s", Link[a->link].ID, Value[a->status]);
}
else
{
if (Link[a->link].Type == PIPE || Link[a->link].Type == CV) fprintf(f, "\nAND PIPE %s SETTING IS %.4f", Link[a->link].ID, a->setting);
else if (Link[a->link].Type == PUMP) fprintf(f, "\nAND PUMP %s SETTING IS %.4f", Link[a->link].ID, a->setting);
else fprintf(f, "\nAND VALVE %s SETTING IS %.4f", Link[a->link].ID, a->setting);
}
a = a->next;
}
}
if (Rule[RuleIdx].priority != 0) fprintf(f, "\nPRIORITY %.4f", Rule[RuleIdx].priority);
return(0);
}
/***************** END OF RULES.C ******************/

View File

@@ -497,6 +497,9 @@ AUTHOR: L. Rossman
#define ERR254 "Input Error 254: Function call error - Node have no coordinates."
#define ERR255 "Input Error 255: Function call error - Coordinates were not loaded."
#define ERR257 "Input Error 257: rule does not exist."
#define ERR258 "Input Error 258: condition or action index specified in rule does not exist."
#define ERR301 "File Error 301: identical file names."
#define ERR302 "File Error 302: cannot open input file."
#define ERR303 "File Error 303: cannot open report file."