[Pntool-developers] SF.net SVN: pntool:[247] spnbox
Brought to you by:
compaqdrew,
miordache
From: <mio...@us...> - 2011-05-11 12:20:46
|
Revision: 247 http://pntool.svn.sourceforge.net/pntool/?rev=247&view=rev Author: miordache Date: 2011-05-11 12:20:38 +0000 (Wed, 11 May 2011) Log Message: ----------- Modified Paths: -------------- newcodegen/ProcessTemplate.c newcodegen/SupervisorTemplate.c newcodegen/plantCompiler.c pnheaders/Makefile pnheaders/main_function.c pnheaders/matrix.c pnheaders/matrix.h pnheaders/pns.c pnheaders/pns.h spnbox/linenf.c spnbox/spnbox.h Modified: newcodegen/ProcessTemplate.c =================================================================== --- newcodegen/ProcessTemplate.c 2011-04-08 22:36:44 UTC (rev 246) +++ newcodegen/ProcessTemplate.c 2011-05-11 12:20:38 UTC (rev 247) @@ -88,6 +88,8 @@ ___send_exit_notification(___pthr); + if(p___) free(p___); + debugInfo("The end of the main function was reached"); return 0; Modified: newcodegen/SupervisorTemplate.c =================================================================== --- newcodegen/SupervisorTemplate.c 2011-04-08 22:36:44 UTC (rev 246) +++ newcodegen/SupervisorTemplate.c 2011-05-11 12:20:38 UTC (rev 247) @@ -314,7 +314,7 @@ for(___ptl = ___pr->tlist, ___i = 0; ___i < ___pr->ntlist; ___i++) if(___t == ___ptl[___i].t) break; - if(___ptl) { // That is, if the transition was found + if(___i < ___pr->ntlist) { // That is, if the transition was found ___pr->fireable = ___t; ___pr->atype |= 2; // set the bit 1 ___qlast->next_in_qelist = ___pr; @@ -1060,14 +1060,21 @@ ___a = IsPermissible(___p); // creates EntryList (qelist) if(___a > 0) { // then the request of ___p can be resolved + // Make sure that ___pn is not in EntryList, since everything in + // EntryList will be removed from the queue + + for(; ___pn; ___pn = ___pn->next_in_queue) + if(!(___pn->atype & 2)) // if not in EntryList + break; + // Grant permission to fire to the processes in EntryList // Remove also from queue and wait list processes in EntryList for(___pa = ___p; ___pa; ___pa = ___pa->next_in_qelist) { // This loop does not affect 'qelist' (EntryList). - // However, it does affect 'queue' and 'wtlist'. - if(___pn == ___pa) // if ___pn will be removed from queued requests - ___pn = ___pn->next_in_queue; // select next queued request + // However, it does affect 'queue' and 'wtlist'. + //if(___pn == ___pa) // if ___pn will be removed from queued requests + // ___pn = ___pn->next_in_queue; // select next queued request ___send_permission_msg(___pa); ___remove_from_queue(___pa); // remove ___pa from queued requests ___remove_from_wtlist(___pa); Modified: newcodegen/plantCompiler.c =================================================================== --- newcodegen/plantCompiler.c 2011-04-08 22:36:44 UTC (rev 246) +++ newcodegen/plantCompiler.c 2011-05-11 12:20:38 UTC (rev 247) @@ -199,6 +199,7 @@ if(procArray[i]->thread) fprintf(plantFile,"\n#define ___THREAD\n"); else fprintf(plantFile,"\n#define ___PROCESS\n"); fprintf(plantFile,"#define ___NAME \"%s\"\n", procArray[i]->name); + fprintf(plantFile,"#define ___INSTANCE \"%s\"\n", procArray[i]->instance); // generate declarations/definitions incl = genDefineBlock(procArray[i], TrInfo[i]); Modified: pnheaders/Makefile =================================================================== --- pnheaders/Makefile 2011-04-08 22:36:44 UTC (rev 246) +++ pnheaders/Makefile 2011-05-11 12:20:38 UTC (rev 247) @@ -1,4 +1,4 @@ -COMPILER=gcc -g +COMPILER=gcc -g -I../spnbox generate: general.o matrix.o pns.o insert.o Modified: pnheaders/main_function.c =================================================================== --- pnheaders/main_function.c 2011-04-08 22:36:44 UTC (rev 246) +++ pnheaders/main_function.c 2011-05-11 12:20:38 UTC (rev 247) @@ -7,6 +7,9 @@ int inline is_verbose() { return verb; } + + + void br_filter(char *p) { // removes beginning and end braces int n; if(!p) @@ -31,16 +34,17 @@ return ! p[i]; } -int th_filter(char** ap) { // filters <thread> commands +int th_filter(char** ap, char* pattern) { // remove pattern from strings char* p = *ap, *p2 = 0; - int i; - if(!p) return 0; + int i, n; + if(!p || !pattern) return 0; + n = strlen(pattern); for(i = 0; p[i]; i++) { if(p[i] == ' ' || p[i] == '\t') continue; - if(!strncmp(p+i, "<thread>", 8)) { - if(!is_empty(p+i+8)) // else p2 remains equal to zero - asprintf(&p2, "%s", p+i+8); + if(!strncmp(p+i, pattern, n)) { + if(!is_empty(p+i+n)) // else p2 remains equal to zero + asprintf(&p2, "%s", p+i+n); free(*ap); *ap = p2; return 1; @@ -66,8 +70,15 @@ continue; br_filter(sp->process_array[i]->build); br_filter(sp->process_array[i]->include); - if(th_filter(&(sp->process_array[i]->build))) - sp->process_array[i]->thread = 1; + //if(th_filter(&(sp->process_array[i]->build))) + //sp->process_array[i]->thread = 1; + + // Is this a thread? + sp->process_array[i]->thread = th_filter(&(sp->process_array[i]->build),\ + "<thread>"); + // Is this a supervisor component? + sp->process_array[i]->supervisor=th_filter(&(sp->process_array[i]->build),\ + "<supervisor>"); pn = sp->process_array[i]->pn; if(pn) { if(pn->segment) @@ -87,23 +98,28 @@ int main(int na, char* argv[]) { - int i, j, l1, l2, UCcnt, UOcnt, *Tuc, *Tuo, *UClst, *UOlst; - int labelcount = 0, finish = 0; + int i, j, l1, l2, UCcnt, UOcnt, LVcnt, *Tuc, *Tuo, *Tlive, *UClst, *UOlst, *LVlst; + int labelcount = 0, finish = 0, plcnum, spcnum; char* input, *build; FILE* f; specs *sp; syncc *snc; - pns pn, *apnsv; + pns pn, pn1, *apnsv; + process **plant_array, **spv_array; matrix L, C, H; int *B; struct myinsert ins; - linenf_r lin_res; + linenf_r lin_res, lin_res2; + dp_p LVparams; + dp_r LVresult; struct synclist *syncl, *syncl2; struct sync_element *syn_el, *syn_el2; struct label_lst* lls; TrData** TInf; + // 1. INITIALIZATION + ins = InitInsert(512); // used to store command line parameters verb = 0; input = 0; @@ -168,11 +184,15 @@ return 0; } - // Call the translator + // 2. TRANSLATE SPECIFICATION sp = ScanInput(input); - if(!sp) // check translator result + + // 2.1. Check translator result + + if(!sp) return 1; + if(sp->process_num <= 0) { fprintf(stderr, "No processes defined! Nothing to do.\n"); dealloc_specs(sp); @@ -180,23 +200,40 @@ return 0; } - sp_filter(sp); // remove extra braces + sp_filter(sp); // detect settings and remove extra braces if(is_verbose() >= 3) { // For debugging for(i = 0; i < sp->process_num; i++) { printf("\n\n======================================================"); - printf("\nPROCESS NAME: %s\n", sp->process_array[i]->name); + if(sp->process_array[i]->supervisor) + printf("\nSUPERVISOR COMPONENT: "); + else if(sp->process_array[i]->thread) + printf("\nTHREAD NAME: "); + else + printf("\nPROCESS NAME: "); + printf("%s (%s)\n", sp->process_array[i]->instance, sp->process_array[i]->name); displaypn(*(sp->process_array[i]->pn), stdout); } } + for(i = 0; i < sp->process_num; i++) + if(!sp->process_array[i]->supervisor) + break; - // Label the PNs + if(i >= sp->process_num) { + fprintf(stderr, "No plant components defined! Nothing to do.\n"); + dealloc_specs(sp); + if(build) free(build); + return 0; + } + + // 2.2 Label the PNs + for(i = 0; i < sp->process_num; i++) updatepn(sp->process_array[i]->pn, "freelabel", &labelcount); - // Deal with synchronization constraints + // 2.2.1 Deal with synchronization constraints for(i = 1; i; ) /* i = 0 indicates when loop may end */ for(i = 0, snc = sp->synclist; snc; snc = snc->next) { @@ -208,7 +245,7 @@ } } - // Obtain SC specification. Currently: + // 2.3 Obtain SC specification. Currently: // extract the L, C, H, and b matrices (more complex specs to be done later) extractLHCB(sp, &pn, &L, &H, &C, &B); @@ -219,18 +256,23 @@ printLHCB(&pn, &L, &H, &C, B, -1, stdout); } - // Perform SC + // 3. SUPERVISORY CONTROL + // 3.1 Enforce SC specs (linear constraints supported currently) + Tuc = tcalloc(pn.tnum, sizeof(*Tuc)); Tuo = tcalloc(pn.tnum, sizeof(*Tuo)); + Tlive = tcalloc(pn.tnum, sizeof(*Tlive)); if(pn.t) for(i = 0; i < pn.tnum; i++) { Tuc[i] = pn.t[i].uncontrollable; Tuo[i] = pn.t[i].unobservable; + Tlive[i] = pn.t[i].live; } UCcnt = findIndices(Tuc, pn.tnum, sizeof(*Tuc), &UClst); UOcnt = findIndices(Tuo, pn.tnum, sizeof(*Tuo), &UOlst); + LVcnt = findIndices(Tlive, pn.tnum, sizeof(*Tlive), &LVlst); lin_res = linenf(&pn.out, &pn.in, &L, B, pn.marking, &H, &C, \ UCcnt, UClst, UOcnt, UOlst); @@ -241,64 +283,178 @@ printLHCB(&pn, &lin_res.Lf, 0, &lin_res.Cf, lin_res.bf, -1, stdout); } - free(Tuc); free(Tuo); free(UClst); free(UOlst); - // Check whether SC was successful if(strcmp(lin_res.how, "OK")) merror(0, "MAIN FUNCTION: SC has failed. Relax the specification\n\ such as by reducing the number of uncontrollable and unobservable transitions"); - // Enforce liveness + // 3.2. Enforce liveness - // no liveness enforcement at this time + // - Liveness enforcement is applied to the closed-loop + // - Check whether the initial marking satisfies the constraints. + // - The result of liveness enforcement is enforced on the closed-loop + // with linenf and no uncontro. and unobs. transitions, since the result + // is guaranteed to be admissible. + // - The supervisor is extracted from the closed-loop reported by linenf via + // getSupervisor - // Extract supervisor as a pn + // For future work: + // - calculate initial marking constraints: check marking constraints satisfied by initial marking of plant. + // - check if responsiveness is guaranteed. + // - To help convergence, invariants from previous constraints should be + // communicated by means of the L, B parameters of the function dp. + + if(LVcnt) { // If T-liveness enforcement has been requested + if(is_verbose() >= 3) { // For debugging + printf("\n\n======================================================"); + printf("\n\nLiveness enforcement has been requested. This may take a while ...\n"); + } + // Initialize parameters + memset(&LVparams, 0, sizeof(LVparams)); + LVparams.Dm = lin_res.Dfm; LVparams.Dp = lin_res.Dfp; + LVparams.Tuc = UClst; LVparams.TucCount = UCcnt; + LVparams.Tuo = UOlst; LVparams.TuoCount = UOcnt; + LVparams.IncludeT = LVlst; LVparams.IncludeCount = LVcnt; + LVparams.option = 12 + (is_verbose() >= 4); + + LVresult = dp(&LVparams); // apply the T-liveness enforcement procedure + if(strcmp(LVresult.how, "OK")) + merror(0, "MAIN FUNCTION: Liveness enforcement has failed. Relax the specification\nsuch as by reducing the number of uncontrollable and unobservable transitions.\nSee also the log file of the liveness enforcement algorithm."); + + // Verify L*m0 >= B + if(!TestLCB(&LVresult.Lf, lin_res.ms0, 0,0, GREATER_OR_EQUAL, LVresult.Bf)) + merror(0, "MAIN FUNCTION: Liveness enforcement has failed due to insufficient initial \nmarking (the initial marking does not satisfy the L*m >= B constraints). \nRelax the specification such as by increasing the initial marking and \nreducing the number of uncontrollable and unobservable transitions. See also \nthe log file of the liveness enforcement algorithm."); + + // Verify L0*m0 >= b0 + if(!TestLCB(&LVresult.L0f, lin_res.ms0,0,0,GREATER_OR_EQUAL, LVresult.B0f)) + merror(0, "MAIN FUNCTION: Liveness enforcement has failed due to insufficient initial \nmarking (the initial marking does not satisfy the L0*m >= B0 constraints). \nRelax the specification such as by increasing the initial marking and \nreducing the number of uncontrollable and unobservable transitions. See also \nthe log file of the liveness enforcement algorithm."); + + // Convert L*m >= B to L*m <= B (the input expected by linenf) + InvertSignOfMatrix(&LVresult.Lf); // L = -L + InvertSignOfVector(LVresult.Bf, NumberOfRows(LVresult.Lf)); // B = -B + + lin_res2 = linenf(&lin_res.Dfm, &lin_res.Dfp, &LVresult.Lf, LVresult.Bf,\ + lin_res.ms0, 0, 0, 0, 0, 0, 0); + // no uncontr. and unobs. transitions have to be passed to linenf + // since constraints are admissible + + DeallocateDp(&LVresult); DeallocateLinenf(&lin_res); + + lin_res = lin_res2; + } + + free(Tuc); free(Tuo); free(Tlive); free(UClst); free(UOlst); free(LVlst); + + // 3.3 Extract supervisor as a pn + apnsv = getSupervisor(&pn, &lin_res.Dfm, &lin_res.Dfp, lin_res.ms0); if(is_verbose() >= 3) { // For debugging printf("\n\n======================================================"); - printf("\nCOMPOSED PN\n"); + printf("\nCOMPOSED PLANT PN PLUS PREDEFINED SUPERVISOR COMPONENTS\n"); displaypn(pn, stdout); printf("\n\n======================================================"); if(apnsv) { - printf("\nSUPERVISOR PN\n"); + printf("\nSC GENERATED SUPERVISOR\n"); displaypn(*apnsv, stdout); } else - printf("\nNO SUPERVISOR PN\n"); + printf("\nNO SC GENERATED SUPERVISOR\n"); } deallocpn(&pn); - // need functions to free linenf_r structures and similar structures - // Generate code + // 4. GENERATE CODE + // 4.1 Separate supervisor components from plant components + spv_array = tcalloc(sp->process_num, sizeof(*spv_array)); + plant_array = tcalloc(sp->process_num, sizeof(*plant_array)); + for(i = 0, plcnum = 0, spcnum = 0; i < sp->process_num; i++) { + if(sp->process_array[i]->supervisor) { + spv_array[spcnum] = sp->process_array[i]; + spcnum++; + } + else { + plant_array[plcnum] = sp->process_array[i]; + plcnum++; + } + } - // Obtain also a synclist structure with the sync data + // 4.2 Compose supervisor components with SC generated supervisor. + + pn = pn_composition(spv_array, spcnum); + pn1 = composepn(apnsv, &pn); + if(apnsv) + free(apnsv); + deallocpn(&pn); // free intermediary result + apnsv = &pn1; + + if(is_verbose() >= 3 && spcnum) { + // If spcnum != 0, then SC supervisor and final supervisor are different. + printf("\n\n======================================================"); + if(apnsv) { + printf("\nFINAL SUPERVISOR\n"); + displaypn(*apnsv, stdout); + } + } + + // 4.3 Obtain a synclist structure with the sync data for plant processes + + /* May be deleted after testing the change lls = get_label_list(sp->process_array, sp->process_num); syncl = get_synclist(lls, sp->process_array); TInf = get_TrData(apnsv, sp->process_array, sp->process_num, lls); + */ - //exit(1); + lls = get_label_list(plant_array, plcnum); + syncl = get_synclist(lls, plant_array); + TInf = get_TrData(apnsv, plant_array, plcnum, lls); - CodeGenerator(apnsv, sp->name, sp->process_array, sp->process_num,\ + // Call the code generation function + + /*CodeGenerator(apnsv, sp->name, sp->process_array, sp->process_num, \ syncl, TInf, build); + */ - // Free memory + CodeGenerator(apnsv, sp->name, plant_array, plcnum, syncl, TInf, build); + + // 5. TERMINATE + if(apnsv) { deallocpn(apnsv); - free(apnsv); + //free(apnsv); } + free(plant_array); + free(spv_array); dealloc_specs(sp); if(build) free(build); free_label_list(lls); free_synclist(syncl); - free_TrData(TInf, sp->process_num); + free_TrData(TInf, plcnum); return 0; } + + +/* Future improvements for deadlock prevention. + + Currently deadlock prevention does not account for determinism. Thus, + some potential deadlocks may remain undetected. + + The following function could be defined in the future to help the deadlock + prevention procedure converge. Additionally, a function for initial + markings could be developed. + +matrix getLB(matrix Lf, matrix Cf, int *Bf, int** B) { + // Outputs a matrix L such that L*m <= B contains the rows of + // Lf*m + Cf*v <= Bf on which Cf is zero. B is also allocated and + // initialized. + +} + +*/ Modified: pnheaders/matrix.c =================================================================== --- pnheaders/matrix.c 2011-04-08 22:36:44 UTC (rev 246) +++ pnheaders/matrix.c 2011-05-11 12:20:38 UTC (rev 247) @@ -452,6 +452,89 @@ +inline int TestCondition(int v, int type, int w) { +/* Checks whether 'v' and 'w' (in this order) are in the relationship + described by 'type', where 'type' may have one of the values in the + range GREATER, ..., LESS. If the relationship is satisfied, the + function returns 1. Else, it returns 0. */ + + int a, b; + + if(type < 0) { + type = -type; + a = v; + b = w; + } + else { + a = w; + b = v; + } + switch(type) { + case GREATER: + if(a >= b) + return 0; + break; + case GREATER_OR_EQUAL: + if(a > b) + return 0; + break; + case EQUAL: + if(a != b) + return 0; + break; + default: + return 0; + } + return 1; +} + +int TestExpression(const int* v, int c, const int* w, int len) { +/* The vectors 'v' and 'w' are compared for the first 'len' elements. + 'c' may have one of the values in the range GREATER, ..., LESS. + The return value is as follows: + * If 'len' <= 0 or v = 0 or w = 0 the function returns a nonzero value; + * Else if 'c' is none of the above, the function returns zero; + * Else if the expression is satisfied for each pair of elements v[i] and + w[i], the function returns a nonzero value; + * Else the function returns zero. */ + + const int *a, *b; + int i; + + if(!v || !w || len <= 0) + return 1; + if(c < 0) { + a = v; + b = w; + c = -c; + } + else { + a = w; + b = v; + } + switch(c) { + case GREATER: + for(i = 0; i < len; i++) + if(a[i] >= b[i]) + return 0; + break; + case GREATER_OR_EQUAL: + for(i = 0; i < len; i++) + if(a[i] > b[i]) + return 0; + break; + case EQUAL: + for(i = 0; i < len; i++) + if(a[i] != b[i]) + return 0; + break; + default: + return 0; + } + return 1; +} + + void free2Darray(int** ar, int nr) { /* Used to deallocate an array created with matrix2array or vector2array; nr is the number of rows */ @@ -501,7 +584,23 @@ memset(m, 0, sizeof(*m)); } +inline void InvertSignOfMatrix(matrix* m) { + int i, j, r, n; + if(!m) return; + r = NumberOfRows(*m); + n = NumberOfColumns(*m); + for(i = 0; i < r; i++) + for(j = 0; j < n; j++) + SetMatrixEl(m, i, j, -GetMatrixEl(m, i, j)); +} +inline void InvertSignOfVector(int* v, int len) { + int i; + if(!v) return; + for(i = 0; i < len; i++) + v[i] = -v[i]; +} + /* To do: - _setmatrel3 does not deallocate elements set to zero - consider better matrix representations. For instance, for type 3 Modified: pnheaders/matrix.h =================================================================== --- pnheaders/matrix.h 2011-04-08 22:36:44 UTC (rev 246) +++ pnheaders/matrix.h 2011-05-11 12:20:38 UTC (rev 247) @@ -127,6 +127,9 @@ int** matrix2array(matrix m); /* Converts a matrix object to an array of integers: result[i][j] = elem(i,j)*/ +void free2Darray(int** ar, int nr); +/* Use to deallocate an array created with matrix2array or vector2array; nr is the number of rows */ + int findIndices(void* vect, int n, int esize, int** answer ); /* Finds the indices of the nonzero elements of 'vect'. Here, 'vect' is a vector of 'n' elements. Each element of 'vect' has the size 'esize'. The @@ -137,7 +140,35 @@ This function is similar to the find function of Matlab. */ -void free2Darray(int** ar, int nr); -/* Use to deallocate an array created with matrix2array or vector2array; nr is the number of rows */ +// Changes in the following can affect TestCondition and TestExpression ! +#define GREATER 2 +#define GREATER_OR_EQUAL 1 +#define EQUAL 0 +#define LESS_OR_EQUAL -1 +#define LESS -2 +inline int TestCondition(int v, int type, int w); +/* Checks whether 'v' and 'w' (in this order) are in the relationship + described by 'type', where 'type' may have one of the values in the + range GREATER, ..., LESS. If the relationship is satisfied, the + function returns 1. Else, it returns 0. */ + +int TestExpression(const int* v, int c, const int* w, int len); +/* The vectors 'v' and 'w' are compared for the first 'len' elements. + 'c' may have one of the values in the range GREATER, ..., LESS above. + The return value is as follows: + * If 'len' <= 0 or v = 0 or w = 0 the function returns a nonzero value; + * Else if 'c' is none of the above, the function returns zero; + * Else if the expression is satisfied for each pair of elements v[i] and + w[i], the function returns a nonzero value; + * Else the function returns zero. */ + +inline void InvertSignOfMatrix(matrix* m); /* m = -m */ + +inline void InvertSignOfVector(int* v, int len); /* v = -v */ + + +// matrixmath.h and extendedmatrix.h of spnbox have additional matrix functions + + #endif Modified: pnheaders/pns.c =================================================================== --- pnheaders/pns.c 2011-04-08 22:36:44 UTC (rev 246) +++ pnheaders/pns.c 2011-05-11 12:20:38 UTC (rev 247) @@ -4,8 +4,8 @@ ****************************************************************************/ #include"pns.h" +#include"matrixmath.h" - void d2dd(const matrix* D, matrix* Dm, matrix* Dp) { int i, j, nr, nc; mtype x; @@ -525,41 +525,18 @@ -pns copypn(pns *src) { - pns dst; +inline pns _copytrans(pns dst, pns *src) { + /* This is a subroutine of copypn and composepn for copying transitions + and arcs from src to dst. */ + + int i; arcs *pa; const arcs *pb; struct placelist *pd; const struct placelist *ps; - int i; - dst = createpn("pnum tnum mDm mDp", src->pnum, src->tnum, src->out, src->in); - if(src->marking) updatepn(&dst, "m0", src->marking); - if(src->C) updatepn(&dst, "C", src->C); - if(src->place_name) - for(i = 0; i < src->pnum; i++) - if(src->place_name[i]) - updatepn(&dst, "place_name", i, src->place_name[i]); - if(src->segment) - for(i = 0; i < src->pnum; i++) - if(src->segment[i]) - updatepn(&dst, "segment", i, src->segment[i]); - if(src->select) - for(i = 0; i < src->pnum; i++) - if(src->select[i]) - updatepn(&dst, "select", i, src->select[i]); - if(src->trans_name) - for(i = 0; i < src->tnum; i++) - if(src->trans_name[i]) - updatepn(&dst, "trans_name", i, src->trans_name[i]); if(src->t) { - dst.t = tcalloc(dst.tnum, sizeof(src->t[0])); - for(i = 0; i < src->tnum; i++) - dst.t[i] = src->t[i]; + dst.t = tcalloc(src->tnum, sizeof(src->t[0])); + memcpy(dst.t, src->t, (src->tnum)*sizeof(src->t[0])); } - if(src->p) { - dst.p = tcalloc(dst.pnum, sizeof(src->p[0])); - for(i = 0; i < src->pnum; i++) - dst.p[i] = src->p[i]; - } if(src->arc_list) { /* copy the list of arcs */ dst.arc_list = tcalloc(dst.tnum, sizeof(*(dst.arc_list))); for(i = 0; i < src->tnum; i++) { @@ -592,7 +569,39 @@ } +pns copypn(pns *src) { + pns dst; + int i; + dst = createpn("pnum tnum mDm mDp", src->pnum, src->tnum, src->out, src->in); + if(src->marking) updatepn(&dst, "m0", src->marking); + if(src->C) updatepn(&dst, "C", src->C); + if(src->place_name) + for(i = 0; i < src->pnum; i++) + if(src->place_name[i]) + updatepn(&dst, "place_name", i, src->place_name[i]); + if(src->segment) + for(i = 0; i < src->pnum; i++) + if(src->segment[i]) + updatepn(&dst, "segment", i, src->segment[i]); + if(src->select) + for(i = 0; i < src->pnum; i++) + if(src->select[i]) + updatepn(&dst, "select", i, src->select[i]); + if(src->trans_name) + for(i = 0; i < src->tnum; i++) + if(src->trans_name[i]) + updatepn(&dst, "trans_name", i, src->trans_name[i]); + if(src->p) { + dst.p = tcalloc(dst.pnum, sizeof(src->p[0])); + for(i = 0; i < src->pnum; i++) + dst.p[i] = src->p[i]; + } + return _copytrans(dst, src); +} + + + void deallocpn(pns *pn) { int i, pnum, tnum; pnum = pn->pnum; @@ -812,17 +821,21 @@ /* Next we deal with the case when pn1 or pn2 does not have transitions */ if(!nt1 || !nt2) { - if(!nt1) { /* if pn1 does not have transitions */ - if(pn2->t) { /* if pn2 has transitions and transition information */ - pn.t = tcalloc(pn.tnum,sizeof(pn.t[0])); - memcpy(pn.t, pn2->t, nt2*sizeof(pn.t[0])); /* copy info */ - } - } + if(!nt1) /* if pn1 does not have transitions */ + pn = _copytrans(pn, pn2); // copies transitions and trans arcs to pn else /* if pn2 does not have transitions */ - if(pn1->t) { /* if pn1 has transitions and transition information */ - pn.t = tcalloc(pn.tnum,sizeof(pn.t[0])); - memcpy(pn.t, pn1->t, nt1*sizeof(pn.t[0])); /* copy info */ + pn = _copytrans(pn, pn1); + // Copy also input/output matrix elements + for(j = 0; j < nt1; j++) + if(np1) { + Copy2ZeroColumn(&(pn1->in),j,&(pn.in),j,0); + Copy2ZeroColumn(&(pn1->out),j,&(pn.out),j,0); } + for(j = 0; j < nt2; j++) + if(np2) { + Copy2ZeroColumn(&(pn2->in),j,&(pn.in),j,np1); + Copy2ZeroColumn(&(pn2->out),j,&(pn.out),j,np1); + } return pn; } @@ -910,6 +923,34 @@ } + +pns pn_composition(process** process_array, int num) { + /* Composes the PNs in the process array and returns the result. */ + pns pn, pn1, *apn; + int i; + + if(num <= 0 || !process_array) + memset(&pn, 0, sizeof(pn)); // return null pn + else if(num == 1) + pn = copypn(process_array[0]->pn); + else { + apn = process_array[0]->pn; + for(i = 1; i < num; i++) { + if(i > 1) { + pn1 = pn; // save intermediary result for subsequent deallocation + apn = &pn1; + } + pn = composepn(apn, process_array[i]->pn); + if(i > 1) + deallocpn(&pn1); // free intermediary result + } + } + + return pn; +} + + + int isfreelabeled(pns *rpn) { int i, j, label; @@ -1175,9 +1216,9 @@ /* This is a temporary implementation; future work should take in account that sp can contain more general specifications */ -/* The implementation assumes that each pn is free labeled and that no disjunctive - constraints are present. */ +/* The implementation assumes that no disjunctive constraints are present. */ + int find_var_index(variable* var, pns* pn, specs* sp) { int i, k; int lab; @@ -1199,7 +1240,7 @@ merror(0, "EXTRACTLHCB: index %d >= tran. number (%d)", var->index, var->pn->tnum); lab = var->pn->t[var->index].l; for(i = 0; i < pn->tnum; i++) - if(pn->t[i].l == lab) + if(pn->t[i].l == lab) // Assumes free-labeled PN return i; merror(0, "EXTRACTLHCB: Variable does not match specified PNs"); } @@ -1215,6 +1256,9 @@ /* Find the composed PN */ + *pn = pn_composition(sp->process_array, sp->process_num); + + /* May be deleted after testing pn_composition above if(sp->process_num == 1) *pn = copypn(sp->process_array[0]->pn); else { @@ -1229,6 +1273,7 @@ deallocpn(&pn1); // dealloc intermediary result } } + */ /* Find cnum, the number of constraints */ for(c = sp->constraint_list, cnum = 0; c; c = c->next, cnum++); @@ -1238,7 +1283,10 @@ AllocateMatrixType(3, L, cnum, pn->pnum); AllocateMatrixType(3, H, cnum, pn->tnum); AllocateMatrixType(3, C, cnum, pn->tnum); - *B = tcalloc(cnum, sizeof(**B)); + if(!cnum) + *B = 0; + else + *B = tcalloc(cnum, sizeof(**B)); /* Initialize L, H, C, B */ @@ -1361,6 +1409,55 @@ } /*************************************************************************** + TestLCB +****************************************************************************/ + +int TestLCB(matrix* L, int* m, matrix* C, int* v, int type, int* B) { + +/* 'type' should be GREATER, LESS, EQUAL, GREATER_OR_EQUAL, or LESS_OR_EQUAL + (which are defined in matrix.h). + + The function calculates L*m + C*v and compares the result to B. + If all elements of the result satisfy the 'type' constraint when compared + to B, then the function returns 1. Otherwise, it returns zero. + + Unused entries may be set to zero. For instance, TestLCB(L,m,0,0,LESS,B,n) + checks whether L*m < B. */ + + int i, a, n; + char zL, zC; + + if(n <= 0) + return 1; + + zL = !L || !m; + zC = !C || !v; + + if(!zL) zL = zL || ! NumberOfRows(*L) || ! NumberOfColumns(*L); + if(!zC) zC = zC || ! NumberOfRows(*C) || ! NumberOfColumns(*C); + + if(!B || (zL && zC)) + return zL && zC && !B; + + if(!zL) + n = NumberOfRows(*L); + else + n = NumberOfRows(*C); + + for(i = 0; i < n; i++) { + a = 0; + if(!zL) + a = MultiplyVector(L, (matrix*) m, i, -1, 0); + if(!zC) + a += MultiplyVector(C, (matrix*) v, i, -1, 0); + if(!TestCondition(a, type, B[i])) + return 0; + } + return 1; +} + + +/*************************************************************************** GETSUPERVISOR ****************************************************************************/ @@ -1370,7 +1467,13 @@ closed-loop input (Dcp) and output (Dcm) matrices and from the initial marking of the closed-loop (ms0). - This function assumes free-labeled PNs. */ + This function assumes that the set of transitions of the closed-loop is + the same as the set of transitions of the plant. Two cases in which + this is true are the following: + - free-labeled closed-loop PN. + - the supervisor implements Lm + Hq + Cv \leq b via SBPI. (Since SBPI does + not add new transitions). +*/ pns *apnsv; int tnum, i, j, k, l, t, pcn, tcn, flag, *labels; @@ -1750,7 +1853,12 @@ } +//========================================================================= + +int TestConstraint(); + + /* Things to do: - composepn ignores the text fields of the pns. - composepn assumes that the places in the two pns are distinct. Modified: pnheaders/pns.h =================================================================== --- pnheaders/pns.h 2011-04-08 22:36:44 UTC (rev 246) +++ pnheaders/pns.h 2011-05-11 12:20:38 UTC (rev 247) @@ -359,6 +359,7 @@ int type:1; /* type = 1 indicates an external process */ int start:1; /* start = 1 if the supervisor should start this process */ char thread:1; /* set to 1 if process should be implemented as a thread */ + char supervisor:1; /* set to 1 if the process is a supervisor component */ } process; @@ -388,14 +389,37 @@ use n < 0. The pn parameter specifies the PN on which the constraints are defined. If one or more of L, H, or C is unavailable, enter 0. */ +int TestLCB(matrix* L, int* m, matrix* C, int* v, int type, int* B); +/* 'type' should be GREATER, LESS, EQUAL, GREATER_OR_EQUAL, or LESS_OR_EQUAL + (which are defined in matrix.h). + + The function calculates L*m + C*v and compares the result to B. + If all elements of the result satisfy the 'type' constraint when compared + to B, then the function returns 1. Otherwise, it returns zero. + + Unused entries may be set to zero. For instance, TestLCB(L,m,0,0,LESS,B,n) + checks whether L*m < B. */ + + +pns pn_composition(process** process_array, int num); +/* Composes the PNs in the process array and returns the result. */ + + pns* getSupervisor(pns* pn, matrix* Dcm, matrix* Dcp, int* ms0); /* Extracts the PN representing the supervisor from the plant PN (pn), the closed-loop input (Dcp) and output (Dcm) matrices and from the initial - marking of the closed-loop (ms0). This function assumes free-labeled PNs. */ + marking of the closed-loop (ms0). + This function assumes that the set of transitions of the closed-loop is + the same as the set of transitions of the plant. Two cases in which + this is true are the following: + - free-labeled closed-loop PN. + - the supervisor implements Lm + Hq + Cv \leq b via SBPI. (Since SBPI does + not add new transitions). */ + void dealloc_specs(specs* sp); void dealloc_process(process* p); Modified: spnbox/linenf.c =================================================================== --- spnbox/linenf.c 2011-04-08 22:36:44 UTC (rev 246) +++ spnbox/linenf.c 2011-05-11 12:20:38 UTC (rev 247) @@ -670,7 +670,7 @@ } } /*If m0 is given, b must be given*/ - if(m0 && ! b) + if(m0 && ! b && Constraints) { merror(0, "LINENF: The constraint vector b must be given if an initial marking m0 is given"); return -1; Modified: spnbox/spnbox.h =================================================================== --- spnbox/spnbox.h 2011-04-08 22:36:44 UTC (rev 246) +++ spnbox/spnbox.h 2011-05-11 12:20:38 UTC (rev 247) @@ -702,7 +702,7 @@ array. -Written for Matlab by Marian V. Iordache, mio...@nd... +Written for Matlab by Marian V. Iordache Original Matlab code extended the Matlab pn2acpn code written on M. Iordache -- Sep. 4, 2000 and revised on Oct. 24, 2001 @@ -1192,7 +1192,7 @@ /* GCDV greatest common divisor of a vector/matrix. Uses GCD. -Written by Marian V. Iordache, mio...@nd... +Written by Marian V. Iordache C Usage: If m is a null pointer, the function returns the gcd of the row and column This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |